Merge branch 'test' into dev

This commit is contained in:
Juan Ferrer 2019-09-26 08:44:00 +02:00
commit 91e4e62a1c
47 changed files with 1156 additions and 589 deletions

View File

@ -0,0 +1,23 @@
ALTER TABLE `vn2008`.`gestdoc`
ADD COLUMN `contentType` VARCHAR(100) NULL AFTER `file`;
CREATE
OR REPLACE ALGORITHM = UNDEFINED
DEFINER = `root`@`%`
SQL SECURITY DEFINER
VIEW `vn`.`dms` AS
SELECT
`g`.`id` AS `id`,
`g`.`gesttip_id` AS `dmsTypeFk`,
`g`.`file` AS `file`,
`g`.`contentType` AS `contentType`,
`g`.`trabajador_id` AS `workerFk`,
`g`.`warehouse_id` AS `warehouseFk`,
`g`.`emp_id` AS `companyFk`,
`g`.`orden` AS `hardCopyNumber`,
`g`.`original` AS `hasFile`,
`g`.`sref` AS `reference`,
`g`.`brief` AS `description`,
`g`.`odbc_date` AS `created`
FROM
`vn2008`.`gestdoc` `g`;

View File

@ -9,10 +9,10 @@
</vn-icon>
</vn-auto>
<vn-one>
<strong>
<div>
<span translate>{{$ctrl.defaultDate | date: 'MMMM'}}</span>
<span>{{$ctrl.defaultDate | date: 'yyyy'}}</span>
</strong>
</div>
</vn-one>
<vn-auto>
<vn-icon
@ -23,7 +23,6 @@
</vn-icon>
</vn-auto>
</vn-horizontal>
<vn-vertical class="body">
<vn-horizontal class="weekdays">
<section title="{{'Monday' | translate}}"
@ -56,8 +55,10 @@
</section>
</vn-horizontal>
<vn-horizontal class="days">
<section ng-repeat="day in $ctrl.days" class="day"
ng-class="{'primary': day.events.length > 0}">
<section
ng-repeat="day in $ctrl.days"
class="day {{::$ctrl.getClass({$day: day.dated})}}"
ng-class="::{primary: day.events.length > 0 || $ctrl.hasEvents({$day: day.dated})}">
<div class="content">
<div class="day-number"
title="{{(day.eventName) | translate}}"

View File

@ -5,6 +5,9 @@ import './style.scss';
/**
* Flat calendar.
*
* @property {Array} data Array of events
* @property {Function} hasEvents Determines if an events exists for a day
* @property {Function} getClass Class to apply to specific day
*/
export default class Calendar extends Component {
constructor($element, $scope) {
@ -48,15 +51,24 @@ export default class Calendar extends Component {
* @param {Date} value - New default date
*/
set defaultDate(value) {
this._defaultDate = value;
if (value) {
value = new Date(value);
value.setHours(0, 0, 0, 0);
value.setDate(1);
}
this._defaultDate = value;
this.repaint();
}
/**
* Sets initial events
* Sets events
*
* @param {Array} value - Array of events
* @param {Date} event.dated - Day to add event
* @param {String} event.name - Tooltip description
* @param {String} event.className - ClassName style
* @param {Object} event.style - Style properties
*/
set data(value) {
if (!value) return;
@ -64,7 +76,9 @@ export default class Calendar extends Component {
this.events = [];
value.forEach(event => {
this.addEvent(event);
event.dated = new Date(event.dated);
event.dated.setHours(0, 0, 0, 0);
this.events.push(event);
});
if (this.defaultDate) {
@ -197,10 +211,10 @@ export default class Calendar extends Component {
const hasEvents = events.length > 0;
if (isCurrentMonth && isSunday && !hasEvents)
params.style = {color: '#f42121'};
params.style = {color: '#999'};
if (isCurrentMonth && isSaturday && !hasEvents)
params.style = {color: '#666666'};
params.style = {color: '#999'};
if (!isCurrentMonth)
params.style = {opacity: '0.5'};
@ -217,42 +231,6 @@ export default class Calendar extends Component {
this.days.push(params);
}
/**
* Adds a new calendar event
*
* @param {Object} options - Event params
* @param {Date} options.dated - Day to add event
* @param {String} options.name - Tooltip description
* @param {String} options.className - ClassName style
* @param {Object} options.style - Style properties
* @param {Boolean} options.isRemovable - True if is removable by users
*/
addEvent(options) {
if (!Object.hasOwnProperty.call(options, 'isRemovable'))
options.isRemovable = true;
options.dated = new Date(options.dated);
options.dated.setHours(0, 0, 0, 0);
this.events.push(options);
}
/**
* Removes an event from an array of events
* @param {Object} dated - Dated event
*/
removeEvent(dated) {
dated = new Date(dated);
dated.setHours(0, 0, 0, 0);
const event = this.events.findIndex(event => {
return event.dated >= dated && event.dated <= dated;
});
if (event > -1)
this.events.splice(event, 1);
}
/**
* Moves to next month(s)
*
@ -261,10 +239,7 @@ export default class Calendar extends Component {
moveNext(skip = 1) {
let next = this.defaultDate.getMonth() + skip;
this.defaultDate.setMonth(next);
this.defaultDate.setHours(0, 0, 0, 0);
this.defaultDate.setDate(1);
this.repaint();
this.emit('moveNext');
}
@ -276,12 +251,7 @@ export default class Calendar extends Component {
movePrevious(skip = 1) {
let previous = this.defaultDate.getMonth() - skip;
this.defaultDate.setMonth(previous);
this.defaultDate.setHours(0, 0, 0, 0);
const lastDate = this.lastDay(this.defaultDate);
this.defaultDate.setDate(lastDate.getDate());
this.repaint();
this.emit('movePrevious');
}
@ -327,6 +297,14 @@ export default class Calendar extends Component {
};
}
}
hasEvents() {
return false;
}
getClass() {
return '';
}
}
Calendar.$inject = ['$element', '$scope'];
@ -341,6 +319,8 @@ ngModule.component('vnCalendar', {
onSelection: '&?',
onMoveNext: '&?',
onMovePrevious: '&?',
hasEvents: '&?',
getClass: '&?',
displayControls: '<?',
disabled: '<?',
skip: '<?'

View File

@ -31,54 +31,6 @@ describe('Component vnCalendar', () => {
});
});
describe('addEvent()', () => {
it(`should add an event to an array of events`, () => {
controller.events = [];
controller.addEvent({
dated: new Date(),
name: 'My event'
});
const firstEvent = controller.events[0];
expect(firstEvent.name).toEqual('My event');
expect(firstEvent.isRemovable).toBeDefined();
expect(firstEvent.isRemovable).toBeTruthy();
});
it(`should not repeat an event for the same date`, () => {
const curDate = new Date();
curDate.setHours(0, 0, 0, 0);
controller.events = [{
dated: curDate,
name: 'My event 1'
}];
controller.addEvent({
dated: curDate,
name: 'My event 2'
});
const firstEvent = controller.events[0];
expect(controller.events.length).toEqual(2);
expect(firstEvent.name).toEqual('My event 1');
});
});
describe('removeEvent()', () => {
it(`should remove an event from an array of events`, () => {
const curDate = new Date();
controller._events = [{
dated: curDate,
name: 'My event 1',
className: 'color'
}];
controller.removeEvent(curDate);
expect(controller.events.length).toEqual(0);
});
});
describe('moveNext()', () => {
it(`should shift to the next n months, then emit a 'moveNext' event`, () => {
spyOn(controller, 'emit');

View File

@ -5,7 +5,6 @@ vn-calendar.small {
display: none
}
}
vn-calendar {
display: block;
@ -14,8 +13,6 @@ vn-calendar {
padding: 0.2em 0;
height: 1.5em
}
.weekdays {
color: $color-font-secondary;
margin-bottom: 0.5em;
@ -23,11 +20,9 @@ vn-calendar {
font-weight: bold;
font-size: 0.8em;
}
.weekdays section {
cursor: pointer
}
.weekdays section, .day {
position: relative;
text-align: center;
@ -35,14 +30,11 @@ vn-calendar {
width: 14.28%;
outline: 0;
}
.days {
justify-content: flex-start;
align-items: flex-start;
flex-wrap: wrap;
}
.day {
.content {
position: absolute;
@ -51,7 +43,6 @@ vn-calendar {
left: 0;
top: 0
}
.day-number {
transition: background-color 0.3s;
text-align:center;
@ -65,30 +56,24 @@ vn-calendar {
cursor: pointer;
outline: 0
}
.day-number:hover {
background-color: lighten($color-font-secondary, 20%);
opacity: 0.8
}
}
.day::after {
content: "";
display: block;
padding-top: 100%;
}
.day.primary .day-number {
background-color: $color-main;
color: $color-font-bg;
color: $color-font-dark;
}
.events {
margin-top: 0.5em;
font-size: 0.6em
}
.events {
color: $color-font-secondary;
@ -96,7 +81,6 @@ vn-calendar {
margin-bottom: .1em;
}
}
.chip {
background-color: $color-main;
color: $color-font-bg;
@ -105,15 +89,11 @@ vn-calendar {
padding: 0.3em .8em;
max-width: 5em;
}
.day.gray {
.day-number {
color: $color-font-secondary
}
}
.day.sunday {
.day-number {
color: $color-alert;

View File

@ -51,4 +51,9 @@ Create new one: Crear nuevo
Toggle: Desplegar/Plegar
Check all: Seleccionar todo
Select a file: Selecciona un fichero
Go up: Ir arriba
Edit: Editar
Edit item: Editar elemento
No records found: No se han encontrado elementos
Day: Día
Days: Días
Go up: Ir arriba

View File

@ -34,6 +34,13 @@ a, .link {
text-decoration: underline;
}
}
vn-bg-title {
display: block;
text-align: center;
padding: 1em;
color: gray;
font-size: 1.3em;
}
.totalBox {
border: 1px solid #CCC;
text-align: right !important;

View File

@ -62,6 +62,7 @@ $color-notice-medium: lighten($color-notice, 20%);
$color-notice-light: lighten($color-notice, 35%);
$color-alert-medium: lighten($color-alert, 20%);
$color-alert-light: lighten($color-alert, 35%);
/**/
// Dark theme
/*

View File

@ -0,0 +1,40 @@
module.exports = Self => {
Self.remoteMethod('getEvents', {
description: 'Returns delivery days for a postcode',
accepts: [
{
arg: 'agencyModeFk',
type: 'Number',
description: 'The agency mode id',
required: true
}, {
arg: 'provinceFk',
type: 'Number',
description: 'The province id',
required: true
}, {
arg: 'postCode',
type: 'String',
description: 'The postcode'
}
],
returns: {
type: 'Object',
root: true
},
http: {
path: `/getEvents`,
verb: 'GET'
}
});
Self.getEvents = async(agencyModeFk, provinceFk, postCode) => {
let [events, exclusions] = await Self.rawSql(
`CALL zone_getEvents(?, ?, ?)`,
[agencyModeFk, provinceFk, postCode]
);
return {events, exclusions};
};
};

View File

@ -14,10 +14,19 @@
"ZoneGeo": {
"dataSource": "vn"
},
"ZoneEvent": {
"dataSource": "vn"
},
"ZoneExclusion": {
"dataSource": "vn"
},
"ZoneCalendar": {
"dataSource": "vn"
},
"ZoneIncluded": {
"dataSource": "vn"
},
"ZoneWarehouse": {
"dataSource": "vn"
}
}

View File

@ -0,0 +1,9 @@
module.exports = Self => {
function rangeValid(err) {
if (this.from && this.to && this.from >= this.to)
err();
}
Self.validate('rangeValid', rangeValid, {
message: `Start date should be lower than end date`
});
};

View File

@ -0,0 +1,47 @@
{
"name": "ZoneEvent",
"base": "VnModel",
"options": {
"mysql": {
"table": "zoneEvent"
}
},
"properties": {
"id": {
"id": true,
"type": "Number"
},
"zoneFk": {
"id": true,
"type": "Number"
},
"from": {
"type": "Date"
},
"to": {
"type": "Date"
},
"weekDays": {
"type": "String"
},
"hour": {
"type": "Date"
},
"travelingDays": {
"type": "Number"
},
"price": {
"type": "Number"
},
"bonus": {
"type": "Number"
}
},
"relations": {
"zone": {
"type": "belongsTo",
"model": "Zone",
"foreignKey": "zoneFk"
}
}
}

View File

@ -0,0 +1,26 @@
{
"name": "ZoneExclusion",
"base": "VnModel",
"options": {
"mysql": {
"table": "zoneExclusion"
}
},
"properties": {
"id": {
"id": true,
"type": "Number"
},
"day": {
"type": "Date",
"required": true
}
},
"relations": {
"zone": {
"type": "belongsTo",
"model": "Zone",
"foreignKey": "zoneFk"
}
}
}

View File

@ -0,0 +1,27 @@
{
"name": "ZoneWarehouse",
"base": "VnModel",
"options": {
"mysql": {
"table": "zoneWarehouse"
}
},
"properties": {
"id": {
"id": true,
"type": "Number"
}
},
"relations": {
"zone": {
"type": "belongsTo",
"model": "Zone",
"foreignKey": "zoneFk"
},
"warehouse": {
"type": "belongsTo",
"model": "Warehouse",
"foreignKey": "warehouseFk"
}
}
}

View File

@ -2,10 +2,7 @@ module.exports = Self => {
require('../methods/zone/clone')(Self);
require('../methods/zone/editPrices')(Self);
require('../methods/zone/getLeaves')(Self);
Self.validatesPresenceOf('warehouseFk', {
message: `Warehouse cannot be blank`
});
require('../methods/zone/getEvents')(Self);
Self.validatesPresenceOf('agencyModeFk', {
message: `Agency cannot be blank`

View File

@ -41,15 +41,25 @@
"model": "ZoneGeo",
"foreignKey": "zoneFk"
},
"warehouse": {
"type": "belongsTo",
"model": "Warehouse",
"foreignKey": "warehouseFk"
},
"agencyMode": {
"type": "belongsTo",
"model": "AgencyMode",
"foreignKey": "agencyModeFk"
},
"events": {
"type": "hasMany",
"model": "ZoneEvent",
"foreignKey": "zoneFk"
},
"exclusions": {
"type": "hasMany",
"model": "ZoneExclusion",
"foreignKey": "zoneFk"
},
"warehouses": {
"type": "hasMany",
"model": "ZoneWarehouse",
"foreignKey": "zoneFk"
}
}
}

View File

@ -8,22 +8,13 @@
<form name="form" ng-submit="$ctrl.onSubmit()" compact>
<vn-card pad-large>
<vn-horizontal>
<vn-textfield vn-two vn-focus
<vn-textfield
label="Name"
field="$ctrl.zone.name"
vn-acl="deliveryBoss">
</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-acl="deliveryBoss">
</vn-autocomplete>
<vn-autocomplete
vn-one
field="$ctrl.zone.agencyModeFk"
@ -35,40 +26,47 @@
</vn-autocomplete>
</vn-horizontal>
<vn-horizontal>
<vn-input-number vn-two
<vn-input-number
label="Traveling days"
model="$ctrl.zone.travelingDays"
min="0" step="1"
min="0"
step="1"
vn-acl="deliveryBoss">
</vn-input-number>
<vn-input-time vn-two
label="Estimated hour (ETD)"
<vn-input-time
label="Closing"
model="$ctrl.zone.hour"
vn-acl="deliveryBoss">
</vn-input-time>
</vn-horizontal>
<vn-horizontal>
<vn-input-number vn-one
<vn-input-number
label="Price"
model="$ctrl.zone.price"
min="0" step="0.01"
min="0"
step="0.01"
vn-acl="deliveryBoss">
</vn-input-number>
<vn-input-number vn-one
<vn-input-number
label="Bonus"
model="$ctrl.zone.bonus"
min="0" step="0.01"
min="0"
step="0.01"
vn-acl="deliveryBoss">
</vn-input-number>
</vn-horizontal>
<vn-horizontal>
<vn-input-number vn-one
<vn-input-number
vn-one
label="Inflation"
model="$ctrl.zone.inflation"
min="0" step="0.01"
min="0"
step="0.01"
vn-acl="deliveryBoss">
</vn-input-number>
<vn-check label="Volumetric" vn-one
<vn-check
vn-one
label="Volumetric"
field="$ctrl.zone.isVolumetric"
vn-acl="deliveryBoss">
</vn-check>

View File

@ -1,74 +1,20 @@
<vn-crud-model
vn-id="model"
url="/agency/api/ZoneCalendars"
link="{zoneFk: $ctrl.$stateParams.id}"
data="$ctrl.data"
primary-key="zoneFk"
auto-load="true">
</vn-crud-model>
<vn-watcher
vn-id="watcher"
data="$ctrl.selectedDay">
</vn-watcher>
<vn-card pad-large>
<vn-horizontal pad-medium class="calendarControlsHeader">
<vn-icon-button icon="keyboard_arrow_left"
ng-click="$ctrl.onMovePrevious([stMonth, ndMonth])"
vn-tooltip="Previous">
</vn-icon-button>
<vn-icon-button icon="keyboard_arrow_right"
ng-click="$ctrl.onMoveNext([stMonth, ndMonth])"
vn-tooltip="Next">
</vn-icon-button>
</vn-horizontal>
<vn-horizontal>
<vn-calendar vn-id="stMonth" vn-one pad-medium
data="$ctrl.events"
display-controls="false"
on-selection="$ctrl.onSelection(values)"
skip="2" vn-acl="deliveryBoss">
</vn-calendar>
<vn-calendar vn-id="ndMonth" vn-one pad-medium
data="$ctrl.events"
display-controls="false"
on-selection="$ctrl.onSelection(values)"
default-date="$ctrl.ndMonthDate"
skip="2" vn-acl="deliveryBoss">
</vn-calendar>
</vn-horizontal>
</vn-card>
<!-- Edit price dialog -->
<vn-dialog class="edit"
vn-id="priceDialog"
on-close="$ctrl.onClose()"
on-response="$ctrl.onResponse(response)">
<tpl-body>
<h5 pad-small-v translate>Edit price</h5>
<vn-horizontal>
<vn-input-number vn-one
label="Price"
model="$ctrl.selectedDay.price"
min="0" step="0.01"
required="true">
</vn-input-number>
<vn-input-number vn-one
label="Bonus"
model="$ctrl.selectedDay.bonus"
min="0" step="0.01"
required="true">
</vn-input-number>
</vn-horizontal>
<vn-horizontal>
<vn-radio-group vn-one
field="$ctrl.selectedDay.option"
options="$ctrl.options">
</vn-radio-group>
</vn-horizontal>
</tpl-body>
<tpl-buttons>
<input type="button" response="CANCEL" translate-attr="{value: 'Cancel'}"/>
<button response="ACCEPT" translate>Save</button>
</tpl-buttons>
</vn-dialog>
<vn-calendar
vn-id="stMonth"
skip="2"
has-events="$ctrl.hasEvents($day)"
get-class="$ctrl.getClass($day)"
on-move-next="ndMonth.moveNext(2)"
on-move-previous="ndMonth.movePrevious(2)"
vn-acl="deliveryBoss"
pad-medium>
</vn-calendar>
<vn-calendar
vn-id="ndMonth"
skip="2"
has-events="$ctrl.hasEvents($day)"
get-class="$ctrl.getClass($day)"
default-date="$ctrl.ndMonthDate"
vn-acl="deliveryBoss"
display-controls="false"
pad-medium>
</vn-calendar>

View File

@ -2,133 +2,107 @@ import ngModule from '../module';
import './style.scss';
class Controller {
constructor($element, $scope, $http, $filter, $translate, $stateParams, vnApp) {
this.$element = $element;
this.$ = $scope;
this.$http = $http;
this.$filter = $filter;
this.$translate = $translate;
this.$stateParams = $stateParams;
this.vnApp = vnApp;
this.stMonthDate = new Date();
constructor($, $stateParams) {
Object.assign(this, {
$,
$stateParams
});
this.excls = {};
this.resetEvents();
this.ndMonthDate = new Date();
this.ndMonthDate.setMonth(this.ndMonthDate.getMonth() + 1);
this.selectedDay = {};
}
$postLink() {
this.stMonth = this.$.stMonth;
this.ndMonth = this.$.ndMonth;
resetEvents() {
this.wdays = [];
this.days = {};
this.ranges = [];
}
get data() {
return this._data;
get events() {
return this._events;
}
set data(value) {
this._data = value;
set events(value) {
this._events = value;
this.resetEvents();
if (!value) return;
const events = [];
value.forEach(event => {
events.push({
name: `P: ${this.$filter('currency')(event.price)}`,
description: 'Price',
dated: event.delivered,
style: {backgroundColor: '#a3d131'},
data: {price: event.price}
});
events.push({
name: `B: ${this.$filter('currency')(event.bonus)}`,
description: 'Bonus',
dated: event.delivered,
data: {bonus: event.bonus}
});
});
this.events = events;
}
onSelection(values) {
if (values.length > 1) return false;
this.options = [
{label: 'Only this day', value: 'Only this day'},
{label: 'From this day', value: 'From this day'},
{label: 'All days', value: 'All days'}
];
const selection = values[0];
const events = selection.events;
const hasEvents = events.length > 0;
if (!hasEvents)
return this.vnApp.showMessage(this.$translate.instant(`There's no delivery for this day`));
this.selectedDay = {
delivered: selection.dated,
option: 'Only this day'
};
events.forEach(event => {
this.selectedDay = Object.assign(this.selectedDay, event.data);
});
this.$.priceDialog.show();
}
onResponse(response) {
if (response == 'ACCEPT') {
try {
const data = {
delivered: this.selectedDay.delivered,
price: this.selectedDay.price,
bonus: this.selectedDay.bonus,
option: this.selectedDay.option
};
this.$.watcher.check();
const path = `/api/Zones/${this.zone.id}/editPrices`;
this.$http.post(path, data).then(() => {
this.vnApp.showSuccess(this.$translate.instant('Data saved!'));
this.$.model.refresh();
this.card.reload();
});
} catch (e) {
this.vnApp.showError(this.$translate.instant(e.message));
return false;
}
function setWdays(wdays, weekDays) {
let codes = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'];
if (!weekDays) return [];
weekDays = weekDays.split(',');
for (let wday of weekDays)
wdays[codes.indexOf(wday)] = true;
return wdays;
}
return this.onClose();
for (let event of value) {
if (event.from && event.to) {
this.ranges.push({
from: new Date(event.from).setHours(0, 0, 0, 0),
to: new Date(event.to).setHours(0, 0, 0, 0),
wdays: setWdays([], event.weekDays)
});
} else if (event.from) {
let day = new Date(event.from).setHours(0, 0, 0, 0);
this.days[day] = true;
} else
setWdays(this.wdays, event.weekDays);
}
this.repaint();
}
onClose() {
this.$.watcher.updateOriginalData();
get exclusions() {
return this._exclusions;
}
onMoveNext(calendars) {
calendars.forEach(calendar => {
calendar.moveNext(2);
set exclusions(value) {
this._exclusions = value;
this.excls = {};
if (!value) return;
value.forEach(exclusion => {
let day = new Date(exclusion.day).setHours(0, 0, 0, 0);
this.excls[day] = true;
});
this.repaint();
}
onMovePrevious(calendars) {
calendars.forEach(calendar => {
calendar.movePrevious(2);
});
hasRange(time, wday) {
let range = this.ranges.find(e => e.from <= time && e.to >= time);
return range && range.wdays[wday];
}
hasEvents(day) {
let time = day.getTime();
let wday = day.getDay();
return this.wdays[wday]
|| this.days[time]
|| this.hasRange(time, wday);
}
getClass(day) {
if (this.excls[day.getTime()])
return 'excluded';
}
repaint() {
this.$.stMonth.repaint();
this.$.ndMonth.repaint();
}
}
Controller.$inject = ['$element', '$scope', '$http', '$filter', '$translate', '$stateParams', 'vnApp'];
Controller.$inject = ['$scope', '$stateParams'];
ngModule.component('vnZoneCalendar', {
template: require('./index.html'),
controller: Controller,
bindings: {
zone: '<'
},
require: {
card: '^vnZoneCard'
events: '<?',
exclusions: '<?'
}
});

View File

@ -1,6 +0,0 @@
Prices: Precios
Edit price: Modificar precio
Only this day: Solo este día
From this day: A partir de este día
All days: Todos los días
There's no delivery for this day: No hay reparto para este día

View File

@ -1,7 +1,13 @@
vn-calendar:nth-child(2n + 1) {
border-right:1px solid #ddd
}
@import "variables";
.calendarControlsHeader {
justify-content: space-between;
vn-zone-calendar {
vn-calendar .day {
&.primary .day-number {
background-color: $color-success;
}
&.excluded .day-number {
background-color: $color-alert;
color: $color-font-dark;
}
}
}

View File

@ -1,7 +1,5 @@
<vn-main-block>
<vn-side-menu side="left">
<vn-zone-descriptor zone="$ctrl.zone"></vn-zone-descriptor>
<vn-left-menu></vn-left-menu>
</vn-side-menu>
<div class="content-block" ui-view></div>
</vn-main-block>
<vn-side-menu side="left">
<vn-zone-descriptor zone="$ctrl.zone"></vn-zone-descriptor>
<vn-left-menu></vn-left-menu>
</vn-side-menu>
<div class="content-block" ui-view></div>

View File

@ -12,10 +12,10 @@ class Controller {
getCard() {
let filter = {
include: [
{relation: 'warehouse', fields: ['name']},
{relation: 'agencyMode', fields: ['name']}
]
include: {
relation: 'agencyMode',
scope: {fields: ['name']}
}
};
let json = encodeURIComponent(JSON.stringify(filter));
let query = `/agency/api/Zones/${this.$stateParams.id}?filter=${json}`;

View File

@ -0,0 +1,47 @@
<div style="margin: 0 auto; max-width: 40em;">
<form ng-submit="$ctrl.onSubmit()">
<vn-card pad-medium>
<vn-vertical>
<vn-horizontal>
<vn-autocomplete
vn-one
label="Agency"
field="$ctrl.params.agencyModeFk"
url="/api/AgencyModes/isActive">
</vn-autocomplete>
</vn-horizontal>
<vn-horizontal>
<vn-autocomplete
vn-one
label="Province"
field="$ctrl.params.provinceFk"
url="/api/Provinces"
fields="['countryFk']"
include="'country'"
style="margin-right: .5em;">
<tpl-item>
<div>{{name}}</div>
<div style="font-size: .9em; color: gray; line-height: .8em;">
{{country.country}}
</div>
</tpl-item>
</vn-autocomplete>
<vn-textfield
vn-one
label="Postcode"
model="$ctrl.params.postCode">
</vn-textfield>
</vn-horizontal>
</vn-vertical>
</vn-card>
<vn-button-bar>
<vn-submit label="Query"></vn-submit>
</vn-button-bar>
</form>
<vn-card pad-medium margin-medium-top>
<vn-zone-calendar
events="events.events"
exclusions="events.exclusions">
</vn-zone-calendar>
</vn-card>
</div>

View File

@ -0,0 +1,22 @@
import ngModule from '../module';
import './style.scss';
class Controller {
constructor($, $http) {
Object.assign(this, {
$,
$http
});
}
onSubmit() {
this.$http.get(`/api/Zones/getEvents`, {params: this.params})
.then(res => this.$.events = res.data);
}
}
Controller.$inject = ['$scope', '$http'];
ngModule.component('vnZoneDeliveryDays', {
template: require('./index.html'),
controller: Controller
});

View File

@ -0,0 +1,12 @@
vn-zone-delivery-days {
vn-zone-calendar {
display: flex;
justify-content: center;
flex-wrap: wrap;
& > vn-calendar {
min-width: 16.5em;
}
}
}

View File

@ -0,0 +1,147 @@
<div class="main-with-right-menu">
<div class="vn-list" style="max-width: 30em;">
<vn-card ng-if="data.length">
<a
ng-repeat="row in data"
translate-attr="{title: 'Edit'}"
ng-click="$ctrl.onEdit(row, $event)"
class="vn-list-item">
<vn-horizontal>
<vn-one>
<div
ng-if="::row.from && !row.to"
margin-small-bottom>
{{::row.from | dateTime:'dd/MM/yyyy'}}
</div>
<div
ng-if="::!row.from || row.to"
margin-small-bottom>
<span ng-if="row.to">
{{::row.from | dateTime:'dd/MM/yyyy'}} - {{::row.to | dateTime:'dd/MM/yyyy'}}
</span>
<span ng-if="!row.to" translate>
Indefinitely
</span>
<span ng-if="row.weekDays">
({{::$ctrl.formatWdays(row.weekDays)}})
</span>
</div>
<vn-label-value
label="Closing"
value="{{::row.hour | dateTime:'hh:mm'}}">
</vn-label-value>
<vn-label-value
label="Traveling days"
value="{{::row.travelingDays}}">
</vn-label-value>
<vn-label-value
label="Price"
value="{{::row.price | currency:'EUR':2}}">
</vn-label-value>
<vn-label-value
label="Bonus"
value="{{::row.bonus | currency:'EUR':2}}">
</vn-label-value>
</vn-one>
<vn-horizontal class="buttons">
<vn-icon-button
icon="delete"
translate-attr="{title: 'Delete'}"
ng-click="$ctrl.onDelete(row.id, $event)">
</vn-icon-button>
</vn-horizontal>
</vn-horizontal>
</a>
</vn-card>
</div>
<vn-bg-title ng-if="!data">
<vn-spinner enable="true"></vn-spinner>
</vn-bg-title>
<vn-bg-title ng-if="data.length == 0" translate>
No records found
</vn-bg-title>
</div>
<vn-side-menu side="right">
<vn-zone-calendar
events="data"
exclusions="exclusions">
</vn-zone-calendar>
</vn-side-menu>
<vn-float-button
icon="add"
translate-attr="{title: 'Add'}"
vn-bind="+"
ng-click="$ctrl.onCreate()"
fixed-bottom-right
style="z-index: 10;">
</vn-float-button>
<vn-dialog
vn-id="dialog"
on-response="$ctrl.onSave(response)">
<tpl-body>
<vn-vertical>
<vn-radio-group
field="$ctrl.eventType"
options="$ctrl.options">
</vn-radio-group>
<div
ng-if="$ctrl.eventType != 'day'"
class="week-days">
<span
ng-repeat="wday in $ctrl.wdays"
ng-class="{marked: $ctrl.selected.wdays[wday.code]}"
ng-click="$ctrl.selected.wdays[wday.code] = !$ctrl.selected.wdays[wday.code]">
{{wday.abr}}
</span>
</div>
<vn-vertical ng-if="$ctrl.eventType == 'day'">
<vn-date-picker
label="Day"
model="$ctrl.selected.from">
</vn-date-picker>
</vn-vertical>
<vn-horizontal ng-if="$ctrl.eventType == 'range'">
<vn-date-picker
label="From"
model="$ctrl.selected.from">
</vn-date-picker>
<vn-date-picker
label="To"
model="$ctrl.selected.to">
</vn-date-picker>
</vn-horizontal>
<vn-input-time
label="Closing"
model="$ctrl.selected.hour">
</vn-input-time>
<vn-input-number
label="Traveling days"
model="$ctrl.selected.travelingDays"
min="0"
step="1">
</vn-input-number>
<vn-input-number
label="Price"
model="$ctrl.selected.price"
min="0"
step="0.01">
</vn-input-number>
<vn-input-number
label="Bonus"
model="$ctrl.selected.bonus"
min="0"
step="0.01">
</vn-input-number>
</vn-vertical>
</tpl-body>
<tpl-buttons>
<input type="button" response="CANCEL" translate-attr="{value: 'Cancel'}"/>
<button response="ACCEPT" translate>Save</button>
</tpl-buttons>
</vn-dialog>
<vn-confirm
vn-id="confirm"
message="This item will be deleted"
question="Are you sure you want to continue?"
on-response="$ctrl.delete(response)">
</vn-confirm>

View File

@ -0,0 +1,174 @@
import ngModule from '../module';
import './style.scss';
class Controller {
constructor($, _, $http, $stateParams) {
Object.assign(this, {
$,
_,
$http
});
this.wdays = [
{
code: 'mon',
name: 'Monday'
}, {
code: 'tue',
name: 'Tuesday'
}, {
code: 'wed',
name: 'Wednesday'
}, {
code: 'thu',
name: 'Thursday'
}, {
code: 'fri',
name: 'Friday'
}, {
code: 'sat',
name: 'Saturday'
}, {
code: 'sun',
name: 'Sunday'
}
];
this.abrWdays = {};
for (let wday of this.wdays) {
let locale = _.instant(wday.name);
this.abrWdays[wday.code] = locale.substr(0, 3);
wday.abr = locale.substr(0, 1);
}
this.options = [
{
label: 'One day',
value: 'day'
}, {
label: 'Range of dates',
value: 'range'
}, {
label: 'Indefinitely',
value: 'indefinitely'
}
];
this.$http.get(`/api/Zones/${$stateParams.id}/exclusions`)
.then(res => this.$.exclusions = res.data);
this.path = `/api/Zones/${$stateParams.id}/events`;
this.refresh();
}
refresh() {
this.$http.get(this.path)
.then(res => this.$.data = res.data);
}
formatWdays(weekDays) {
if (!weekDays) return;
let abrWdays = [];
for (let wday of weekDays.split(','))
abrWdays.push(this.abrWdays[wday]);
return abrWdays.length < 7
? abrWdays.join(', ')
: this._.instant('Everyday');
}
onEdit(row, event) {
if (event.defaultPrevented) return;
this.isNew = false;
if (row.from && !row.to)
this.eventType = 'day';
else if (!row.from)
this.eventType = 'indefinitely';
else
this.eventType = 'range';
this.selected = angular.copy(row);
this.selected.wdays = {};
if (row.weekDays) {
let weekDays = row.weekDays.split(',');
for (let day of weekDays)
this.selected.wdays[day] = true;
}
this.$.dialog.show();
}
onCreate() {
this.isNew = true;
this.eventType = 'day';
this.selected = {};
this.$.dialog.show();
}
onSave(response) {
if (response != 'ACCEPT') return;
let selected = this.selected;
if (this.eventType == 'indefinitely') {
selected.from = null;
selected.to = null;
}
if (this.eventType != 'day') {
let weekDays = [];
for (let wday in selected.wdays) {
if (selected.wdays[wday])
weekDays.push(wday);
}
selected.weekDays = weekDays.join(',');
} else {
selected.to = null;
selected.weekDays = '';
}
let req;
if (this.isNew)
req = this.$http.post(this.path, selected);
else
req = this.$http.put(`${this.path}/${selected.id}`, selected);
req.then(() => {
this.selected = null;
this.isNew = null;
this.$.dialog.hide();
this.refresh();
});
return false;
}
onDelete(id, event) {
event.preventDefault();
this.$.confirm.show();
this.deleteId = id;
}
delete(response) {
if (response != 'ACCEPT') return;
if (!this.deleteId) return;
this.$http.delete(`${this.path}/${this.deleteId}`)
.then(() => {
this.refresh();
this.deleteId = null;
});
}
}
Controller.$inject = ['$scope', '$translate', '$http', '$stateParams'];
ngModule.component('vnZoneEvents', {
template: require('./index.html'),
controller: Controller
});

View File

@ -0,0 +1,28 @@
@import "effects";
vn-zone-events {
.week-days {
margin-top: $margin-small;
margin-bottom: $margin-medium;
text-align: center;
& > span {
@extend %clickable;
border-radius: 50%;
padding: .4em;
margin: .2em;
display: inline-flex;
width: 1.5em;
height: 1.5em;
justify-content: center;
align-items: center;
outline: none;
background-color: rgba(0, 0, 0, .05);
&.marked {
background: $color-main;
color: $color-font-dark;
}
}
}
}

View File

@ -0,0 +1,53 @@
<vn-card
ng-if="data.length"
style="max-width: 25em; margin: 0 auto;">
<vn-table>
<vn-tbody>
<vn-tr ng-repeat="row in data | orderBy:'day'">
<vn-td>{{::row.day | dateTime:'dd/MM/yyyy'}}</vn-td>
<vn-td style="width: 1px; text-align: center">
<vn-icon-button
icon="delete"
translate-attr="{title: 'Delete'}"
ng-click="$ctrl.onDelete($index)">
</vn-icon-button>
</vn-td>
</vn-tr>
</vn-tbody>
</vn-table>
</vn-card>
<vn-bg-title ng-if="!data">
<vn-spinner enable="true"></vn-spinner>
</vn-bg-title>
<vn-bg-title ng-if="data.length == 0" translate>
No records found
</vn-bg-title>
<vn-float-button
icon="add"
translate-attr="{title: 'Add'}"
vn-bind="+"
ng-click="$ctrl.onCreate()"
fixed-bottom-right>
</vn-float-button>
<vn-dialog
vn-id="dialog"
on-response="$ctrl.onSave(response)">
<tpl-body>
<vn-vertical>
<vn-date-picker
label="Day"
model="$ctrl.selected.day">
</vn-date-picker>
</vn-vertical>
</tpl-body>
<tpl-buttons>
<input type="button" response="CANCEL" translate-attr="{value: 'Cancel'}"/>
<button response="ACCEPT" translate>Save</button>
</tpl-buttons>
</vn-dialog>
<vn-confirm
vn-id="confirm"
message="This item will be deleted"
question="Are you sure you want to continue?"
on-response="$ctrl.delete(response)">
</vn-confirm>

View File

@ -0,0 +1,60 @@
import ngModule from '../module';
class Controller {
constructor($, $http, $stateParams) {
Object.assign(this, {
$,
$http
});
this.path = `/api/Zones/${$stateParams.id}/exclusions`;
this.refresh();
}
refresh() {
this.$http.get(this.path)
.then(res => this.$.data = res.data);
}
onCreate() {
this.isNew = true;
this.selected = {};
this.$.dialog.show();
}
onSave(response) {
if (response != 'ACCEPT') return;
this.$http.post(this.path, this.selected)
.then(() => {
this.selected = null;
this.isNew = null;
this.$.dialog.hide();
this.refresh();
});
return false;
}
onDelete(index) {
this.$.confirm.show();
this.deleteIndex = index;
}
delete(response) {
if (response != 'ACCEPT') return;
let id = this.$.data[this.deleteIndex].id;
if (!id) return;
this.$http.delete(`${this.path}/${id}`)
.then(() => {
this.$.data.splice(this.deleteIndex, 1);
this.deleteIndex = null;
});
}
}
Controller.$inject = ['$scope', '$http', '$stateParams'];
ngModule.component('vnZoneExclusions', {
template: require('./index.html'),
controller: Controller
});

View File

@ -1,12 +1,17 @@
export * from './module';
import './main';
import './index/';
import './delivery-days';
import './summary';
import './card';
import './descriptor';
import './search-panel';
import './create';
import './basic-data';
import './location';
import './location/calendar';
import './warehouses';
import './events';
import './calendar';
import './exclusions';
import './location';
import './calendar';

View File

@ -18,27 +18,28 @@
</vn-searchbar>
</vn-card>
</div>
<vn-card margin-medium-v margin-huge-bottom>
<vn-card margin-medium-v margin-huge-bottom compact>
<vn-table model="model">
<vn-thead>
<vn-tr>
<vn-th field="id" number>Id</vn-th>
<vn-th field="name" expand>Name</vn-th>
<vn-th field="agencyModeFk">Agency</vn-th>
<vn-th field="warehouseFK">Warehouse</vn-th>
<vn-th field="hour" vn-tooltip="ETD" default-order="DESC" shrink>Hour</vn-th>
<vn-th field="price" number shrink>Price</vn-th>
<vn-th field="hour" shrink>Closing</vn-th>
<vn-th field="price" number>Price</vn-th>
<vn-th shrink></vn-th>
</vn-tr>
</vn-thead>
<vn-tbody>
<vn-tr ng-repeat="zone in zones" ui-sref="zone.card.location({id: zone.id})" class="clickable searchResult">
<vn-tr
ng-repeat="zone in zones"
ui-sref="zone.card.location({id: zone.id})"
class="clickable searchResult">
<vn-td number>{{::zone.id}}</vn-td>
<vn-td expand>{{::zone.name}}</vn-td>
<vn-td>{{::zone.agencyMode.name}}</vn-td>
<vn-td>{{::zone.warehouse.name}}</vn-td>
<vn-td shrink>{{::zone.hour | dateTime: 'HH:mm'}}</vn-td>
<vn-td number shrink>{{::zone.price | currency: 'EUR':2}}</vn-td>
<vn-td number>{{::zone.price | currency: 'EUR':2}}</vn-td>
<vn-td shrink>
<vn-horizontal class="buttons">
<vn-icon-button
@ -68,15 +69,16 @@
<vn-zone-summary zone="$ctrl.selectedZone"></vn-zone-summary>
</tpl-body>
</vn-dialog>
<!-- Clone confirmation -->
<vn-confirm
vn-id="clone"
on-response="$ctrl.onCloneAccept(response)"
question="Do you want to clone this zone?"
message="All it's properties will be copied">
</vn-confirm>
<!-- End clone confirmation -->
<a ui-sref="zone.create" vn-tooltip="New zone" vn-bind="+" fixed-bottom-right>
<a ui-sref="zone.create"
vn-tooltip="New zone"
vn-bind="+"
fixed-bottom-right>
<vn-float-button icon="add"
vn-acl="deliveryBoss"
vn-acl-action="remove">

View File

@ -6,10 +6,10 @@ export default class Controller {
this.$http = $http;
this.$state = $state;
this.filter = {
include: [
{relation: 'agencyMode', fields: ['name']},
{relation: 'warehouse', fields: ['name']}
]
include: {
relation: 'agencyMode',
scope: {fields: ['name']}
}
};
}
@ -19,7 +19,8 @@ export default class Controller {
return /^\d+$/.test(value)
? {id: value}
: {name: {like: `%${value}%`}};
case 'warehouseFk':
case 'name':
return {[param]: {like: `%${value}%`}};
case 'agencyModeFk':
return {[param]: value};
}

View File

@ -1,7 +1,10 @@
Agency: Agencia
Warehouses: Almacenes
Week days: Días de la semana
Exceptions: Excepciones
Exclusions: Exclusiones
Warehouse: Almacén
Hour: Hora (ETD)
ETD: Tiempo de salida estimado
Hour: Hora
Price: Precio
Locations: Localizaciones
This zone will be removed: La zona será eliminada
@ -11,4 +14,15 @@ New zone: Nueva zona
Volumetric: Volumétrico
Clone: Clonar
Search zone by id or name: Buscar zonas por identificador o nombre
Inflation: Inflación
From: Desde
To: Hasta
Closing: Cierre
One day: Un día
Range of dates: Rango de fechas
Indefinitely: Indefinido
Everyday: Todos los días
Delivery days: Días de entrega
Province: Provincia
Postcode: Código postal
Inflation: Inflación
Query: Consultar

View File

@ -1,23 +0,0 @@
<vn-crud-model
vn-id="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-calendar pad-small vn-id="stMonth" skip="2"
data="$ctrl.events"
on-selection="$ctrl.onSelection(values, stMonth)"
on-move-next="$ctrl.onMoveNext(ndMonth)"
on-move-previous="$ctrl.onMovePrevious(ndMonth)"
vn-acl="deliveryBoss">
</vn-calendar>
<vn-calendar pad-small vn-id="ndMonth" skip="2"
data="$ctrl.events"
display-controls="false"
on-selection="$ctrl.onSelection(values, ndMonth)"
default-date="$ctrl.ndMonthDate"
vn-acl="deliveryBoss">
</vn-calendar>

View File

@ -1,150 +0,0 @@
import ngModule from '../module';
class Controller {
constructor($element, $scope, $stateParams, $http) {
this.$element = $element;
this.$stateParams = $stateParams;
this.$scope = $scope;
this.$http = $http;
this.stMonthDate = new Date();
this.ndMonthDate = new Date();
this.ndMonthDate.setMonth(this.ndMonthDate.getMonth() + 1);
}
$postLink() {
this.stMonth = this.$scope.stMonth;
this.ndMonth = this.$scope.ndMonth;
}
// Disabled until implementation
// of holidays by node
/* 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,
className: 'red',
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({
name: 'Has delivery',
dated: event.delivered,
style: {backgroundColor: '#a3d131'}
});
});
this.events = events;
}
onSelection(values, calendar) {
let totalEvents = 0;
values.forEach(day => {
const exists = calendar.events.findIndex(event => {
return event.dated >= day.dated && event.dated <= day.dated
&& event.isRemovable;
});
if (exists > -1) totalEvents++;
});
if (totalEvents == 1 || totalEvents > (values.length / 2))
this.removeEvents(calendar, values);
else
this.insertEvents(calendar, values);
}
insertEvents(calendar, days) {
days.forEach(day => {
const event = calendar.events.find(event => {
return event.dated >= day.dated && event.dated <= day.dated;
});
if (event) return false;
this.$scope.model.insert({
zoneFk: this.zone.id,
delivered: day.dated,
price: this.zone.price,
bonus: this.zone.bonus
});
calendar.addEvent({
name: 'Has delivery',
dated: day.dated,
style: {backgroundColor: '#a3d131'}
});
});
this.$scope.model.save().then(() => {
this.events = calendar.events;
});
}
removeEvents(calendar, days) {
let dates = [];
days.forEach(day => {
const event = calendar.events.find(event => {
return event.dated >= day.dated && event.dated <= day.dated;
});
if (event && !event.isRemovable)
return false;
dates.push(day.dated);
calendar.removeEvent(day.dated);
});
if (dates.length == 0) return;
const params = {zoneFk: this.zone.id, dates};
this.$http.post('/agency/api/zoneCalendars/removeByDate', params).then(() => {
this.events = calendar.events;
});
}
onMoveNext(calendar) {
calendar.moveNext(2);
}
onMovePrevious(calendar) {
calendar.movePrevious(2);
}
}
Controller.$inject = ['$element', '$scope', '$stateParams', '$http'];
ngModule.component('vnZoneLocationCalendar', {
template: require('./calendar.html'),
controller: Controller,
bindings: {
zone: '<'
}
});

View File

@ -4,12 +4,14 @@
filter="::$ctrl.filter"
auto-load="false">
</vn-crud-model>
<div class="main-with-right-menu">
<vn-card compact pad-large>
<div compact>
<vn-card pad-large-h>
<vn-searchbar
on-search="$ctrl.onSearch($params)"
vn-focus>
</vn-searchbar>
</vn-card>
<vn-card pad-large margin-medium-top>
<vn-treeview
vn-id="treeview"
model="model"
@ -18,8 +20,4 @@
selectable="true">
</vn-treeview>
</vn-card>
<vn-side-menu side="right">
<vn-zone-location-calendar zone="::$ctrl.zone">
</vn-zone-location-calendar>
</vn-side-menu>
</div>

View File

@ -0,0 +1,14 @@
<vn-main-block>
<vn-side-menu side="left">
<ul class="menu">
<li>
<a translate ui-sref="zone.index">Zones</a>
</li>
<li>
<a translate ui-sref="zone.deliveryDays">Delivery days</a>
</li>
</ul>
</vn-side-menu>
<div class="content-block" ui-view></div>
</vn-main-block>

View File

@ -0,0 +1,6 @@
import ngModule from '../module';
import './style.scss';
ngModule.component('vnZone', {
template: require('./index.html')
});

View File

@ -0,0 +1,18 @@
@import "effects";
vn-zone {
ul.menu {
list-style-type: none;
padding: 0;
padding-top: $pad-medium;
margin: 0;
font-size: inherit;
& > li > a {
@extend %clickable;
display: block;
color: inherit;
padding: .6em 2em;
}
}
}

View File

@ -7,36 +7,39 @@
"menu": [
{"state": "zone.card.basicData", "icon": "settings"},
{"state": "zone.card.location", "icon": "my_location"},
{"state": "zone.card.calendar", "icon": "icon-deliveryprices"}
{"state": "zone.card.warehouses", "icon": "home"},
{"state": "zone.card.events", "icon": "today"},
{"state": "zone.card.exclusions", "icon": "block"}
],
"routes": [
{
"url": "/zone",
"state": "zone",
"abstract": true,
"component": "ui-view",
"component": "vn-zone",
"description": "Zones"
},
{
}, {
"url": "/index?q",
"state": "zone.index",
"component": "vn-zone-index",
"description": "Zones"
},
{
}, {
"url": "/delivery-days",
"state": "zone.deliveryDays",
"component": "vn-zone-delivery-days",
"description": "Delivery days"
}, {
"url": "/create",
"state": "zone.create",
"component": "vn-zone-create",
"description": "New zone"
},
{
}, {
"url": "/:id",
"state": "zone.card",
"component": "vn-zone-card",
"abstract": true,
"description": "Detail"
},
{
}, {
"url": "/summary",
"state": "zone.card.summary",
"component": "vn-zone-summary",
@ -44,8 +47,7 @@
"params": {
"zone": "$ctrl.zone"
}
},
{
}, {
"url": "/basic-data",
"state": "zone.card.basicData",
"component": "vn-zone-basic-data",
@ -53,8 +55,22 @@
"params": {
"zone": "$ctrl.zone"
}
},
{
}, {
"url": "/warehouses",
"state": "zone.card.warehouses",
"component": "vn-zone-warehouses",
"description": "Warehouses"
}, {
"url": "/events",
"state": "zone.card.events",
"component": "vn-zone-events",
"description": "Calendar"
}, {
"url": "/exclusions",
"state": "zone.card.exclusions",
"component": "vn-zone-exclusions",
"description": "Exclusions"
}, {
"url": "/location?q",
"state": "zone.card.location",
"component": "vn-zone-location",
@ -62,15 +78,6 @@
"params": {
"zone": "$ctrl.zone"
}
},
{
"url": "/calendar",
"state": "zone.card.calendar",
"component": "vn-zone-calendar",
"description": "Prices",
"params": {
"zone": "$ctrl.zone"
}
}
]
}

View File

@ -21,15 +21,7 @@
vn-one
label="Agency"
field="filter.agencyModeFk"
url="/agency/api/AgencyModes/isActive"
show-field="name"
value-field="id">
</vn-autocomplete>
<vn-autocomplete
vn-one
label="Warehouse"
field="filter.warehouseFk"
url="/agency/api/Warehouses"
url="/api/AgencyModes/isActive"
show-field="name"
value-field="id">
</vn-autocomplete>

View File

@ -8,9 +8,6 @@
<vn-label-value label="Name"
value="{{$ctrl.summary.name}}">
</vn-label-value>
<vn-label-value label="Warehouse"
value="{{$ctrl.summary.warehouse.name}}">
</vn-label-value>
<vn-label-value label="Agency"
value="{{$ctrl.summary.agencyMode.name}}">
</vn-label-value>

View File

@ -19,10 +19,7 @@ class Controller {
getSummary() {
let filter = {
include: [
{relation: 'warehouse', fields: ['name']},
{relation: 'agencyMode', fields: ['name']}
],
include: {relation: 'agencyMode', fields: ['name']},
where: {id: this.zone.id}
};
filter = encodeURIComponent(JSON.stringify((filter)));

View File

@ -0,0 +1,56 @@
<vn-card
ng-if="data.length"
style="max-width: 25em; margin: 0 auto;">
<vn-table>
<vn-tbody>
<vn-tr ng-repeat="row in data | orderBy:'warehouse.name'">
<vn-td>{{::row.warehouse.name}}</vn-td>
<vn-td style="width: 1px; text-align: center">
<vn-icon-button
icon="delete"
translate-attr="{title: 'Delete'}"
ng-click="$ctrl.onDelete($index)">
</vn-icon-button>
</vn-td>
</vn-tr>
</vn-tbody>
</vn-table>
</vn-card>
<vn-bg-title ng-if="!data">
<vn-spinner enable="true"></vn-spinner>
</vn-bg-title>
<vn-bg-title ng-if="data.length == 0" translate>
No records found
</vn-bg-title>
<vn-float-button
icon="add"
translate-attr="{title: 'Add'}"
vn-bind="+"
ng-click="$ctrl.onCreate()"
fixed-bottom-right>
</vn-float-button>
<vn-dialog
vn-id="dialog"
on-response="$ctrl.onSave(response)">
<tpl-body>
<vn-vertical>
<vn-autocomplete
field="$ctrl.selected.warehouseFk"
url="/api/Warehouses"
show-field="name"
value-field="id"
label="Warehouse">
</vn-autocomplete>
</vn-vertical>
</tpl-body>
<tpl-buttons>
<input type="button" response="CANCEL" translate-attr="{value: 'Cancel'}"/>
<button response="ACCEPT" translate>Save</button>
</tpl-buttons>
</vn-dialog>
<vn-confirm
vn-id="confirm"
message="This item will be deleted"
question="Are you sure you want to continue?"
on-response="$ctrl.delete(response)">
</vn-confirm>

View File

@ -0,0 +1,60 @@
import ngModule from '../module';
class Controller {
constructor($, _, $http, $stateParams) {
Object.assign(this, {
$,
$http
});
this.path = `/api/Zones/${$stateParams.id}/warehouses`;
this.refresh();
}
refresh() {
let filter = {include: 'warehouse'};
this.$http.get(this.path, {params: {filter}})
.then(res => this.$.data = res.data);
}
onCreate() {
this.selected = {};
this.$.dialog.show();
}
onSave(response) {
if (response != 'ACCEPT') return;
this.$http.post(this.path, this.selected)
.then(() => {
this.selected = null;
this.isNew = null;
this.$.dialog.hide();
this.refresh();
});
return false;
}
onDelete(index) {
this.$.confirm.show();
this.deleteIndex = index;
}
delete(response) {
if (response != 'ACCEPT') return;
let id = this.$.data[this.deleteIndex].id;
if (!id) return;
this.$http.delete(`${this.path}/${id}`)
.then(() => {
this.$.data.splice(this.deleteIndex, 1);
this.deleteIndex = null;
});
}
}
Controller.$inject = ['$scope', '$translate', '$http', '$stateParams'];
ngModule.component('vnZoneWarehouses', {
template: require('./index.html'),
controller: Controller
});