Merge branch 'dev' into test

This commit is contained in:
Joan Sanchez 2019-01-21 11:46:59 +01:00
commit 1ed63de3b9
156 changed files with 7148 additions and 1886 deletions

View File

@ -64,7 +64,7 @@ let actions = {
},
selectModule: function(moduleName, done) {
this.waitToClick(`body > vn-app > vn-vertical > vn-vertical > vn-home > div > div > a[ui-sref="${moduleName}.index"]`)
this.waitToClick(`vn-home a[ui-sref="${moduleName}.index"]`)
.waitForURL(moduleName)
.then(done)
.catch(done);

View File

@ -104,7 +104,7 @@ export default {
phoneInput: `${components.vnTextfield}[name="phone"]`,
mobileInput: `${components.vnTextfield}[name="mobile"]`,
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-icon-button[icon="star_border"]',
secondMakeDefaultStar: 'vn-client-address-index vn-card vn-horizontal:nth-child(3) vn-icon-button[icon="star_border"]',
firstEditButton: `vn-client-address-index vn-icon-button[icon='edit']`,
secondEditButton: `vn-client-address-index vn-horizontal:nth-child(3) vn-icon-button[icon='edit']`,
activeCheckbox: `vn-check[label='Enabled'] > label > input`,
@ -261,12 +261,12 @@ export default {
submitBotanicalButton: `${components.vnSubmit}`
},
itemSummary: {
basicData: `vn-item-summary vn-vertical[name="basicData"]`,
vat: `vn-item-summary vn-vertical[name="tax"]`,
tags: `vn-item-summary vn-vertical[name="tags"]`,
niche: `vn-item-summary vn-vertical[name="niche"]`,
botanical: `vn-item-summary vn-vertical[name="botanical"]`,
barcode: `vn-item-summary vn-vertical[name="barcode"]`
basicData: `vn-item-summary [name="basicData"]`,
vat: `vn-item-summary [name="tax"]`,
tags: `vn-item-summary [name="tags"]`,
niche: `vn-item-summary [name="niche"]`,
botanical: `vn-item-summary [name="botanical"]`,
barcode: `vn-item-summary [name="barcode"]`
},
itemDiary: {
thirdTicketId: 'vn-item-diary > vn-vertical > vn-card > div > vn-vertical > vn-table > div > vn-tbody > vn-tr:nth-child(3) > vn-td:nth-child(2) > span',
@ -275,14 +275,14 @@ export default {
warehouseAutocomplete: 'vn-item-diary vn-autocomplete[field="$ctrl.warehouseFk"]',
},
ticketSummary: {
sale: 'vn-ticket-summary > vn-card > div > vn-vertical > vn-horizontal:nth-child(3) > vn-one > table > tbody > tr',
firstSaleItemId: 'vn-ticket-summary > vn-card > div > vn-vertical > vn-horizontal:nth-child(3) > vn-one > table > tbody > tr > td:nth-child(2) > span',
popoverDiaryButton: 'vn-ticket-summary > vn-item-descriptor-popover vn-item-descriptor vn-icon[icon="icon-transaction"]',
firstSaleQuantity: 'vn-ticket-summary > vn-card > div > vn-vertical > vn-horizontal:nth-child(3) > vn-one > table > tbody > tr > td:nth-child(4)',
firstSaleDiscount: 'vn-ticket-summary > vn-card > div > vn-vertical > vn-horizontal:nth-child(3) > vn-one > table > tbody > tr > td:nth-child(6)'
sale: 'vn-ticket-summary [name="sales"] table > tbody > tr',
firstSaleItemId: 'vn-ticket-summary [name="sales"] table > tbody > tr > td:nth-child(2) > span',
popoverDiaryButton: 'vn-ticket-summary vn-item-descriptor-popover vn-item-descriptor vn-icon[icon="icon-transaction"]',
firstSaleQuantity: 'vn-ticket-summary [name="sales"] table > tbody > tr > td:nth-child(4)',
firstSaleDiscount: 'vn-ticket-summary [name="sales"] table > tbody > tr > td:nth-child(6)'
},
ticketsIndex: {
newTicketButton: 'body > vn-app > vn-vertical > vn-vertical > ui-view > vn-ticket-index > a',
newTicketButton: 'vn-ticket-index > a',
searchResult: `vn-ticket-index vn-card > div > vn-table > div > vn-tbody > a.vn-tr`,
searchResultDate: `vn-ticket-index vn-table vn-tbody > a:nth-child(1) > vn-td:nth-child(4)`,
searchResultAddress: `vn-ticket-index vn-table vn-tbody > a:nth-child(1) > vn-td:nth-child(6)`,

View File

@ -35,34 +35,34 @@ describe('Item summary path', () => {
it(`should check the item summary preview shows fields from basic data`, async() => {
const result = await nightmare
.waitForTextInElement(selectors.itemSummary.basicData, 'Name: Object1 Gem1 5')
.waitForTextInElement(selectors.itemSummary.basicData, 'Object1 Gem1 5')
.waitToGetProperty(selectors.itemSummary.basicData, 'innerText');
expect(result).toContain('Name: Object1 Gem1 5');
expect(result).toContain('Object1 Gem1 5');
});
it(`should check the item summary preview shows fields from tags`, async() => {
const result = await nightmare
.waitForTextInElement(selectors.itemSummary.tags, 'Color: Yellow')
.waitForTextInElement(selectors.itemSummary.tags, 'Yellow')
.waitToGetProperty(selectors.itemSummary.tags, 'innerText');
expect(result).toContain('Color: Yellow');
expect(result).toContain('Yellow');
});
it(`should check the item summary preview shows fields from niche`, async() => {
const result = await nightmare
.waitForTextInElement(selectors.itemSummary.niche, 'Warehouse One: A1')
.waitForTextInElement(selectors.itemSummary.niche, 'A1')
.waitToGetProperty(selectors.itemSummary.niche, 'innerText');
expect(result).toContain('Warehouse One: A1');
expect(result).toContain('A1');
});
it(`should check the item summary preview shows fields from botanical`, async() => {
const result = await nightmare
.waitForTextInElement(selectors.itemSummary.botanical, 'Botanical: Hedera helix')
.waitForTextInElement(selectors.itemSummary.botanical, 'Hedera helix')
.waitToGetProperty(selectors.itemSummary.botanical, 'innerText');
expect(result).toContain('Botanical: Hedera helix');
expect(result).toContain('Hedera helix');
});
it(`should check the item summary preview shows fields from barcode`, async() => {
@ -83,7 +83,7 @@ describe('Item summary path', () => {
it('should search for other item', async() => {
const result = await nightmare
.clearInput('body > vn-app > vn-vertical > vn-vertical > ui-view > vn-item-index > div > div > vn-card:nth-child(1) > div > vn-searchbar > form > vn-horizontal > vn-textfield > div > div > div.infix > input')
.clearInput('vn-item-index vn-searchbar input')
.click(selectors.itemsIndex.searchButton)
.type(selectors.itemsIndex.searchItemInput, 'Object2 Gem2 3')
.click(selectors.itemsIndex.searchButton)
@ -109,34 +109,34 @@ describe('Item summary path', () => {
it(`should now check the item summary preview shows fields from basic data`, async() => {
const result = await nightmare
.waitForTextInElement(selectors.itemSummary.basicData, 'Name: Object2 Gem2 3')
.waitForTextInElement(selectors.itemSummary.basicData, 'Object2 Gem2 3')
.waitToGetProperty(selectors.itemSummary.basicData, 'innerText');
expect(result).toContain('Name: Object2 Gem2 3');
expect(result).toContain('Object2 Gem2 3');
});
it(`should now check the item summary preview shows fields from tags`, async() => {
const result = await nightmare
.waitForTextInElement(selectors.itemSummary.tags, 'Color: Red')
.waitForTextInElement(selectors.itemSummary.tags, 'Red')
.waitToGetProperty(selectors.itemSummary.tags, 'innerText');
expect(result).toContain('Color: Red');
expect(result).toContain('Red');
});
it(`should now check the item summary preview shows fields from niche`, async() => {
const result = await nightmare
.waitForTextInElement(selectors.itemSummary.niche, 'Warehouse One: A4')
.waitForTextInElement(selectors.itemSummary.niche, 'A4')
.waitToGetProperty(selectors.itemSummary.niche, 'innerText');
expect(result).toContain('Warehouse One: A4');
expect(result).toContain('A4');
});
it(`should now check the item summary preview shows fields from botanical`, async() => {
const result = await nightmare
.waitForTextInElement(selectors.itemSummary.botanical, 'Botanical: -')
.waitForTextInElement(selectors.itemSummary.botanical, '-')
.waitToGetProperty(selectors.itemSummary.botanical, 'innerText');
expect(result).toContain('Botanical: -');
expect(result).toContain('-');
});
it(`should now check the item summary preview shows fields from barcode`, async() => {
@ -166,31 +166,31 @@ describe('Item summary path', () => {
it(`should check the item summary shows fields from basic data section`, async() => {
const result = await nightmare
.waitForTextInElement(selectors.itemSummary.basicData, 'Name: Object2 Gem2 3')
.waitForTextInElement(selectors.itemSummary.basicData, 'Object2 Gem2 3')
.waitToGetProperty(selectors.itemSummary.basicData, 'innerText');
expect(result).toContain('Name: Object2 Gem2 3');
expect(result).toContain('Object2 Gem2 3');
});
it(`should check the item summary shows fields from tags section`, async() => {
const result = await nightmare
.waitToGetProperty(selectors.itemSummary.tags, 'innerText');
expect(result).toContain('Color: Red');
expect(result).toContain('Red');
});
it(`should check the item summary shows fields from niches section`, async() => {
const result = await nightmare
.waitToGetProperty(selectors.itemSummary.niche, 'innerText');
expect(result).toContain('Warehouse One: A4');
expect(result).toContain('One A4');
});
it(`should check the item summary shows fields from botanical section`, async() => {
const result = await nightmare
.waitToGetProperty(selectors.itemSummary.botanical, 'innerText');
expect(result).toContain('Botanical: -');
expect(result).toContain('-');
});
it(`should check the item summary shows fields from barcodes section`, async() => {

View File

@ -214,7 +214,7 @@ describe('Ticket Edit sale path', () => {
.wait(selectors.claimBasicData.claimStateAutocomplete)
.parsedUrl();
expect(url.hash).toEqual('#!/claim/6/basic-data');
expect(url.hash).toEqual('#!/claim/5/basic-data');
});
it('should click on the Claims button of the top bar menu', async() => {

View File

@ -2,21 +2,84 @@
<vn-horizontal class="header">
<vn-auto>
<vn-icon icon="keyboard_arrow_left" class="pointer"
ng-click="$ctrl.movePrevious()"
ng-click="$ctrl.movePrevious($ctrl.skip)"
ng-show="$ctrl.displayControls"
</vn-icon>
</vn-auto>
<vn-one>
<strong>{{$ctrl.defaultDate | date: 'dd/MM/yyyy'}}</strong>
<strong>
<span translate>{{$ctrl.defaultDate | date: 'MMMM'}}</span>
<span>{{$ctrl.defaultDate | date: 'yyyy'}}</span>
</strong>
</vn-one>
<vn-auto>
<vn-icon icon="keyboard_arrow_right" class="pointer"
ng-click="$ctrl.moveNext()"
ng-click="$ctrl.moveNext($ctrl.skip)"
ng-show="$ctrl.displayControls"
</vn-icon>
</vn-auto>
</vn-horizontal>
<vn-horizontal class="body">
<section ng-repeat="day in $ctrl.days" class="day {{day.color}}" ng-click="$ctrl.select($index)">
<span>{{::day.number}}</span>
<vn-horizontal>
<!-- <vn-auto>
<vn-vertical class="body">
<section class="day">
<span></span>
</section>
<section class="day">
<span>1</span>
</section>
<section class="day">
<span>2</span>
</section>
<section class="day">
<span>3</span>
</section>
<section class="day">
<span>4</span>
</section>
<section class="day">
<span>5</span>
</section>
<section class="day">
<span>6</span>
</section>
</vn-vertical>
</vn-auto>
<vn-one> -->
<vn-vertical class="body">
<vn-horizontal class="weekdays">
<section class="day" ng-click="$ctrl.selectAll(1)">
<span>L</span>
</section>
<section class="day" ng-click="$ctrl.selectAll(2)">
<span>M</span>
</section>
<section class="day" ng-click="$ctrl.selectAll(3)">
<span>X</span>
</section>
<section class="day" ng-click="$ctrl.selectAll(4)">
<span>J</span>
</section>
<section class="day" ng-click="$ctrl.selectAll(5)">
<span>V</span>
</section>
<section class="day" ng-click="$ctrl.selectAll(6)">
<span>S</span>
</section>
<section class="day" ng-click="$ctrl.selectAll(0)">
<span>D</span>
</section>
</vn-horizontal>
<vn-horizontal class="days">
<section ng-repeat="day in $ctrl.days" class="day {{day.color}}"
ng-click="$ctrl.select($index)">
<span ng-if="day.event" vn-tooltip="{{day.event.title}}">
{{::day.date | date: 'd'}}
</span>
<span ng-if="!day.event">{{::day.date | date: 'd'}}</span>
</section>
</vn-horizontal>
</vn-vertical>
</vn-one>
</vn-horizontal>
</div>

View File

@ -9,8 +9,10 @@ import './style.scss';
export default class Calendar extends Component {
constructor($element, $scope) {
super($element, $scope);
this.events = [];
this.defaultDate = new Date();
this.displayControls = true;
this.skip = 1;
}
get defaultDate() {
@ -19,67 +21,218 @@ export default class Calendar extends Component {
set defaultDate(value) {
this._defaultDate = value;
this.buildDays();
this.repaint();
}
get lastDay() {
let year = this.defaultDate.getYear();
// Month starts from zero, so we increment one month
let month = this.defaultDate.getMonth() + 1;
return new Date(year, month, 0).getDate();
get currentMonth() {
return this.defaultDate;
}
buildDays() {
let firstMonthDay = new Date(this.defaultDate);
firstMonthDay.setDate(1);
get events() {
return this._events;
}
let weekday = firstMonthDay.getDay();
set events(value) {
if (!value) return;
let year = this.defaultDate.getYear();
let month = this.defaultDate.getMonth();
let previousLastMonthDay = new Date(year, month, 0);
value.map(event => {
event.date = new Date(event.date);
});
this._events = value;
if (value.length && this.defaultDate)
this.repaint();
}
get nextMonth() {
const newDate = new Date(this.currentMonth);
newDate.setMonth(this.currentMonth.getMonth() + 1);
return newDate;
}
get previousMonth() {
const newDate = new Date(this.currentMonth);
newDate.setMonth(this.currentMonth.getMonth() - 1);
return newDate;
}
/**
* Returns first day of month from a given date
*
* @param {Date} date - Origin date
* @return {Integer}
*/
firstDay(date) {
const newDate = new Date(
date.getFullYear(),
date.getMonth(), 1);
this.applyOffset(newDate);
return newDate;
}
/**
* Returns last day of month from a given date
*
* @param {Date} date - Origin date
* @return {Integer}
*/
lastDay(date) {
const newDate = new Date(
date.getFullYear(),
date.getMonth() + 1, 0);
this.applyOffset(newDate);
return newDate;
}
applyOffset(date) {
date.setTime(date.getTime() - date.getTimezoneOffset() * 60000);
}
repaint() {
const firstWeekday = this.firstDay(this.currentMonth).getDay();
const previousLastDay = this.lastDay(this.previousMonth).getDate();
const currentLastDay = this.lastDay(this.currentMonth).getDate();
const maxFields = 42; // Max field limit
let weekdayOffset = firstWeekday > 0 ? firstWeekday : 7;
let dayPrevious = previousLastDay - (weekdayOffset - 2);
let dayCurrent = 1;
let dayNext = 1;
this.days = [];
let day = 1;
let previousMonthDay = previousLastMonthDay.getDate() - (weekday - 2);
let nextMonthDay = 1;
for (let d = 1; d <= 35; d++) {
if (d < weekday) {
let monthDay = new Date(previousLastMonthDay);
monthDay.setDate(previousMonthDay);
this.days.push({number: previousMonthDay, date: monthDay, color: 'gray'});
previousMonthDay++;
} else if (d >= weekday && day <= this.lastDay) {
let monthDay = new Date(this.defaultDate);
monthDay.setDate(day);
this.days.push({number: day, date: monthDay});
day++;
} else if (d >= weekday && day > this.lastDay) {
this.days.push({number: nextMonthDay, color: 'gray'});
nextMonthDay++;
for (let fieldIndex = 1; fieldIndex <= maxFields; fieldIndex++) {
if (fieldIndex < weekdayOffset) {
this.addDay(this.previousMonth, dayPrevious, 'gray');
dayPrevious++;
} else if (fieldIndex >= weekdayOffset && dayCurrent <= currentLastDay) {
this.addDay(this.currentMonth, dayCurrent);
dayCurrent++;
} else if (fieldIndex >= weekdayOffset && dayCurrent > currentLastDay) {
this.addDay(this.nextMonth, dayNext, 'gray');
dayNext++;
}
}
}
moveNext() {
let next = this.defaultDate.getMonth() + 1;
addDay(date, day, color = '') {
const curDate = new Date();
curDate.setHours(0, 0, 0, 0);
this.applyOffset(curDate);
const newDate = new Date(
date.getFullYear(),
date.getMonth(), day);
this.applyOffset(newDate);
let event = this.events.find(event => {
return event.date >= newDate && event.date <= newDate;
});
/* if (curDate >= newDate && curDate <= newDate)
color = 'orange'; */
/* if (newDate.getMonth() === this.currentMonth.getMonth() && newDate.getDay() == 6)
color = 'light-blue'; */
if (newDate.getMonth() === this.currentMonth.getMonth() && newDate.getDay() == 0)
color = 'red';
if (event)
color = event.color;
this.days.push({date: newDate, color, event});
}
/**
* Adds a new calendar event
*
* @param {Date} date - Day to add event
* @param {String} color - [green, blue, orange, red]
* @param {String} title - Tooltip description
* @param {Boolean} isRemovable - True if is removable by users
*/
addEvent(date, color, title = '', isRemovable = true) {
const event = this.events.findIndex(event => {
return event.date >= date && event.date <= date;
});
if (event == -1)
this.events.push({date, color, title, isRemovable});
this.repaint();
}
removeEvent(date) {
const event = this.events.findIndex(event => {
return event.date >= date && event.date <= date;
});
if (event > -1)
this.events.splice(event, 1);
this.repaint();
}
/**
* Moves to next month
*
* @param {Integer} skip - Months to skip at once
*/
moveNext(skip = 1) {
let next = this.defaultDate.getMonth() + skip;
this.defaultDate.setMonth(next);
this.buildDays();
this.repaint();
this.emit('moveNext');
}
movePrevious() {
let previous = this.defaultDate.getMonth() - 1;
/**
* Moves to previous month
*
* @param {Integer} skip - Months to skip at once
*/
movePrevious(skip = 1) {
let previous = this.defaultDate.getMonth() - skip;
this.defaultDate.setMonth(previous);
this.buildDays();
this.repaint();
this.emit('movePrevious');
}
/**
* Day selection event
*
* @param {Integer} index - Index from days array
*/
select(index) {
this.emit('selection', {value: this.days[index]});
let day = this.days[index];
day.index = index;
this.emit('selection', {values: [day]});
}
selectAll(weekday) {
let selected = [];
for (let i in this.days) {
const day = this.days[i];
const date = day.date;
day.index = i;
if (date.getDay() === weekday && date.getMonth() == this.defaultDate.getMonth())
selected.push(day);
}
this.emit('selection', {values: selected});
}
}
Calendar.$inject = ['$element', '$scope', '$attrs'];
@ -89,7 +242,12 @@ ngModule.component('vnCalendar', {
controller: Calendar,
bindings: {
model: '<',
events: '<?',
defaultDate: '<?',
onSelection: '&?'
onSelection: '&?',
onMoveNext: '&?',
onMovePrevious: '&?',
displayControls: '<?',
skip: '<?'
}
});

View File

@ -4,21 +4,31 @@ vn-calendar {
width: 100%;
.header vn-one {
text-align: center
text-align: center;
padding: 0.2em 0
}
.body {
.days {
justify-content: flex-start;
align-items: flex-start;
flex-wrap: wrap;
}
& > .day {
.weekdays {
border-bottom: 1px solid $hover;
border-top: 1px solid $hover;
font-weight: bold
}
.day {
box-sizing: border-box;
padding: 0.1em;
width: 14.2857143%;
line-height: 1.5em;
span {
transition: background-color 0.3s;
text-align: center;
font-size: 0.8vw;
border-radius: 50%;
@ -26,16 +36,105 @@ vn-calendar {
padding: 0.2em;
cursor: pointer
}
}
& > .day:hover span {
.day:hover span {
background-color: #DDD
}
& > .day.gray {
.day.gray {
color: $secondary-font-color
}
.day.orange {
font-weight: bold;
color: $main-01;
}
.day.orange-circle {
color: $main-font-color;
& > span {
background-color: $main-01
}
}
.day.orange-circle:hover {
& > span {
background-color: $main-01-05
}
}
.day.light-orange {
color: $main-01-05
}
.day.green {
font-weight: bold;
color: $main-02;
}
.day.green-circle {
color: $main-font-color;
& > span {
background-color: $main-02
}
}
.day.green-circle:hover {
& > span {
background-color: $main-02-05
}
}
.day.light-green {
font-weight: bold;
color: $main-02-05
}
.day.blue {
font-weight: bold;
color: $main-03;
}
.day.blue-circle {
color: $main-font-color;
& > span {
background-color: $main-03
}
}
.day.blue-circle:hover {
& > span {
background-color: $main-03-05
}
}
.day.light-blue {
font-weight: bold;
color: $main-03-05
}
.day.red {
font-weight: bold;
color: $alert-01
}
.day.red-circle {
color: $main-font-color;
& > span {
background-color: $alert-01
}
}
.day.red-circle:hover {
& > span {
background-color: $alert-01-05
}
}
.day.light-red {
font-weight: bold;
color: $alert-01-05;
}
}
}

View File

@ -35,6 +35,7 @@ export default class Controller extends Input {
onChange() {
this._field = this.input.checked == true;
this.$.$applyAsync();
this.emit('change');
}
}
Controller.$inject = ['$element', '$scope', '$attrs'];
@ -47,6 +48,7 @@ ngModule.component('vnCheck', {
},
bindings: {
field: '=?',
onChange: '&?',
label: '@?',
disabled: '<?',
rule: '@?'

View File

@ -13,6 +13,8 @@
background-color: rgba(0, 0, 0, .6);
opacity: 0;
transition: opacity 300ms ease-in-out;
padding: 3em;
box-sizing: border-box;
&.shown {
opacity: 1;
@ -25,6 +27,7 @@
overflow: auto;
padding: 2em;
box-sizing: border-box;
max-height: 100%;
tpl-body {
display: block;
@ -67,50 +70,4 @@
}
}
}
&.dialog-summary {
vn-card {
border: none;
box-shadow: none;
padding: 0;
& > div > vn-vertical {
padding: 0;
margin: 0
}
}
& > div > button.close > vn-icon {
color: $main-01;
}
& > div {
padding: 0
}
tpl-body {
width:auto;
background-color: transparent;
padding: 0 2em
}
.body {
overflow: auto;
margin-top: 2em;
max-height: 700px;
}
form {
min-width: 680px;
}
.buttons {
margin-top: 2em
}
vn-check label span {
font-size: .9em
}
}
}

View File

@ -2,7 +2,8 @@
<vn-one>{{::$ctrl.item.name}}</vn-one>
<vn-auto>
<section
class="inline-tag ellipsize" ng-class="{'empty': !fetchedTag.value}"
class="inline-tag ellipsize"
ng-class="::{empty: !fetchedTag.value}"
ng-repeat="fetchedTag in $ctrl.tags track by $index"
vn-tooltip="{{::fetchedTag.name}}: {{::fetchedTag.value}}">
{{::fetchedTag.value}}

View File

@ -4,59 +4,35 @@ vn-fetched-tags {
&.noTitle vn-one {
display: none !important;
}
& > vn-horizontal {
align-items: center;
@media screen and (max-width: 1600px){
& vn-horizontal {
@media screen and (max-width: 1600px) {
flex-direction: column;
text-align: center;
& > vn-one {
padding: 0 0 0.2em 0;
}
& > vn-two {
text-align: center;
margin: 0 auto
}
.inline-tag {
font-size: 0.7em;
padding: 0.3em
padding-bottom: .2em;
}
}
& > vn-one {
min-width: 12em;
}
@media screen and (max-width: 1200px){
& vn-horizontal {
.inline-tag {
font-size: 0.6em;
padding: 0.2em
}
}
}
& vn-one {
padding-top: 0.2em
}
& vn-two {
white-space: nowrap
}
& .inline-tag {
background-color: $color-white;
& > vn-auto > .inline-tag {
display: inline-block;
color: $secondary-font-color;
margin-right: 0.4em;
margin-right: .4em;
text-align: center;
font-size: 0.8em;
font-size: .8em;
height: 1.25em;
padding: 0.3em;
width: 5em;
padding: .1em;
border-radius: .1em;
width: 4em;
border: 1px solid $secondary-font-color;
}
& .inline-tag.empty {
border: 1px solid $main-bg
&.empty {
border: 1px solid $main-bg;
}
}
}
}

View File

@ -42,5 +42,6 @@ import './input-time';
import './fetched-tags';
import './log';
import './treeview';
import './treeview/child';
import './calendar';

View File

@ -8,7 +8,7 @@ export default class Controller {
}
set label(value) {
let label = this.element.querySelector('vn-label');
label.textContent = this._.instant(value) + ':';
label.textContent = this._.instant(value);
this._label = value;
}
get label() {

View File

@ -3,6 +3,10 @@
vn-label-value > section {
& > vn-label {
color: $secondary-font-color;
&::after {
content: ':';
}
}
& > span {
color: $main-font-color;

View File

@ -82,9 +82,6 @@
</vn-empty-rows>
</vn-table>
</vn-vertical>
<vn-pagination
model="$ctrl.model"
scroll-selector="ui-view">
</vn-pagination>
<vn-pagination model="$ctrl.model"></vn-pagination>
</vn-card>
</vn-vertical>

View File

@ -23,7 +23,7 @@ class Pagination extends Component {
$onInit() {
if (!this._scrollElement)
this.scrollElement = document.body;
this.scrollElement = window;
}
set scrollSelector(value) {
@ -50,9 +50,24 @@ class Pagination extends Component {
}
onScroll() {
let scrollInfo;
let scrollElement = this.scrollElement;
let shouldLoad =
scrollElement.scrollTop + scrollElement.clientHeight >= (scrollElement.scrollHeight - this.scrollOffset)
if (scrollElement == window) {
scrollInfo = {
top: window.pageYOffset,
height: window.innerHeight,
position: window.document.body.scrollHeight
};
} else {
scrollInfo = {
top: scrollElement.scrollTop,
height: scrollElement.clientHeight,
position: scrollElement.scrollHeight
};
}
let shouldLoad = scrollInfo.top + scrollInfo.height >= (scrollInfo.position - this.scrollOffset)
&& !this.model.isLoading
&& (this.maxLoads <= 0 || this.nLoads < this.maxLoads);

View File

@ -0,0 +1,25 @@
<ul ng-if="$ctrl.items">
<li ng-repeat="item in $ctrl.items" ng-class="{'selected' : item.selected, 'included': item.included}">
<vn-horizontal>
<vn-auto class="actions">
<vn-icon icon="keyboard_arrow_up" ng-if="item.childs.length"
ng-click="$ctrl.toggle(item, $event)">
</vn-icon>
<vn-icon icon="keyboard_arrow_down" ng-if="!item.childs"
ng-click="$ctrl.toggle(item, $event)">
</vn-icon>
</vn-auto>
<vn-one class="description">
<vn-horizontal>
<vn-check vn-auto field="item.selected"
on-change="$ctrl.select(item)">
</vn-check>
<vn-one ng-dblclick="$ctrl.toggle(item)" class="text unselectable">
{{::item.name}}
</vn-one>
</vn-horizontal>
</vn-one>
</vn-horizontal>
<vn-treeview-child items="item.childs"></vn-treeview-child>
</li>
</ul>

View File

@ -0,0 +1,27 @@
import ngModule from '../../module';
import Component from '../../lib/component';
class Controller extends Component {
constructor($element, $scope) {
super($element, $scope);
}
toggle(item) {
this.treeview.onToggle(item);
}
select(item) {
this.treeview.onSelection(item);
}
}
ngModule.component('vnTreeviewChild', {
template: require('./child.html'),
controller: Controller,
bindings: {
items: '<'
},
require: {
treeview: '^vnTreeview'
}
});

View File

@ -1,13 +1 @@
<div>
<ul>
<li ng-repeat="item in $ctrl.data">
<a href="">
<vn-icon icon="keyboard_arrow_down"></vn-icon>
<span>{{::item.name}}</span>
<section style="float:right">
icons</section>
</a>
</li>
</ul>
</div>
<vn-treeview-child items="$ctrl.data"></vn-treeview-child>

View File

@ -8,20 +8,137 @@ import './style.scss';
* @property {String} position The relative position to the parent
*/
export default class Treeview extends Component {
constructor($element, $scope, $timeout) {
constructor($element, $scope) {
super($element, $scope);
this.data = [];
}
get data() {
return this.model.data;
$onInit() {
this.refresh();
}
set selection(value) {
this._selection = value;
refresh() {
this.model.refresh().then(() => {
this.data = this.model.data;
this.repaintAll();
});
}
repaintAll() {
let oldData = this.data;
oldData.forEach(node => {
this.repaintAsc(node);
this.repaintDesc(node);
});
}
repaintNode(node) {
this.repaintAsc(node);
this.repaintDesc(node);
}
repaintAsc(node) {
if (!node.parent) return;
const parent = node.parent;
if ((node.selected || node.included) && !parent.selected) {
parent.included = true;
parent.hasCheckedChilds = true;
} else if (!this.hasCheckedChilds(parent) && !this.hasCheckedParents(node))
parent.included = false;
// FIXME - Propagate hasCheckedCHilds
if (!node.selected && this.hasCheckedParents(node)) {
node.included = true;
parent.hasCheckedChilds = false;
}
if (!this.hasCheckedChilds(node))
node.hasCheckedChilds = false;
this.repaintAsc(parent);
}
repaintDesc(node) {
/* if (node.hasCheckedChilds)
node.included = false; */
if (!node.selected && this.hasCheckedChilds(node)) {
node.hasCheckedChilds = true;
node.included = true;
} else if (!node.selected && node.childs && !this.hasCheckedChilds(node))
node.hasCheckedChilds = false;
const childs = node.childs || [];
for (let i = 0; i < childs.length; i++) {
childs[i].included = false;
if ((node.selected || node.included && this.hasCheckedParents(childs[i])) && !childs[i].selected)
childs[i].included = true;
this.repaintDesc(childs[i]);
}
if (!node.selected && node.hasCheckedChilds)
node.included = true;
}
hasCheckedChilds(node) {
if (!node.childs) return false;
const childs = node.childs;
for (let i = 0; i < childs.length; i++) {
if (childs[i].selected || this.hasCheckedChilds(childs[i]))
return true;
}
return false;
}
hasCheckedParents(node) {
if (!node.parent) return false;
const parent = node.parent;
if (parent.selected || this.hasCheckedParents(parent))
return true;
return false;
}
onSelection(item) {
item.selected = !item.selected;
if (item.selected && item.included)
item.included = false;
if (this.hasCheckedChilds(item))
item.hasCheckedChilds = true;
else if (this.childs)
item.hasCheckedChilds = false;
this.emit('selection', {item});
}
onToggle(item) {
if (item.childs && item.childs.length == 0)
return;
if (item.childs)
item.childs = undefined;
else {
this.model.applyFilter({}, {parentFk: item.id}).then(() => {
item.childs = this.model.data;
item.childs.forEach(child => {
child.parent = item;
});
this.repaintNode(item);
});
}
}
}
Treeview.$inject = ['$element', '$scope', '$attrs'];
Treeview.$inject = ['$element', '$scope'];
ngModule.component('vnTreeview', {
template: require('./index.html'),

View File

@ -1,3 +1,5 @@
@import "colors";
vn-treeview {
ul {
margin: 0;
@ -5,15 +7,43 @@ vn-treeview {
li {
list-style: none;
cursor: pointer;
a {
display: block;
.actions {
padding: 0.5em;
}
.description {
padding: 0.5em
}
}
li ul {
padding: 0 1.8em;
}
& > ul > li {
li > vn-horizontal:hover {
background-color: $hover
}
li.selected > vn-horizontal > .description .text,
li.included > vn-horizontal > .description .text {
font-weight: bold;
color: $main-01;
}
li.included {
& > vn-horizontal > .description > vn-horizontal > vn-check {
.mdl-checkbox .mdl-checkbox__box-outline, {
border: 2px solid $main-01-05;
}
fieldset[disabled] .mdl-checkbox .mdl-checkbox__box-outline, .mdl-checkbox.is-disabled .mdl-checkbox__box-outline {
border: 2px solid rgba(0,0,0,.26);
}
.mdl-checkbox .mdl-checkbox__tick-outline {
background: $main-01-05;
}
}
}
}
}

View File

@ -25,3 +25,16 @@ Value should have a length between %s and %s: El valor debe tener una longitud d
Value should have at least %s characters: El valor debe tener al menos %s carácteres
Value should have at most %s characters: El valor debe tener un máximo de %s carácteres
General search: Busqueda general
January: Enero
February: Febrero
March: Marzo
April: Abril
May: Mayo
June: Junio
July: Julio
August: Agosto
September: Septiembre
October: Octubre
November: Noviembre
December: Diciembre
Has delivery: Hay reparto

View File

@ -1,13 +1,11 @@
<vn-vertical full-height class="bg-content">
<vn-topbar vn-auto>
<vn-topbar vn-auto>
<a ui-sref="home" title="{{'Home' | translate}}">
<img class="logo" src="./logo.svg" alt="Logo"></img>
</a>
<vn-spinner enable="$ctrl.vnApp.loading"></vn-spinner>
<vn-main-menu></vn-main-menu>
</vn-topbar>
<vn-vertical vn-one ui-view scrollable class="main-view">
</vn-topbar>
<div ui-view class="main-view">
<vn-home></vn-home>
</vn-vertical>
<vn-snackbar vn-id="snackbar"></vn-snackbar>
</vn-vertical>
</div>
<vn-snackbar vn-id="snackbar"></vn-snackbar>

View File

@ -1,12 +1,20 @@
body {
height: 100%;
}
@import "background";
body {
@extend .bg-content;
overflow: auto;
}
vn-app {
display: block;
height: 100%;
vn-topbar {
position: fixed;
top: 0;
left: 0;
width: 100%;
z-index: 1;
box-shadow: 0 .1em .2em rgba(1, 1, 1, .2);
.logo {
float: left;
height: 1.8em;
@ -18,9 +26,6 @@ vn-app {
}
}
.main-view {
& > * {
height: 100%;
overflow: auto;
}
padding-top: 4em;
}
}

View File

@ -1,18 +1,22 @@
<div ng-if="$ctrl.state.current.name === 'home'">
<div ng-if="$ctrl.$state.current.name === 'home'">
<div class="modules">
<a
ng-repeat="mod in ::$ctrl.modules"
ui-sref="{{::mod.route.state}}"
translate-attr="{title: '{{::mod.name}}'}"
translate-attr="::{title: mod.name}"
class="mdl-shadow--4dp">
<vn-icon icon="{{::mod.icon}}"></vn-icon>
<h4 translate>{{::mod.name}}</h4>
<div>
<vn-icon icon="{{::mod.icon || 'photo'}}"></vn-icon>
</div>
<h4 ng-bind-html="$ctrl.getModuleName(mod)"></h4>
<!--
<span
ng-show='mod.keyBind'
vn-tooltip="Ctrl + Alt + {{mod.keyBind}}">
({{::mod.keyBind}})
</span>
<span ng-show='!mod.keyBind'>&nbsp;</span>
-->
</a>
</div>
</div>

View File

@ -3,26 +3,42 @@ import './style.scss';
import keybindings from '../../global-keybindings.yml';
export default class Controller {
constructor(modulesFactory, $state, $translate, $scope) {
constructor(modulesFactory, $state, $translate, $sce) {
this.modules = modulesFactory.getModules();
this.state = $state;
this.$translate = $translate;
this.$scope = $scope;
this.$state = $state;
this._ = $translate;
this.$sce = $sce;
this.keybindings = keybindings;
}
$onInit() {
this.modules.map(module => {
this.modules.map(mod => {
let keyBind = this.keybindings.find(keyBind => {
return keyBind.sref == module.route.state;
return keyBind.sref == mod.route.state;
});
if (keyBind)
module.keyBind = keyBind.key.toUpperCase();
mod.keyBind = keyBind.key.toUpperCase();
});
}
getModuleName(mod) {
let getName = mod => {
let name = this._.instant(mod.name);
let lower = name.toUpperCase();
if (!mod.keyBind) return name;
let index = lower.indexOf(mod.keyBind);
if (index === -1) return name;
let newName = name.substr(0, index);
newName += `<span class="bind-letter">${name.substr(index, 1)}</span>`;
newName += name.substr(index + 1);
return newName;
};
return this.$sce.trustAsHtml(getName(mod));
}
}
Controller.$inject = ['modulesFactory', '$state', '$translate', '$scope'];
Controller.$inject = ['modulesFactory', '$state', '$translate', '$sce'];
ngModule.component('vnHome', {
template: require('./home.html'),

View File

@ -15,6 +15,8 @@ vn-home {
flex-direction: row;
justify-content: center;
flex-wrap: wrap;
max-width: 40em;
margin: 0 auto;
& > a {
@extend %clickable-light;
@ -30,18 +32,17 @@ vn-home {
padding: 1em;
justify-content: center;
& > div {
height: 70px;
display: flex;
align-items: center;
justify-content: center;
& > vn-icon {
font-size: 4em;
display: block;
font-size: 3.5em;
}
& > vn-icon i[class="material-icons"] {
line-height: 75px;
}
& > vn-icon, & > vn-icon i, & > vn-icon i::before {
max-height: 75px;
}
& > span {
font-size: 0.9em;
text-align: center;
@ -53,6 +54,11 @@ vn-home {
white-space: nowrap;
overflow: hidden;
color: white;
margin: 0;
& > .bind-letter {
color: #FD0;
}
}
}
}

View File

@ -1,7 +1,4 @@
<vn-card ng-if="::$ctrl.items.length > 0">
<vn-vertical pad-medium-top pad-medium-bottom>
<vn-horizontal>
<ul>
<ul ng-if="::$ctrl.items.length > 0" pad-medium-v>
<li ng-repeat="item in ::$ctrl.items" name="{{::item.description}}">
<a ui-sref="{{::item.state}}" ng-class="{active: item.childs.length == 0 && item.active, expanded: item.active, collapsed: !item.active}"
ng-click="$ctrl.setActive(item)">
@ -9,7 +6,6 @@
<vn-icon icon="keyboard_arrow_down" ng-if="::item.childs.length > 0"></vn-icon>
<span translate>{{::item.description}}</span>
</a>
<ul ng-show="item.childs.length > 0 && item.active">
<li ng-repeat="child in ::item.childs">
<a ui-sref="{{::child.state}}" ng-class="{active: child.active}">
@ -19,7 +15,4 @@
</li>
</ul>
</li>
</ul>
</vn-horizontal>
</vn-vertical>
</vn-card>
</ul>

View File

@ -22,7 +22,7 @@
<vn-menu vn-id="apps-menu">
<ul pad-small>
<li ng-repeat="mod in ::$ctrl.modules" ui-sref="{{::mod.route.state}}">
<vn-icon icon="{{::mod.icon}}"></vn-icon>
<vn-icon icon="{{::mod.icon || 'photo'}}"></vn-icon>
<span translate>{{::mod.name}}</span>
</li>
</ul>

View File

@ -4,10 +4,9 @@ function modulesFactory(aclService) {
function getMainRoute(routeCollection) {
let cant = routeCollection.length;
for (let i = 0; i < cant; i++) {
if (!routeCollection[i].abstract) {
if (!routeCollection[i].abstract)
return routeCollection[i];
}
}
return null;
}
@ -16,7 +15,7 @@ function modulesFactory(aclService) {
for (let file in window.routes) {
let card = {
name: routes[file].name || routes[file].module,
icon: routes[file].icon || ''
icon: routes[file].icon || null
};
let mainRoute = getMainRoute(window.routes[file].routes);
if (mainRoute && aclService.routeHasPermission(mainRoute)) {

View File

@ -162,18 +162,24 @@ vn-tool-bar {
}
vn-main-block {
display:block;
max-width: 1920px;
width:100%;
display: block;
margin: 0 auto;
.left-block {
position: fixed;
z-index: 1;
top: 4em;
left: 0;
bottom: 0;
width: 16em;
min-width: 16em;
padding-left: 1em;
padding-bottom: 1em;
background-color: white;
box-shadow: 0 .1em .2em rgba(1, 1, 1, .2);
overflow: auto;
}
& > vn-horizontal > vn-one > [ui-view] {
padding-left: 16em;
}
.right-block {
width: 16em;
min-width: 16em;

View File

@ -1,18 +1,64 @@
@import "./colors";
@import "./margin";
@import "./padding";
.summary{
h5:not(.title) {
padding: 7px;
background-color: $main-01-03;
border-bottom: 2px solid $main-01;
font-family: unset !important;
text-transform: uppercase;
}
.title, p.title {
.summary {
margin: 0 auto;
max-width: 950px;
& > div {
& > h5 {
@extend .pad-small;
border: none;
background: $main-01;
color: $color-white;
margin: 0!important;
margin: 0;
text-align: center;
line-height: 1.3em;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
& > vn-horizontal {
flex-wrap: wrap;
@extend .pad-medium;
h4 {
@extend .margin-medium-bottom;
text-transform: uppercase;
font-size: 15pt;
line-height: 1;
padding: 7px;
padding-bottom: 4px; /* Bottom line-height fix */
font-family: unset;
background-color: $main-01-03;
border-bottom: .1em solid $main-01;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
& > * {
@extend .margin-small;
min-width: 14em;
overflow: hidden;
padding: 0;
}
& > vn-auto {
width: 100%;
}
vn-label-value > section {
margin-bottom: .3em;
& > vn-label {
display: block;
font-size: .9em;
&::after {
content: initial;
}
}
}
}
}
p:after {
content: ' ';
@ -20,42 +66,50 @@
display: block;
clear: both
}
}
vn-label-value > section {
margin-bottom: .3em
.vn-dialog.dialog-summary {
vn-card {
border: none;
box-shadow: none;
}
& > div > button.close {
display: none;
}
& > div {
padding: 0
}
tpl-body {
width: auto;
}
.buttons {
display: none;
}
vn-check label span {
font-size: .9em
}
}
.state {
@extend .summary;
padding: 5px;
background-color: $main-01;
vn-one:nth-child(1){
border-right: 1px solid white;
}
color: white;
p {
font-size: 12px;
line-height: 15px!important;
padding: 0 0 2px 0;
font-size: 13px;
line-height: 15px;
text-align: center;
margin: .1em 0;
&:nth-child(1) {
text-transform: uppercase;
}
h5 {
line-height: 10px!important;
}
vn-one {
padding: 0;
}
vn-one > h5{
padding-bottom: 7px;
}
}
vn-item-descriptor .state{
@extend .state;
vn-one > p{
padding-top: 5px;
}
vn-one > h5{
padding-bottom: 12px;
&:nth-child(1) {
border-right: .1em solid white;
}
}
}

View File

@ -26,5 +26,6 @@
"Warehouse cannot be blank": "Warehouse cannot be blank",
"Agency cannot be blank": "Agency cannot be blank",
"The IBAN does not have the correct format": "The IBAN does not have the correct format",
"You can't make changes on the basic data of an confirmed order or with rows": "You can't make changes on the basic data of an confirmed order or with rows"
"You can't make changes on the basic data of an confirmed order or with rows": "You can't make changes on the basic data of an confirmed order or with rows",
"You can't create a ticket for a inactive client": "You can't create a ticket for a inactive client"
}

View File

@ -0,0 +1,35 @@
module.exports = Self => {
Self.remoteMethod('getByWarehouse', {
description: 'Returns an array of labour holidays from an specified warehouse',
accessType: '',
accepts: [{
arg: 'warehouseFk',
type: 'Number',
required: true,
}],
returns: {
type: ['object'],
root: true
},
http: {
path: `/getByWarehouse`,
verb: 'GET'
}
});
Self.getByWarehouse = warehouseFk => {
let beginningYear = new Date();
beginningYear.setMonth(0);
beginningYear.setDate(1);
beginningYear.setHours(0, 0, 0, 0);
return Self.rawSql(
`SELECT lh.dated, lhl.description, lht.name, w.id
FROM vn.labourHoliday lh
JOIN vn.workCenter w ON w.id = lh.workcenterFk
LEFT JOIN vn.labourHolidayLegend lhl ON lhl.id = lh.labourHolidayLegendFk
LEFT JOIN vn.labourHolidayType lht ON lht.id = lh.labourHolidayTypeFk
WHERE w.warehouseFk = ? AND lh.dated >= ?`, [warehouseFk, beginningYear]
);
};
};

View File

@ -0,0 +1,31 @@
module.exports = Self => {
Self.remoteMethod('removeByDate', {
description: 'Removes one or more delivery dates for a zone',
accessType: '',
accepts: [{
arg: 'zoneFk',
type: 'Number',
required: true,
},
{
arg: 'dates',
type: ['Date'],
required: true,
}],
returns: {
type: 'object',
root: true
},
http: {
path: `/removeByDate`,
verb: 'POST'
}
});
Self.removeByDate = (zoneFk, dates) => {
return Self.destroyAll({zoneFk, delivered: {inq: dates}});
/* return Self.rawSql(`
DELETE FROM vn.zoneCalendar
WHERE zoneFk = ? AND delivered IN(?)`, [zoneFk, dates]); */
};
};

View File

@ -0,0 +1,35 @@
module.exports = Self => {
Self.remoteMethod('toggleIsIncluded', {
description: 'Toggle include to delivery',
accessType: '',
accepts: [{
arg: 'zoneFk',
type: 'Number',
required: true,
},
{
arg: 'geoFk',
type: 'Number',
required: true,
}],
returns: {
type: 'object',
root: true
},
http: {
path: `/toggleIsIncluded`,
verb: 'POST'
}
});
Self.toggleIsIncluded = async(zoneFk, geoFk) => {
const isIncluded = await Self.findOne({
where: {zoneFk, geoFk}
});
if (isIncluded)
return Self.destroyAll({zoneFk, geoFk});
else
return Self.upsert({zoneFk, geoFk});
};
};

View File

@ -0,0 +1,94 @@
const ParameterizedSQL = require('loopback-connector').ParameterizedSQL;
module.exports = Self => {
Self.remoteMethod('getLeaves', {
description: 'Returns the first shipped and landed possible for params',
accessType: '',
accepts: [{
arg: 'filter',
type: 'Object',
description: 'Filter defining where, order, offset, and limit - must be a JSON-encoded string',
http: {source: 'query'}
},
{
arg: 'zoneFk',
type: 'Number',
required: true,
},
{
arg: 'parentFk',
type: 'Number',
default: 1,
required: false,
}],
returns: {
type: ['object'],
root: true
},
http: {
path: `/getLeaves`,
verb: 'GET'
}
});
Self.getLeaves = async(filter, zoneFk, parentFk = 1) => {
let conn = Self.dataSource.connector;
let stmts = [];
stmts.push(new ParameterizedSQL(
`SELECT lft, rgt, depth + 1 INTO @lft, @rgt, @depth
FROM zoneTreeview WHERE id = ?`, [parentFk]));
stmts.push(`DROP TEMPORARY TABLE IF EXISTS tChilds`);
let stmt = new ParameterizedSQL(
`CREATE TEMPORARY TABLE tChilds
ENGINE = MEMORY
SELECT id, lft, rgt
FROM zoneTreeview pt`);
stmt.merge(conn.makeSuffix(filter));
if (!filter.where) {
stmt.merge(`WHERE pt.lft > @lft AND pt.rgt < @rgt
AND pt.depth = @depth`);
}
stmts.push(stmt);
stmts.push(`DROP TEMPORARY TABLE IF EXISTS tZones`);
stmts.push(new ParameterizedSQL(
`CREATE TEMPORARY TABLE tZones
(INDEX (id))
ENGINE = MEMORY
SELECT t.id
FROM tChilds t
JOIN zoneTreeview zt
ON zt.lft > t.lft AND zt.rgt < t.rgt
JOIN zoneIncluded zi
ON zi.geoFk = zt.id AND zi.zoneFk = ?
GROUP BY t.id`, [zoneFk]));
const resultIndex = stmts.push(new ParameterizedSQL(
`SELECT
pt.id,
pt.name,
pt.lft,
pt.rgt,
pt.depth,
pt.sons,
ti.id IS NOT NULL hasCheckedChilds,
zi.geoFk IS NOT NULL AS selected
FROM zoneTreeview pt
LEFT JOIN vn.zoneIncluded zi
ON zi.geoFk = pt.id AND zi.zoneFk = ?
JOIN tChilds c ON c.id = pt.id
LEFT JOIN tZones ti ON ti.id = pt.id
ORDER BY selected DESC, name`, [zoneFk])) - 1;
const sql = ParameterizedSQL.join(stmts, ';');
const result = await Self.rawStmt(sql);
return result[resultIndex];
};
};

View File

@ -11,13 +11,29 @@
"Zone": {
"dataSource": "vn"
},
"ZoneCalendar": {
"ZoneGeo": {
"dataSource": "vn"
},
"ZoneGeo": {
"ZoneCalendar": {
"dataSource": "vn"
},
"ZoneIncluded": {
"dataSource": "vn"
},
"ZoneTreeview": {
"dataSource": "vn"
},
"LabourHoliday": {
"dataSource": "vn"
},
"LabourHolidayLegend": {
"dataSource": "vn"
},
"LabourHolidayType": {
"dataSource": "vn"
}
}

View File

@ -0,0 +1,18 @@
{
"name": "LabourHolidayLegend",
"base": "VnModel",
"options": {
"mysql": {
"table": "labourHolidayLegend"
}
},
"properties": {
"id": {
"id": true,
"type": "Number"
},
"description": {
"type": "String"
}
}
}

View File

@ -0,0 +1,21 @@
{
"name": "LabourHolidayType",
"base": "VnModel",
"options": {
"mysql": {
"table": "labourHolidayType"
}
},
"properties": {
"id": {
"id": true,
"type": "Number"
},
"name": {
"type": "String"
},
"rgb": {
"type": "String"
}
}
}

View File

@ -0,0 +1,3 @@
module.exports = Self => {
require('../methods/labour-holiday/getByWarehouse')(Self);
};

View File

@ -0,0 +1,39 @@
{
"name": "LabourHoliday",
"base": "VnModel",
"options": {
"mysql": {
"table": "labourHoliday"
}
},
"properties": {
"labourHolidayLegendFk": {
"id": true,
"type": "Number"
},
"labourHolidayTypeFk": {
"id": true,
"type": "Number"
},
"dated": {
"type": "Date"
}
},
"relations": {
"legend": {
"type": "belongsTo",
"model": "LabourHolidayLegend",
"foreignKey": "labourHolidayLegendFk"
},
"type": {
"type": "belongsTo",
"model": "LabourHolidayType",
"foreignKey": "labourHolidayTypeFk"
},
"workCenter": {
"type": "belongsTo",
"model": "WorkCenter",
"foreignKey": "workCenterFk"
}
}
}

View File

@ -0,0 +1,25 @@
{
"name": "WorkCenter",
"base": "VnModel",
"options": {
"mysql": {
"table": "work-center"
}
},
"properties": {
"id": {
"id": true,
"type": "Number"
},
"name": {
"type": "String"
}
},
"relations": {
"warehouse": {
"type": "belongsTo",
"model": "Warehouse",
"foreignKey": "warehouseFk"
}
}
}

View File

@ -0,0 +1,3 @@
module.exports = Self => {
require('../methods/zone-calendar/removeByDate')(Self);
};

View File

@ -3,7 +3,7 @@
"base": "VnModel",
"options": {
"mysql": {
"table": "ZoneCalendar"
"table": "zoneCalendar"
}
},
"properties": {
@ -12,6 +12,7 @@
"type": "Number"
},
"delivered": {
"id": true,
"type": "Date"
}
},

View File

@ -0,0 +1,3 @@
module.exports = Self => {
require('../methods/zone-included/toggleIsIncluded')(Self);
};

View File

@ -0,0 +1,3 @@
module.exports = Self => {
require('../methods/zone-treeview/getLeaves')(Self);
};

View File

@ -0,0 +1,30 @@
{
"name": "ZoneTreeview",
"base": "VnModel",
"options": {
"mysql": {
"table": "zoneTreeview"
}
},
"properties": {
"id": {
"id": true,
"type": "Number"
},
"name": {
"type": "String"
},
"lft": {
"type": "Number"
},
"rgt": {
"type": "Number"
},
"depth": {
"type": "Number"
},
"sons": {
"type": "Number"
}
}
}

View File

@ -0,0 +1,67 @@
<mg-ajax path="/agency/api/Zones/{{patch.params.id}}" options="vnPatch"></mg-ajax>
<vn-watcher
vn-id="watcher"
data="$ctrl.zone"
form="form"
save="patch">
</vn-watcher>
<form name="form" ng-submit="$ctrl.onSubmit()">
<vn-card pad-large>
<vn-title>Basic data</vn-title>
<vn-horizontal>
<vn-textfield vn-two vn-focus
label="Name"
field="$ctrl.zone.name">
</vn-textfield>
</vn-horizontal>
<vn-horizontal>
<vn-autocomplete
vn-one
field="$ctrl.zone.warehouseFk"
url="/agency/api/Warehouses"
show-field="name"
value-field="id"
label="Warehouse">
</vn-autocomplete>
<vn-autocomplete
vn-one
field="$ctrl.zone.agencyModeFk"
url="/agency/api/AgencyModes"
show-field="name"
value-field="id"
label="Agency">
</vn-autocomplete>
</vn-horizontal>
<vn-horizontal>
<vn-input-number
vn-two
min="0"
step="1"
label="Traveling days"
field="$ctrl.zone.travelingDays">
</vn-input-number>
<vn-input-time
vn-two
label="Estimated hour (ETD)"
field="$ctrl.zone.hour">
</vn-input-time>
</vn-horizontal>
<vn-horizontal>
<vn-input-number vn-one
label="Price"
field="$ctrl.zone.price"
min="0.00"
step="0.50">
</vn-input-number>
<vn-input-number vn-one
label="Bonus"
field="$ctrl.zone.bonus"
min="0.00"
step="0.50">
</vn-input-number>
</vn-horizontal>
</vn-card>
<vn-button-bar>
<vn-submit label="Save"></vn-submit>
</vn-button-bar>
</form>

View File

@ -8,7 +8,6 @@ class Controller {
onSubmit() {
this.$scope.watcher.submit().then(() => {
this.$state.go('zone.card.location');
this.card.reload();
});
}
@ -16,7 +15,7 @@ class Controller {
Controller.$inject = ['$scope', '$state'];
ngModule.component('vnZoneEdit', {
ngModule.component('vnZoneBasicData', {
template: require('./index.html'),
controller: Controller,
bindings: {

View File

@ -1,21 +1,29 @@
<!-- <vn-crud-model
<vn-crud-model
vn-id="model"
url="/order/api/ItemCategories"
data="categories">
</vn-crud-model> -->
url="/agency/api/ZoneCalendars"
fields="['zoneFk', 'delivered']"
link="{zoneFk: $ctrl.$stateParams.id}"
data="$ctrl.data"
primary-key="zoneFk" auto-load="true">
</vn-crud-model>
<vn-horizontal>
<vn-vertical vn-one>
<vn-card >
<vn-card>
<vn-vertical>
<vn-vertical pad-small>
<vn-calendar
default-date="$ctrl.defaultDate"
on-selection="$ctrl.onSelection(value)">
<vn-calendar vn-id="stMonth" events="$ctrl.events" skip="2"
on-selection="$ctrl.onSelection(stMonth, values)"
on-move-next="$ctrl.onMoveNext(ndMonth)"
on-move-previous="$ctrl.onMovePrevious(ndMonth)">
</vn-calendar>
</vn-vertical>
<vn-vertical pad-small>
<vn-calendar vn-id="ndMonth" events="$ctrl.events" skip="2"
display-controls="false"
on-selection="$ctrl.onSelection(ndMonth, values)"
default-date="$ctrl.ndMonthDate">
</vn-calendar>
</vn-vertical>
<!-- <vn-vertical pad-small>
<vn-calendar default-date="$ctrl.defaultNexDate"></vn-calendar>
</vn-vertical> -->
</vn-vertical>
</vn-card>
</vn-vertical>

View File

@ -1,19 +1,144 @@
import ngModule from '../module';
class Controller {
constructor($scope) {
constructor($scope, $stateParams, $http) {
this.$stateParams = $stateParams;
this.$scope = $scope;
this.defaultDate = new Date();
this.defaultNexDate = new Date(this.defaultDate);
this.defaultNexDate.setMonth(this.defaultNexDate.getMonth() + 1);
this.$http = $http;
this.stMonthDate = new Date();
this.ndMonthDate = new Date();
this.ndMonthDate.setMonth(this.ndMonthDate.getMonth() + 1);
this.events = [];
}
onSelection(value) {
console.log(value);
$postLink() {
this.stMonth = this.$scope.stMonth;
this.ndMonth = this.$scope.ndMonth;
}
get zone() {
return this._zone;
}
set zone(value) {
this._zone = value;
if (!value) return;
let query = '/agency/api/LabourHolidays/getByWarehouse';
this.$http.get(query, {params: {warehouseFk: value.warehouseFk}}).then(res => {
if (!res.data) return;
const events = [];
res.data.forEach(holiday => {
events.push({
date: holiday.dated,
color: 'blue-circle',
title: holiday.description || holiday.name,
isRemovable: false
});
});
this.events = this.events.concat(events);
});
}
get data() {
return this._data;
}
set data(value) {
this._data = value;
if (!value) return;
const events = [];
value.forEach(event => {
events.push({
date: event.delivered,
color: 'green-circle',
title: 'Has delivery',
isRemovable: true
});
});
this.events = this.events.concat(events);
}
onSelection(calendar, values) {
let totalEvents = 0;
values.forEach(day => {
const exists = this.events.findIndex(event => {
return event.date >= day.date && event.date <= day.date
&& event.isRemovable;
});
if (exists > -1) totalEvents++;
});
if (totalEvents > (values.length / 2))
this.removeEvents(values);
else
this.addEvents(values);
}
addEvents(days) {
days.forEach(day => {
const event = this.events.find(event => {
return event.date >= day.date && event.date <= day.date;
});
if (event)
return false;
this.$scope.model.insert({
zoneFk: this.zone.id,
delivered: day.date
});
this.stMonth.addEvent(day.date, 'green-circle', 'Has delivery', true);
this.stMonth.repaint();
this.ndMonth.addEvent(day.date, 'green-circle', 'Has delivery', true);
this.ndMonth.repaint();
});
this.$scope.model.save();
}
removeEvents(days) {
let dates = [];
days.forEach(day => {
const event = this.events.find(event => {
return event.date >= day.date && event.date <= day.date;
});
if (event && !event.isRemovable)
return false;
// FIXME - Date offset
let date = new Date(day.date);
date.setHours(0, 0, 0, 0);
dates.push(date);
this.stMonth.removeEvent(day.date);
this.stMonth.repaint();
this.ndMonth.removeEvent(day.date);
this.ndMonth.repaint();
});
if (dates.length == 0) return;
const params = {zoneFk: this.zone.id, dates};
this.$http.post('/agency/api/zoneCalendars/removeByDate', params);
}
onMoveNext(calendar) {
calendar.moveNext(2);
}
onMovePrevious(calendar) {
calendar.movePrevious(2);
}
}
Controller.$inject = ['$scope'];
Controller.$inject = ['$scope', '$stateParams', '$http'];
ngModule.component('vnZoneCalendar', {
template: require('./index.html'),

View File

@ -1,11 +1,11 @@
<vn-main-block>
<vn-vertical margin-medium>
<vn-zone-descriptor zone="$ctrl.zone"></vn-zone-descriptor>
<vn-horizontal>
<vn-one ui-view></vn-one>
<vn-auto class="right-block">
<vn-zone-calendar zone="$ctrl.zone"></vn-zone-calendar>
<vn-auto class="left-block">
<vn-zone-descriptor zone="$ctrl.zone"></vn-zone-descriptor>
<vn-left-menu></vn-left-menu>
</vn-auto>
<vn-one>
<vn-vertical margin-medium ui-view></vn-vertical>
</vn-one>
</vn-horizontal>
</vn-vertical>
</vn-main-block>

View File

@ -1,6 +1,6 @@
import './index.js';
describe('Agency', () => {
xdescribe('Agency', () => {
describe('Component vnZoneCard', () => {
let $scope;
let controller;

View File

@ -14,7 +14,7 @@ export default class Controller {
onSubmit() {
this.$scope.watcher.submit().then(res => {
this.$state.go('zone.card.basicData', {id: res.data.id});
this.$state.go('zone.card.location', {id: res.data.id});
});
}
}

View File

@ -1,7 +1,7 @@
import './index';
import watcher from 'core/mocks/watcher';
describe('Agency', () => {
xdescribe('Agency', () => {
describe('Component vnZoneCreate', () => {
let $scope;
let $state;

View File

@ -1,4 +1,4 @@
<vn-card margin-medium-v class="vn-descriptor">
<vn-card class="vn-descriptor">
<vn-horizontal class="header">
<a translate-attr="{title: 'Return to module index'}" ui-sref="zone.index">
<vn-icon icon="chevron_left"></vn-icon>
@ -14,36 +14,34 @@
on-change="$ctrl.onMoreChange(value)">
</vn-icon-menu>
</vn-horizontal>
<vn-horizontal pad-medium>
<vn-vertical pad-medium>
<vn-one>
<vn-label-value label="Id"
value="{{::$ctrl.zone.id}}">
value="{{$ctrl.zone.id}}">
</vn-label-value>
<vn-label-value label="Name"
value="{{::$ctrl.zone.name}}">
value="{{$ctrl.zone.name}}">
</vn-label-value>
<vn-label-value label="Warehouse"
value="{{::$ctrl.zone.warehouse.name}}">
value="{{$ctrl.zone.warehouse.name}}">
</vn-label-value>
<vn-label-value label="Agency"
value="{{::$ctrl.zone.agencyMode.name}}">
value="{{$ctrl.zone.agencyMode.name}}">
</vn-label-value>
</vn-one>
<vn-one>
<vn-label-value label="Estimated hour (ETD)"
value="{{::$ctrl.zone.hour | date: 'HH:mm'}}">
value="{{$ctrl.zone.hour | date: 'HH:mm'}}">
</vn-label-value>
<vn-label-value label="Traveling days"
value="{{::$ctrl.zone.travelingDays}}">
value="{{$ctrl.zone.travelingDays}}">
</vn-label-value>
<vn-label-value label="Price"
value="{{::$ctrl.zone.price | currency: '€': 2}}">
value="{{$ctrl.zone.price | currency: '€': 2}}">
</vn-label-value>
<vn-label-value label="Bonus"
value="{{::$ctrl.zone.price | currency: '€': 2}}">
value="{{$ctrl.zone.price | currency: '€': 2}}">
</vn-label-value>
</vn-one>
</vn-horizontal>
</vn-vertical>
</vn-card>
<vn-confirm

View File

@ -6,7 +6,6 @@ class Controller {
this.$state = $state;
this.$http = $http;
this.moreOptions = [
{callback: this.editZone, name: 'Settings'},
{callback: this.deleteZone, name: 'Delete'}
];
}
@ -19,10 +18,6 @@ class Controller {
this.$scope.deleteZone.show();
}
editZone() {
this.$state.go('zone.card.edit', {zone: this.zone});
}
returnDialog(response) {
if (response === 'ACCEPT') {
this.$http.delete(`/agency/api/Zones/${this.zone.id}`).then(() => {

View File

@ -6,6 +6,6 @@ import './card';
import './descriptor';
import './search-panel';
import './create';
import './edit';
import './basic-data';
import './location';
import './calendar';

View File

@ -40,7 +40,7 @@
<vn-td number>{{::zone.price | currency:'€':2}}</vn-td>
<vn-td>
<vn-icon-button
ng-click="$ctrl.preview(zone)"
ng-click="$ctrl.preview($event, zone)"
vn-tooltip="Preview"
icon="desktop_windows">
</vn-icon-button>
@ -52,11 +52,15 @@
</vn-empty-rows>
</vn-table>
</vn-card>
<vn-pagination
model="model"
scroll-selector="ui-view">
</vn-pagination>
<vn-pagination model="model"></vn-pagination>
</div>
<vn-dialog
vn-id="summary"
class="dialog-summary">
<tpl-body>
<vn-zone-summary zone="$ctrl.zoneSelected"></vn-zone-summary>
</tpl-body>
</vn-dialog>
<a ui-sref="zone.create" vn-tooltip="New zone" vn-bind="+" fixed-bottom-right>
<vn-float-button icon="add"></vn-float-button>

View File

@ -26,8 +26,8 @@ export default class Controller {
preview(event, zone) {
event.preventDefault();
event.stopImmediatePropagation();
this.$scope.summary.zone = zone;
this.$scope.dialog.show();
this.zoneSelected = zone;
this.$scope.summary.show();
}
}

View File

@ -1,6 +1,6 @@
import './index.js';
describe('Agency', () => {
xdescribe('Agency', () => {
describe('Component vnZoneIndex', () => {
let $componentController;
let controller;

View File

@ -6,7 +6,7 @@ Price: Precio
Create: Crear
Delete: Eliminar
Settings: Ajustes
Delivery days: Días de envío
Locations: Localizaciones
Enter a new search: Introduce una nueva búsqueda
Delete zone: Eliminar zona
Are you sure you want to delete this zone?: ¿Estás seguro de querer eliminar esta zona?
@ -15,4 +15,4 @@ Zones: Zonas
List: Listado
Summary: Vista previa
New zone: Nueva zona
Edit zone: Editar zona
Basic data: Datos básicos

View File

@ -1,18 +1,26 @@
<vn-crud-model
vn-id="model"
url="/agency/api/ZoneGeos"
data="geos">
url="/agency/api/ZoneTreeviews/getLeaves"
filter="::$ctrl.filter"
params="{zoneFk: $ctrl.$stateParams.id, parentFk: 1}">
</vn-crud-model>
<vn-vertical vn-one>
<vn-horizontal>
<vn-vertical vn-one>
<vn-card pad-large>
<vn-title>Delivery days</vn-title>
<vn-title>Locations</vn-title>
<vn-searchbar
panel="vn-calendar-search-panel"
model="model"
expr-builder="$ctrl.exprBuilder(param, value)"
on-search="$ctrl.onSearch()"
vn-focus>
</vn-searchbar>
<vn-treeview model="model"></vn-treeview>
<vn-treeview vn-id="treeview" model="model"
on-selection="$ctrl.onSelection(item)">
</vn-treeview>
</vn-card>
</vn-vertical>
</vn-vertical>
<vn-auto class="right-block">
<vn-zone-calendar zone="::$ctrl.zone"></vn-zone-calendar>
</vn-auto>
</vn-horizontal>

View File

@ -1,12 +1,37 @@
import ngModule from '../module';
class Controller {
constructor($scope) {
constructor($scope, $http, $stateParams) {
this.$stateParams = $stateParams;
this.$scope = $scope;
this.$http = $http;
this.searchValue = '';
this.filter = {};
}
onSearch() {
this.$scope.$$postDigest(() => {
this.$scope.treeview.refresh();
});
}
exprBuilder(param, value) {
switch (param) {
case 'search':
return {name: {like: `%${value}%`}};
}
}
onSelection(item) {
const path = '/agency/api/ZoneIncludeds/toggleIsIncluded';
const params = {geoFk: item.id, zoneFk: this.zone.id};
this.$http.post(path, params).then(() => {
this.$scope.treeview.repaintNode(item);
});
}
}
Controller.$inject = ['$scope'];
Controller.$inject = ['$scope', '$http', '$stateParams'];
ngModule.component('vnZoneLocation', {
template: require('./index.html'),

View File

@ -32,23 +32,26 @@
"description": "Detail"
},
{
"url": "/location",
"url": "/location?q",
"state": "zone.card.location",
"component": "vn-zone-location",
"description": "Location",
"description": "Locations",
"params": {
"zone": "$ctrl.zone"
}
},
{
"url": "/edit",
"state": "zone.card.edit",
"component": "vn-zone-edit",
"description": "Edit zone",
"url": "/basic-data",
"state": "zone.card.basicData",
"component": "vn-zone-basic-data",
"description": "Basic data",
"params": {
"zone": "$ctrl.zone"
}
}
],
"menu": []
"menu": [
{"state": "zone.card.basicData", "icon": "settings"},
{"state": "zone.card.location", "icon": "my_location"}
]
}

View File

@ -1,30 +1,37 @@
<vn-card class="summary">
<vn-vertical pad-medium>
<vn-horizontal>
<vn-one margin-medium>
<vn-vertical name="basicData">
<h5 translate>Basic data</h5>
<vn-auto>
<h5 text-center pad-small-v class="title">{{$ctrl.summary.name}}</h5>
</vn-auto>
<vn-horizontal pad-medium>
<vn-one>
<vn-label-value label="Id"
value="{{::$ctrl.summary.id}}">
</vn-label-value>
<vn-label-value label="Name"
value="{{$ctrl.zone.name}}">
value="{{::$ctrl.summary.name}}">
</vn-label-value>
<vn-label-value label="Warehouse"
value="{{$ctrl.zone.warehouse.name}}">
value="{{::$ctrl.summary.warehouse.name}}">
</vn-label-value>
<vn-label-value label="Agency"
value="{{$ctrl.zone.agencyMode.name}}">
value="{{::$ctrl.summary.agencyMode.name}}">
</vn-label-value>
</vn-one>
<vn-one>
<vn-label-value label="Estimated hour (ETD)"
value="{{$ctrl.zone.hour | date: 'HH:mm'}}">
value="{{::$ctrl.summary.hour | date: 'HH:mm'}}">
</vn-label-value>
<vn-label-value label="Traveling days"
value="{{::$ctrl.summary.travelingDays}}">
</vn-label-value>
<vn-label-value label="Price"
value="{{$ctrl.zone.price | currency: '€': 2}}">
value="{{::$ctrl.summary.price | currency: '€': 2}}">
</vn-label-value>
<vn-label-value label="Bonus"
value="{{$ctrl.zone.price | currency: '€': 2}}">
value="{{::$ctrl.summary.price | currency: '€': 2}}">
</vn-label-value>
</vn-vertical>
</vn-one>
<vn-one margin-medium></vn-one>
</vn-horizontal>
</vn-vertical>
</vn-card>

View File

@ -18,8 +18,17 @@ class Controller {
}
getSummary() {
this.$http.get(`/agency/api/Zones/${this.zone.id}`).then(response => {
this.summary = response.data;
let filter = {
include: [
{relation: 'warehouse', fields: ['name']},
{relation: 'agencyMode', fields: ['name']}
],
where: {id: this.zone.id}
};
filter = encodeURIComponent(JSON.stringify((filter)));
this.$http.get(`/agency/api/Zones/findOne?filter=${filter}`).then(res => {
if (res && res.data)
this.summary = res.data;
});
}
}

View File

@ -1,4 +1,4 @@
<vn-card margin-medium-v class="vn-descriptor">
<vn-card class="vn-descriptor">
<vn-horizontal class="header">
<a translate-attr="{title: 'Return to module index'}" ui-sref="claim.index">
<vn-icon icon="chevron_left"></vn-icon>

View File

@ -61,10 +61,7 @@
</vn-empty-rows>
</vn-table>
</vn-card>
<vn-pagination
model="model"
scroll-selector="ui-view">
</vn-pagination>
<vn-pagination model="model"></vn-pagination>
</div>
<vn-client-descriptor-popover vn-id="descriptor"></vn-client-descriptor-popover>
<vn-dialog class="dialog-summary"

View File

@ -36,9 +36,9 @@ export default class Controller {
case 'search':
return /^\d+$/.test(value)
? {id: value}
: {client: {regexp: value}};
: {client: {like: `%${value}%`}};
case 'client':
return {[param]: {regexp: value}};
return {[param]: {like: `%${value}%`}};
case 'created':
return {created: {between: [value, value]}};
case 'id':

View File

@ -1,16 +1,12 @@
<vn-vertical vn-one>
<vn-card class="summary" pad-medium compact>
<vn-vertical margin-medium>
<vn-auto>
<h5 text-center pad-small-v class="title">{{$ctrl.summary.claim.id}} - {{$ctrl.summary.claim.client.name}}</h5>
</vn-auto>
<vn-horizontal pad-medium-v>
<vn-card class="summary">
<h5>{{$ctrl.summary.claim.id}} - {{$ctrl.summary.claim.client.name}}</h5>
<vn-horizontal>
<vn-one>
<vn-label-value label="Created"
value="{{$ctrl.summary.claim.created | dateTime: 'dd/MM/yyyy'}}">
</vn-label-value>
<vn-label-value label="State"
value="{{::$ctrl.summary.claim.claimState.description}}">
value="{{$ctrl.summary.claim.claimState.description}}">
</vn-label-value>
<vn-label-value label="Salesperson"
value="{{$ctrl.summary.claim.client.salesPerson.firstName}} {{$ctrl.summary.claim.client.salesPerson.name}}">
@ -39,18 +35,17 @@
vn-acl="salesAssistant">
</vn-input-range>
</vn-one>
</vn-horizontal>
<vn-horizontal>
<vn-one margin-medium-v>
<h5 translate>Detail</h5>
<vn-auto>
<h4 translate>Detail</h4>
<div style="overflow: auto">
<vn-table model="model">
<vn-thead>
<vn-tr>
<vn-th number>Id</vn-th>
<vn-th number>Landed</vn-th>
<vn-th>Landed</vn-th>
<vn-th number>Quantity</vn-th>
<vn-th number>Claimed</vn-th>
<vn-th number>Description</vn-th>
<vn-th>Description</vn-th>
<vn-th number>Price</vn-th>
<vn-th number>Disc.</vn-th>
<vn-th number>Total</vn-th>
@ -65,10 +60,10 @@
{{("000000"+saleClaimed.sale.itemFk).slice(-6)}}
</span>
</vn-td>
<vn-td number>{{saleClaimed.sale.ticket.landed | dateTime: 'dd/MM/yyyy'}}</vn-td>
<vn-td>{{saleClaimed.sale.ticket.landed | dateTime: 'dd/MM/yyyy'}}</vn-td>
<vn-td number>{{saleClaimed.sale.quantity}}</vn-td>
<vn-td number>{{saleClaimed.quantity}}</vn-td>
<vn-td number>{{saleClaimed.sale.concept}}</vn-td>
<vn-td>{{saleClaimed.sale.concept}}</vn-td>
<vn-td number>{{saleClaimed.sale.price | currency:'€':2}}</vn-td>
<vn-td number>{{saleClaimed.sale.discount}} %</vn-td>
<vn-td number>
@ -83,39 +78,39 @@
No results
</vn-empty-rows>
</vn-table>
</vn-one>
</vn-horizontal>
<vn-horizontal>
<vn-one margin-medium-v>
<h5 translate>Development</h5>
</div>
</vn-auto>
<vn-auto>
<h4 translate>Development</h4>
<div style="overflow: auto">
<vn-table model="model">
<vn-thead>
<vn-tr>
<vn-th number>Reason</vn-th>
<vn-th number>Result</vn-th>
<vn-th number>Responsible</vn-th>
<vn-th number>Worker</vn-th>
<vn-th number>Redelivery</vn-th>
<vn-th>Reason</vn-th>
<vn-th>Result</vn-th>
<vn-th>Responsible</vn-th>
<vn-th>Worker</vn-th>
<vn-th>Redelivery</vn-th>
</vn-tr>
</vn-thead>
<vn-tbody>
<vn-tr ng-repeat="development in $ctrl.summary.developments">
<vn-td number>{{development.claimReason.description}}</vn-td>
<vn-td number>{{development.claimResult.description}}</vn-td>
<vn-td number>{{development.claimResponsible.description}}</vn-td>
<vn-td number>{{development.worker.firstName}}</vn-td>
<vn-td number>{{development.claimRedelivery.description}}</vn-td>
<vn-td>{{development.claimReason.description}}</vn-td>
<vn-td>{{development.claimResult.description}}</vn-td>
<vn-td>{{development.claimResponsible.description}}</vn-td>
<vn-td>{{development.worker.firstName}}</vn-td>
<vn-td>{{development.claimRedelivery.description}}</vn-td>
</vn-tr>
</vn-tbody>
<vn-empty-rows ng-if="model.data.length === 0" translate>
No results
</vn-empty-rows>
</vn-table>
</vn-one>
</vn-horizontal>
<vn-horizontal>
<vn-one margin-medium-v>
<h5 translate>Action</h5>
</div>
</vn-auto>
<vn-auto>
<h4 translate>Action</h4>
<div style="overflow: auto">
<vn-table model="model">
<vn-thead>
<vn-tr>
@ -157,11 +152,11 @@
No results
</vn-empty-rows>
</vn-table>
</vn-one>
</div>
</vn-auto>
</vn-horizontal>
</vn-vertical>
</vn-card>
</vn-vertical>
<vn-item-descriptor-popover vn-id="descriptor"
quicklinks="$ctrl.quicklinks">
</vn-card>
<vn-item-descriptor-popover
vn-id="descriptor"
quicklinks="$ctrl.quicklinks">
</vn-item-descriptor-popover>

View File

@ -6,8 +6,8 @@
data="addresses"
auto-load="true">
</vn-crud-model>
<vn-vertical>
<vn-card pad-large compact>
<div compact>
<vn-card pad-large>
<vn-title vn-one>Addresses</vn-title>
<vn-horizontal ng-repeat="address in addresses" class="pad-medium-top" style="align-items: center;">
<vn-one border-radius class="pad-small border-solid"
@ -67,4 +67,4 @@
icon="add"
label="Add">
</vn-float-button>
</vn-vertical>
</div>

View File

@ -1,5 +1,5 @@
<vn-vertical>
<vn-card pad-large compact>
<div compact>
<vn-card pad-large>
<vn-title vn-one>Contract credit insurance</vn-title>
<vn-horizontal ng-repeat="classification in $ctrl.classifications track by classification.id" class="pad-medium-top" style="align-items: center;">
<vn-one border-radius class="pad-small border-solid" ng-class="{'bg-main': !classification.finished,'bg-opacity-item': classification.finished}">
@ -55,7 +55,7 @@
vn-bind="+"
label="Add">
</vn-float-button>
</vn-vertical>
</div>
<vn-confirm
vn-id="close-contract"
on-response="$ctrl.returnDialog(response)"

View File

@ -30,10 +30,7 @@
</vn-empty-rows>
</vn-table>
</vn-vertical>
<vn-pagination
model="model"
scroll-selector="ui-view">
</vn-pagination>
<vn-pagination model="model"></vn-pagination>
</vn-card>
<vn-button-bar>
<button

View File

@ -31,10 +31,7 @@
</vn-empty-rows>
</vn-table>
</vn-vertical>
<vn-pagination
model="model"
scroll-selector="ui-view">
</vn-pagination>
<vn-pagination model="model"></vn-pagination>
</vn-card>
</vn-vertical>

View File

@ -1,4 +1,4 @@
<vn-card margin-medium-v class="vn-descriptor">
<vn-card class="vn-descriptor">
<vn-horizontal class="header">
<a translate-attr="{title: 'Return to module index'}" ui-sref="client.index">
<vn-icon icon="chevron_left"></vn-icon>

View File

@ -45,10 +45,7 @@
</vn-empty-rows>
</vn-table>
</vn-vertical>
<vn-pagination
model="model"
scroll-selector="ui-view">
</vn-pagination>
<vn-pagination model="model"></vn-pagination>
</vn-card>
</vn-vertical>

View File

@ -6,7 +6,6 @@
data="clients"
auto-load="false">
</vn-crud-model>
<div margin-medium>
<div class="vn-list">
<vn-card pad-medium-h>
@ -31,10 +30,7 @@
Enter a new search
</vn-empty-rows>
</vn-card>
<vn-pagination
model="model"
scroll-selector="ui-view">
</vn-pagination>
<vn-pagination model="model"></vn-pagination>
</div>
</div>
<a ui-sref="client.create" vn-tooltip="New client" vn-bind="+" fixed-bottom-right>

View File

@ -23,7 +23,7 @@ export default class Controller {
case 'name':
case 'socialName':
case 'city':
return {[param]: {regexp: `%${value}%`}};
return {[param]: {like: `%${value}%`}};
case 'id':
case 'fi':
case 'postcode':

View File

@ -33,7 +33,7 @@ List: Listado
New client: Nuevo cliente
Summary: Vista previa
Basic data: Datos básicos
Fiscal data: Datos Fiscales
Fiscal data: Datos fiscales
Pay method: Forma de pago
Addresses: Consignatarios
New address: Nuevo consignatario

View File

@ -35,9 +35,6 @@
</vn-empty-rows>
</vn-table>
</vn-vertical>
<vn-pagination
model="model"
scroll-selector="ui-view">
</vn-pagination>
<vn-pagination model="model"></vn-pagination>
</vn-card>
</vn-vertical>

View File

@ -43,10 +43,7 @@
</vn-empty-rows>
</vn-table>
</vn-vertical>
<vn-pagination
model="model"
scroll-selector="ui-view">
</vn-pagination>
<vn-pagination model="model"></vn-pagination>
</vn-card>
</vn-vertical>

View File

@ -91,10 +91,7 @@
</vn-empty-rows>
</vn-table>
</vn-vertical>
<vn-pagination
model="model"
scroll-selector="ui-view">
</vn-pagination>
<vn-pagination model="model"></vn-pagination>
</vn-card>
</vn-vertical>
<a ui-sref="client.card.risk.create"

View File

@ -35,10 +35,7 @@
</vn-empty-rows>
</vn-table>
</vn-vertical>
<vn-pagination
model="model"
scroll-selector="ui-view">
</vn-pagination>
<vn-pagination model="model"></vn-pagination>
</vn-card>
</vn-vertical>
<a ui-sref="client.card.sample.create" vn-tooltip="Send sample"

View File

@ -1,12 +1,8 @@
<vn-vertical vn-one>
<vn-card class="summary" pad-medium>
<vn-vertical margin-medium>
<vn-auto>
<h5 text-center pad-small-v class="title">{{$ctrl.summary.name}} - {{$ctrl.summary.id}} - {{$ctrl.summary.salesPerson.firstName}} {{$ctrl.summary.salesPerson.name}}</h5>
</vn-auto>
<vn-horizontal vn-one>
<vn-one margin-medium>
<h5 translate>Basic data</h5>
<vn-card class="summary">
<h5>{{$ctrl.summary.name}} - {{$ctrl.summary.id}} - {{$ctrl.summary.salesPerson.firstName}} {{$ctrl.summary.salesPerson.name}}</h5>
<vn-horizontal>
<vn-one>
<h4 translate>Basic data</h4>
<vn-label-value label="Id"
value="{{$ctrl.summary.id}}">
</vn-label-value>
@ -32,8 +28,8 @@
value="{{$ctrl.summary.contactChannel.name}}">
</vn-label-value>
</vn-one>
<vn-one margin-medium>
<h5 translate>Fiscal data</h5>
<vn-one>
<h4 translate>Fiscal address</h4>
<vn-label-value label="Social name"
value="{{$ctrl.summary.socialName}}">
</vn-label-value>
@ -55,52 +51,49 @@
<vn-label-value label="Country"
value="{{$ctrl.summary.country.country}}">
</vn-label-value>
</vn-one>
<vn-one>
<h4 translate>Fiscal data</h4>
<vn-vertical>
<vn-check vn-one
<vn-check
label="Is equalizated"
field="$ctrl.summary.isEqualizated"
disabled="true">
</vn-check>
<vn-check vn-one
<vn-check
label="Active"
field="$ctrl.summary.isActive"
disabled="true">
</vn-check>
<vn-check vn-one
<vn-check
label="Invoice by address"
field="$ctrl.summary.hasToInvoiceByAddress"
disabled="true">
</vn-check>
<vn-check vn-one
<vn-check
label="Verified data"
field="$ctrl.summary.isTaxDataChecked"
disabled="true">
</vn-check>
<vn-check vn-one
<vn-check
label="Has to invoice"
field="$ctrl.summary.hasToInvoice"
disabled="true">
</vn-check>
<vn-check vn-one
<vn-check
label="Invoice by mail"
field="$ctrl.summary.isToBeMailed"
disabled="true">
</vn-check>
<vn-check vn-one
<vn-check
label="Vies"
field="$ctrl.summary.isVies"
disabled="true">
</vn-check>
</vn-vertical>
</vn-one>
<vn-one margin-medium>
<h5 translate>Pay method</h5>
<vn-one>
<h4 translate>Pay method</h4>
<vn-label-value label="Pay method"
value="{{$ctrl.summary.payMethod.name}}">
</vn-label-value>
@ -111,29 +104,25 @@
value="{{$ctrl.summary.dueDay}}">
</vn-label-value>
<vn-vertical>
<vn-check vn-one
<vn-check
label="Received LCR"
field="$ctrl.summary.hasLcr"
disabled="true">
</vn-check>
<vn-check vn-one
<vn-check
label="Received core VNL"
field="$ctrl.summary.hasCoreVnl"
disabled="true">
</vn-check>
<vn-check vn-one
<vn-check
label="Received B2B VNL"
field="$ctrl.summary.hasSepaVnl"
disabled="true">
</vn-check>
</vn-vertical>
</vn-one>
</vn-horizontal>
<vn-horizontal vn-one>
<vn-one margin-medium>
<h5 translate>Default address</h5>
<vn-one>
<h4 translate>Default address</h4>
<vn-label-value label="Name"
value="{{$ctrl.summary.addresses[0].nickname}}">
</vn-label-value>
@ -144,57 +133,57 @@
value="{{$ctrl.summary.addresses[0].city}}">
</vn-label-value>
</vn-one>
<vn-one margin-medium>
<h5 translate>Web access</h5>
<vn-one>
<h4 translate>Web access</h4>
<vn-label-value label="User"
value="{{$ctrl.summary.account.name}}">
</vn-label-value>
<vn-vertical>
<vn-check vn-one
<vn-check
label="Enable web access"
field="$ctrl.summary.account.active"
disabled="true">
</vn-check>
</vn-vertical>
</vn-one>
<vn-one margin-medium>
<h5 translate>Business data</h5>
<vn-one>
<h4 translate>Business data</h4>
<vn-label-value label="Total greuge"
value="{{$ctrl.summary.totalGreuge | currency:'€ ':2}}">
value="{{$ctrl.summary.totalGreuge | currency:'€':2}}">
</vn-label-value>
<vn-label-value label="Mana"
value="{{$ctrl.summary.mana.mana | currency:'€ ':2}}">
value="{{$ctrl.summary.mana.mana | currency:'€':2}}">
</vn-label-value>
<vn-label-value label="Rate"
value="{{$ctrl.summary.claimsRatio[0].priceIncreasing | percentage}}">
</vn-label-value>
<vn-label-value label="Average invoiced"
value="{{$ctrl.summary.averageInvoiced.invoiced | currency:'€ ':2}}">
value="{{$ctrl.summary.averageInvoiced.invoiced | currency:'€':2}}">
</vn-label-value>
<vn-label-value label="Claims"
value="{{$ctrl.summary.claimsRatio[0].claimingRate | percentage}}">
</vn-label-value>
</vn-one>
<vn-one margin-medium>
<h5 translate>Financial information</h5>
<vn-one>
<h4 translate>Financial information</h4>
<vn-label-value label="Risk"
value="{{$ctrl.summary.debt.debt | currency:'€ ':2}}"
ng-class="{bold: $ctrl.summary.debt.debt > $ctrl.summary.credit}">
value="{{$ctrl.summary.debt.debt | currency:'€':2}}"
ng-class="{alert: $ctrl.summary.debt.debt > $ctrl.summary.credit}">
</vn-label-value>
<vn-label-value label="Credit"
value="{{$ctrl.summary.credit | currency:'€ ':2 }} "
ng-class="{bold: $ctrl.summary.credit > $ctrl.summary.creditInsurance ||
value="{{$ctrl.summary.credit | currency:'€':2 }} "
ng-class="{alert: $ctrl.summary.credit > $ctrl.summary.creditInsurance ||
($ctrl.summary.credit && $ctrl.summary.creditInsurance == null)}">
</vn-label-value>
<vn-label-value label="Secured credit"
value="{{$ctrl.summary.creditInsurance | currency:'€ ':2}} ({{$ctrl.summary.classifications[0].insurances[0].grade}})">
value="{{$ctrl.summary.creditInsurance | currency:'€':2}} ({{$ctrl.summary.classifications[0].insurances[0].grade}})">
</vn-label-value>
<vn-label-value label="Balance"
value="{{$ctrl.summary.sumRisk | currency:'€ ':2}}">
value="{{$ctrl.summary.sumRisk | currency:'€':2}}">
</vn-label-value>
<vn-label-value label="Balance due"
value="{{$ctrl.summary.defaulters[0].amount | currency:'€ ':2}}"
ng-class="{bold: $ctrl.summary.defaulters[0].amount}">
value="{{$ctrl.summary.defaulters[0].amount | currency:'€':2}}"
ng-class="{alert: $ctrl.summary.defaulters[0].amount}">
</vn-label-value>
<vn-vertical ng-if="$ctrl.summary.recovery.started">
<vn-label-value label="Recovery since"
@ -203,6 +192,4 @@
</vn-vertical>
</vn-one>
</vn-horizontal>
</vn-vertical>
</vn-card>
</vn-vertical>
</vn-card>

View File

@ -11,3 +11,4 @@ Balance due: Saldo vencido
Rate: Tarifa
Business data: Datos comerciales
Recovery since: Recobro desde
Fiscal address: Dirección fiscal

View File

@ -1,11 +1,7 @@
vn-dialog {
vn-client-summary vn-one {
min-width: 10em;
}
}
@import 'colors';
vn-client-summary {
.bold {
font-family: vn-font-bold;
.alert span {
color: $alert-01 !important
}
}

View File

@ -54,9 +54,6 @@
</vn-empty-rows>
</vn-table>
</vn-vertical>
<vn-pagination
model="model"
scroll-selector="ui-view">
</vn-pagination>
<vn-pagination model="model"></vn-pagination>
</vn-card>
</vn-vertical>

View File

@ -1,10 +1,7 @@
<vn-main-block>
<vn-horizontal>
<vn-auto class="left-block">
<vn-item-descriptor
margin-medium-v
item="$ctrl.item">
</vn-item-descriptor>
<vn-item-descriptor item="$ctrl.item"></vn-item-descriptor>
<vn-left-menu></vn-left-menu>
</vn-auto>
<vn-one>

View File

@ -20,7 +20,6 @@ class Controller {
reload() {
this.getCard();
}
}
Controller.$inject = ['$http', '$stateParams'];

View File

@ -33,12 +33,12 @@
</vn-auto>
<vn-horizontal class="state">
<vn-one>
<p class="title" uppercase text-center>Visible</p>
<h5 class="title" text-center>{{$ctrl.item.visible}}</h5>
<p translate>Visible</p>
<p>{{$ctrl.item.visible}}</p>
</vn-one>
<vn-one>
<p class="title" uppercase translate text-center>Available</p>
<h5 text-center class="title">{{$ctrl.item.available}}</h5>
<p translate>Available</p>
<p>{{$ctrl.item.available}}</p>
</vn-one>
</vn-horizontal>
<vn-auto pad-medium>

View File

@ -11,13 +11,11 @@ vn-item-diary {
width: 400px;
}
.balanceNegative .balance {
background-color: $main-01;
color: white;
color: $alert-01;
font-weight: bold;
}
.isIn .in {
background-color: $main-02;
color: white;
color: $main-02;
font-weight: bold;
}
.isToday .date{

View File

@ -33,9 +33,6 @@
</vn-empty-rows>
</vn-table>
</vn-vertical>
<vn-pagination
model="model"
scroll-selector="ui-view">
</vn-pagination>
<vn-pagination model="model"></vn-pagination>
</vn-card>
</vn-vertical>

View File

@ -8,6 +8,8 @@ import './card';
import './descriptor';
import './descriptor-popover';
import './ticket-descriptor';
import './ticket-descriptor/addStowaway';
import './ticket-descriptor/removeStowaway';
import './ticket-descriptor-popover';
import './data';
import './tags';

View File

@ -31,10 +31,7 @@
Enter a new search
</vn-empty-rows>
</vn-card>
<vn-pagination
model="model"
scroll-selector="ui-view">
</vn-pagination>
<vn-pagination model="model"></vn-pagination>
</div>
</div>
<a ui-sref="item.create" vn-tooltip="New item" vn-bind="+" fixed-bottom-right>

View File

@ -68,9 +68,6 @@
</vn-empty-rows>
</vn-table>
</vn-vertical>
<vn-pagination
model="model"
scroll-selector="ui-view">
</vn-pagination>
<vn-pagination model="model"></vn-pagination>
</vn-card>
</vn-vertical>

View File

@ -1,31 +1,25 @@
<vn-card class="summary">
<vn-vertical pad-medium>
<h5>{{$ctrl.item.id}} - {{$ctrl.summary.item.name}}</h5>
<vn-horizontal>
<vn-auto margin-medium>
<vn-vertical>
<vn-one>
<h5 text-center pad-small-v class="title">{{$ctrl.item.id}}</h5>
</vn-one>
<vn-one>
<img
<img style="width: 100%"
ng-src="//verdnatura.es/vn-image-data/catalog/200x200/{{$ctrl.item.image}}"
zoom-image="//verdnatura.es/vn-image-data/catalog/1600x900/{{$ctrl.item.image}}" on-error-src/>
</vn-one>
<vn-horizontal class="state">
<vn-one>
<p class="title" uppercase text-center>Visible</p>
<h5 class="title" text-center>{{$ctrl.summary.visible}}</h5>
<p translate>Visible</p>
<p>{{$ctrl.summary.visible}}</p>
</vn-one>
<vn-one>
<p class="title" uppercase translate text-center>Available</p>
<h5 text-center class="title">{{$ctrl.summary.available}}</h5>
<p translate>Available</p>
<p>{{$ctrl.summary.available}}</p>
</vn-one>
</vn-horizontal>
</vn-vertical>
</vn-auto>
<vn-one margin-medium>
<vn-vertical name="basicData">
<h5 translate>Basic data</h5>
</vn-one>
<vn-one name="basicData">
<h4 translate>Basic data</h4>
<vn-label-value label="Name"
value="{{$ctrl.summary.item.name}}">
</vn-label-value>
@ -47,11 +41,9 @@
<vn-label-value label="Buyer"
value="{{$ctrl.summary.item.itemType.worker.firstName}} {{$ctrl.summary.item.itemType.worker.name}}">
</vn-label-value>
</vn-vertical>
</vn-one>
<vn-one margin-medium>
<vn-vertical name="otherData">
<h5 translate>Other data</h5>
<vn-one name="otherData">
<h4 translate>Other data</h4>
<vn-label-value label="Intrastat code"
value="{{$ctrl.summary.item.intrastat.id}}">
</vn-label-value>
@ -74,35 +66,30 @@
value="{{$ctrl.summary.item.expence.name}}">
</vn-label-value>
</vn-one>
<vn-one margin-medium>
<vn-vertical name="tags">
<h5 translate>Tags</h5>
<vn-label-value label="{{tag.priority}} {{tag.tag.name}}" ng-repeat="tag in $ctrl.summary.tags track by tag.id"
<vn-one name="tags">
<h4 translate>Tags</h4>
<vn-label-value
label="{{tag.priority}} {{tag.tag.name}}"
ng-repeat="tag in $ctrl.summary.tags.slice(3, 6) track by tag.id"
value="{{tag.value}}">
</vn-label-value>
</vn-vertical>
</vn-one>
</vn-horizontal>
<vn-horizontal>
<vn-one margin-medium>
<vn-vertical name="tax">
<h5 translate>Tax</h5>
<vn-label-value label="{{tax.country.country}}" ng-repeat="tax in $ctrl.summary.item.taxes"
<vn-one name="tax">
<h4 translate>Tax</h4>
<vn-label-value label="{{tax.country.country}}"
ng-repeat="tax in $ctrl.summary.item.taxes"
value="{{tax.taxClass.description}}">
</vn-label-value>
</vn-vertical>
</vn-one>
<vn-one margin-medium>
<vn-vertical name="niche">
<h5 translate>Niche</h5>
<vn-label-value label="{{niche.warehouse.name}}" ng-repeat="niche in $ctrl.summary.niches"
<vn-one name="niche">
<h4 translate>Niche</h4>
<vn-label-value label="{{niche.warehouse.name}}"
ng-repeat="niche in $ctrl.summary.niches"
value="{{niche.code}}">
</vn-label-value>
</vn-vertical>
</vn-one>
<vn-one margin-medium>
<vn-vertical name="botanical">
<h5 translate>Botanical</h5>
<vn-one name="botanical">
<h4 translate>Botanical</h4>
<vn-label-value label="Botanical"
value="{{$ctrl.summary.botanical.botanical}}">
</vn-label-value>
@ -112,16 +99,12 @@
<vn-label-value label="Specie"
value="{{$ctrl.summary.botanical.specie.latin_species_name}}">
</vn-label-value>
</vn-vertical>
</vn-one>
<vn-one margin-medium>
<vn-vertical name="barcode">
<h5 translate>Barcode</h5>
<vn-one name="barcode">
<h4 translate>Barcode</h4>
<p ng-repeat="barcode in $ctrl.summary.item.itemBarcode track by $index">
<b>{{barcode.code}}</b>
</p>
</vn-vertical>
</vn-one>
</vn-horizontal>
</vn-vertical>
</vn-card>

View File

@ -1,5 +1,5 @@
vn-item-summary {
p{
p {
margin: 0;
}
}

View File

@ -0,0 +1,35 @@
<vn-dialog
vn-id="dialog"
class="modalForm"
on-open="$ctrl.getPossibleStowaways()">
<tpl-body>
<vn-horizontal pad-medium class="header">
<h5><span translate>Stowaways to add</span></h5>
</vn-horizontal>
<vn-horizontal pad-medium>
<vn-table>
<vn-thead>
<vn-tr>
<vn-th number>Ticket id</vn-th>
<vn-th number>Shipped</vn-th>
<vn-th number>Agency</vn-th>
<vn-th number>Warehouse</vn-th>
<vn-th number>State</vn-th>
</vn-tr>
</vn-thead>
<vn-tbody>
<vn-tr ng-repeat="ticket in $ctrl.possibleStowaways" class="clickable" ng-click="$ctrl.addStowaway($index)">
<vn-td number>{{ticket.id}}</vn-td>
<vn-td number>{{ticket.landed | dateTime: 'dd/MM/yyyy'}}</vn-td>
<vn-td number>{{ticket.agencyMode.name}}</vn-td>
<vn-td number>{{ticket.warehouse.name}}</vn-td>
<vn-td number>{{ticket.state.state.name}}</vn-td>
</vn-tr>
</vn-tbody>
<vn-empty-rows ng-if="$ctrl.possibleStowaways.length === 0" translate>
No results
</vn-empty-rows>
</vn-table>
</vn-horizontal>
</tpl-body>
</vn-dialog>

Some files were not shown because too many files have changed in this diff Show More