Merge pull request 'feat: refs #7354 deleted code and redirect to Lilium' (!2906) from 7354_ZoneMigration_End into dev
gitea/salix/pipeline/head This commit looks good
Details
gitea/salix/pipeline/head This commit looks good
Details
Reviewed-on: #2906 Reviewed-by: Alex Moreno <alexm@verdnatura.es>
This commit is contained in:
commit
5c3d1ca531
|
@ -1,68 +0,0 @@
|
|||
import selectors from '../../helpers/selectors.js';
|
||||
import getBrowser from '../../helpers/puppeteer';
|
||||
|
||||
describe('SmartTable SearchBar integration', () => {
|
||||
let browser;
|
||||
let page;
|
||||
beforeAll(async() => {
|
||||
browser = await getBrowser();
|
||||
page = browser.page;
|
||||
await page.loginAndModule('salesPerson', 'item');
|
||||
await page.waitToClick(selectors.globalItems.searchButton);
|
||||
});
|
||||
|
||||
afterAll(async() => {
|
||||
await browser.close();
|
||||
});
|
||||
|
||||
it('should search by type in searchBar, reload page and have same results', async() => {
|
||||
await page.waitToClick(selectors.itemsIndex.openAdvancedSearchButton);
|
||||
await page.autocompleteSearch(selectors.itemsIndex.advancedSearchItemType, 'Anthurium');
|
||||
await page.waitToClick(selectors.itemsIndex.advancedSearchButton);
|
||||
await page.waitForNumberOfElements(selectors.itemsIndex.searchResult, 4);
|
||||
|
||||
await page.reload({
|
||||
waitUntil: 'networkidle2'
|
||||
});
|
||||
|
||||
await page.waitForNumberOfElements(selectors.itemsIndex.searchResult, 4);
|
||||
|
||||
await page.write(selectors.itemsIndex.advancedSmartTableGrouping, '1');
|
||||
await page.keyboard.press('Enter');
|
||||
await page.waitForNumberOfElements(selectors.itemsIndex.searchResult, 2);
|
||||
|
||||
await page.reload({
|
||||
waitUntil: 'networkidle2'
|
||||
});
|
||||
|
||||
await page.waitForNumberOfElements(selectors.itemsIndex.searchResult, 1);
|
||||
});
|
||||
|
||||
it('should filter in section without smart-table and search in searchBar go to zone section', async() => {
|
||||
await page.loginAndModule('salesPerson', 'zone');
|
||||
await page.waitToClick(selectors.globalItems.searchButton);
|
||||
|
||||
await page.doSearch('A');
|
||||
const firstCount = await page.countElement(selectors.zoneIndex.searchResult);
|
||||
|
||||
await page.doSearch('A');
|
||||
const secondCount = await page.countElement(selectors.zoneIndex.searchResult);
|
||||
|
||||
expect(firstCount).toEqual(7);
|
||||
expect(secondCount).toEqual(7);
|
||||
});
|
||||
|
||||
it('should order orders by first id and order by last id, reload page and have same order', async() => {
|
||||
await page.loginAndModule('developer', 'item');
|
||||
await page.accessToSection('item.fixedPrice');
|
||||
await page.keyboard.press('Enter');
|
||||
|
||||
await page.waitForTextInField(selectors.itemFixedPrice.firstItemID, '1');
|
||||
|
||||
await page.waitToClick(selectors.itemFixedPrice.orderColumnId);
|
||||
await page.reload({
|
||||
waitUntil: 'networkidle2'
|
||||
});
|
||||
await page.waitForTextInField(selectors.itemFixedPrice.firstItemID, '3');
|
||||
});
|
||||
});
|
|
@ -1,104 +0,0 @@
|
|||
import selectors from '../../helpers/selectors.js';
|
||||
import getBrowser from '../../helpers/puppeteer';
|
||||
|
||||
describe('Zone basic data path', () => {
|
||||
let browser;
|
||||
let page;
|
||||
|
||||
beforeAll(async() => {
|
||||
browser = await getBrowser();
|
||||
page = browser.page;
|
||||
|
||||
await page.loginAndModule('deliveryAssistant',
|
||||
'zone'); // turns up the zone module name and route aint the same lol
|
||||
await page.accessToSearchResult('10');
|
||||
await page.accessToSection('zone.card.basicData');
|
||||
});
|
||||
|
||||
afterAll(async() => {
|
||||
await browser.close();
|
||||
});
|
||||
|
||||
it('should reach the basic data section', async() => {
|
||||
await page.waitForState('zone.card.basicData');
|
||||
});
|
||||
|
||||
it('should edit de form and then save', async() => {
|
||||
await page.clearInput(selectors.zoneBasicData.name);
|
||||
await page.write(selectors.zoneBasicData.name, 'Brimstone teleportation');
|
||||
await page.autocompleteSearch(selectors.zoneBasicData.agency, 'Quantum break device');
|
||||
await page.clearInput(selectors.zoneBasicData.maxVolume);
|
||||
await page.write(selectors.zoneBasicData.maxVolume, '10');
|
||||
await page.clearInput(selectors.zoneBasicData.travelingDays);
|
||||
await page.write(selectors.zoneBasicData.travelingDays, '1');
|
||||
await page.clearInput(selectors.zoneBasicData.closing);
|
||||
await page.pickTime(selectors.zoneBasicData.closing, '21:00');
|
||||
await page.clearInput(selectors.zoneBasicData.price);
|
||||
await page.write(selectors.zoneBasicData.price, '999');
|
||||
await page.clearInput(selectors.zoneBasicData.bonus);
|
||||
await page.write(selectors.zoneBasicData.bonus, '100');
|
||||
await page.clearInput(selectors.zoneBasicData.inflation);
|
||||
await page.write(selectors.zoneBasicData.inflation, '200');
|
||||
await page.waitToClick(selectors.zoneBasicData.volumetric);
|
||||
await page.waitToClick(selectors.zoneBasicData.saveButton);
|
||||
const message = await page.waitForSnackbar();
|
||||
|
||||
expect(message.text).toContain('Data saved!');
|
||||
});
|
||||
|
||||
it('should now reload the section', async() => {
|
||||
await page.reloadSection('zone.card.basicData');
|
||||
});
|
||||
|
||||
it('should confirm the name was updated', async() => {
|
||||
const result = await page.waitToGetProperty(selectors.zoneBasicData.name, 'value');
|
||||
|
||||
expect(result).toEqual('Brimstone teleportation');
|
||||
});
|
||||
|
||||
it('should confirm the agency was updated', async() => {
|
||||
const result = await page.waitToGetProperty(selectors.zoneBasicData.agency, 'value');
|
||||
|
||||
expect(result).toEqual('Quantum break device');
|
||||
});
|
||||
|
||||
it('should confirm the max volume was updated', async() => {
|
||||
const result = await page.waitToGetProperty(selectors.zoneBasicData.maxVolume, 'value');
|
||||
|
||||
expect(result).toEqual('10');
|
||||
});
|
||||
|
||||
it('should confirm the traveling days were updated', async() => {
|
||||
const result = await page.waitToGetProperty(selectors.zoneBasicData.travelingDays, 'value');
|
||||
|
||||
expect(result).toEqual('1');
|
||||
});
|
||||
|
||||
it('should confirm the closing hour was updated', async() => {
|
||||
const result = await page.waitToGetProperty(selectors.zoneBasicData.closing, 'value');
|
||||
|
||||
expect(result).toEqual('21:00');
|
||||
});
|
||||
|
||||
it('should confirm the price was updated', async() => {
|
||||
const result = await page.waitToGetProperty(selectors.zoneBasicData.price, 'value');
|
||||
|
||||
expect(result).toEqual('999');
|
||||
});
|
||||
|
||||
it('should confirm the bonus was updated', async() => {
|
||||
const result = await page.waitToGetProperty(selectors.zoneBasicData.bonus, 'value');
|
||||
|
||||
expect(result).toEqual('100');
|
||||
});
|
||||
|
||||
it('should confirm the inflation was updated', async() => {
|
||||
const result = await page.waitToGetProperty(selectors.zoneBasicData.inflation, 'value');
|
||||
|
||||
expect(result).toEqual('200');
|
||||
});
|
||||
|
||||
it('should confirm the volumetric checkbox was checked', async() => {
|
||||
await page.waitForClassPresent(selectors.zoneBasicData.volumetric, 'checked');
|
||||
});
|
||||
});
|
|
@ -1,32 +0,0 @@
|
|||
import selectors from '../../helpers/selectors.js';
|
||||
import getBrowser from '../../helpers/puppeteer';
|
||||
|
||||
describe('Zone descriptor path', () => {
|
||||
let browser;
|
||||
let page;
|
||||
|
||||
beforeAll(async() => {
|
||||
browser = await getBrowser();
|
||||
page = browser.page;
|
||||
await page.loginAndModule('deliveryAssistant', 'zone');
|
||||
await page.accessToSearchResult('13');
|
||||
});
|
||||
|
||||
afterAll(async() => {
|
||||
await browser.close();
|
||||
});
|
||||
|
||||
it('should eliminate the zone using the descriptor option', async() => {
|
||||
await page.waitToClick(selectors.zoneDescriptor.menu);
|
||||
await page.waitToClick(selectors.zoneDescriptor.deleteZone);
|
||||
await page.respondToDialog('accept');
|
||||
await page.waitForState('zone.index');
|
||||
});
|
||||
|
||||
it('should search for the deleted zone to find no results', async() => {
|
||||
await page.doSearch('13');
|
||||
const count = await page.countElement(selectors.zoneIndex.searchResult);
|
||||
|
||||
expect(count).toEqual(0);
|
||||
});
|
||||
});
|
|
@ -1,114 +0,0 @@
|
|||
<mg-ajax path="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()"
|
||||
class="vn-w-md">
|
||||
<vn-card class="vn-pa-lg">
|
||||
<vn-horizontal>
|
||||
<vn-textfield
|
||||
label="Name"
|
||||
ng-model="$ctrl.zone.name"
|
||||
vn-acl="deliveryAssistant"
|
||||
rule>
|
||||
</vn-textfield>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-autocomplete
|
||||
vn-one
|
||||
ng-model="$ctrl.zone.agencyModeFk"
|
||||
url="AgencyModes"
|
||||
show-field="name"
|
||||
value-field="id"
|
||||
label="Agency"
|
||||
vn-acl="deliveryAssistant"
|
||||
rule>
|
||||
</vn-autocomplete>
|
||||
<vn-input-number
|
||||
vn-one
|
||||
label="Max m³"
|
||||
ng-model="$ctrl.zone.itemMaxSize"
|
||||
min="0"
|
||||
vn-acl="deliveryAssistant"
|
||||
rule>
|
||||
</vn-input-number>
|
||||
<vn-input-number
|
||||
vn-one
|
||||
label="Maximum m³"
|
||||
ng-model="$ctrl.zone.m3Max"
|
||||
min="0"
|
||||
vn-acl="deliveryAssistant"
|
||||
rule>
|
||||
</vn-input-number>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-input-number
|
||||
label="Traveling days"
|
||||
ng-model="$ctrl.zone.travelingDays"
|
||||
min="0"
|
||||
step="1"
|
||||
vn-acl="deliveryAssistant"
|
||||
rule>
|
||||
</vn-input-number>
|
||||
<vn-input-time
|
||||
label="Closing"
|
||||
ng-model="$ctrl.zone.hour"
|
||||
vn-acl="deliveryAssistant"
|
||||
rule>
|
||||
</vn-input-time>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-input-number
|
||||
label="Price"
|
||||
ng-model="$ctrl.zone.price"
|
||||
min="0"
|
||||
step="0.01"
|
||||
vn-acl="deliveryAssistant"
|
||||
rule>
|
||||
</vn-input-number>
|
||||
<vn-input-number
|
||||
label="Bonus"
|
||||
ng-model="$ctrl.zone.bonus"
|
||||
step="0.01"
|
||||
vn-acl="deliveryAssistant"
|
||||
rule>
|
||||
</vn-input-number>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-input-number
|
||||
vn-one
|
||||
label="Inflation"
|
||||
ng-model="$ctrl.zone.inflation"
|
||||
min="0"
|
||||
step="0.01"
|
||||
vn-acl="deliveryAssistant"
|
||||
rule>
|
||||
</vn-input-number>
|
||||
<vn-check
|
||||
vn-one
|
||||
label="Volumetric"
|
||||
ng-model="$ctrl.zone.isVolumetric"
|
||||
vn-acl="deliveryAssistant"
|
||||
rule>
|
||||
</vn-check>
|
||||
</vn-horizontal>
|
||||
</vn-card>
|
||||
<vn-button-bar>
|
||||
<vn-submit
|
||||
disabled="!watcher.dataChanged()"
|
||||
vn-acl="deliveryAssistant"
|
||||
label="Save">
|
||||
</vn-submit>
|
||||
<vn-button
|
||||
class="cancel"
|
||||
label="Undo changes"
|
||||
disabled="!watcher.dataChanged()"
|
||||
ng-click="watcher.loadOriginalData()">
|
||||
</vn-button>
|
||||
</vn-button-bar>
|
||||
</form>
|
|
@ -1,21 +0,0 @@
|
|||
import ngModule from '../module';
|
||||
import Section from 'salix/components/section';
|
||||
|
||||
class Controller extends Section {
|
||||
onSubmit() {
|
||||
this.$.watcher.submit().then(() =>
|
||||
this.card.reload()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ngModule.vnComponent('vnZoneBasicData', {
|
||||
template: require('./index.html'),
|
||||
controller: Controller,
|
||||
bindings: {
|
||||
zone: '<'
|
||||
},
|
||||
require: {
|
||||
card: '^vnZoneCard'
|
||||
}
|
||||
});
|
|
@ -1,33 +0,0 @@
|
|||
<vn-card>
|
||||
<div class="header">
|
||||
<vn-button
|
||||
icon="navigate_before"
|
||||
ng-click="$ctrl.step(-1)"
|
||||
class="flat">
|
||||
</vn-button>
|
||||
<div>
|
||||
<span translate>{{$ctrl.firstDay | date:'MMMM'}}</span>
|
||||
<span>{{$ctrl.firstDay | date:'yyyy'}} -</span>
|
||||
<span translate>{{$ctrl.lastDay | date:'MMMM'}}</span>
|
||||
<span>{{$ctrl.lastDay | date:'yyyy'}}</span>
|
||||
</div>
|
||||
<vn-button
|
||||
icon="navigate_next"
|
||||
ng-click="$ctrl.step(1)"
|
||||
class="flat">
|
||||
</vn-button>
|
||||
</div>
|
||||
<div class="calendars vn-pa-md">
|
||||
<vn-calendar
|
||||
ng-repeat="date in $ctrl.months track by date.getTime()"
|
||||
default-date="date"
|
||||
display-controls="false"
|
||||
hide-contiguous="true"
|
||||
has-events="$ctrl.hasEvents($day)"
|
||||
get-class="$ctrl.getClass($day)"
|
||||
on-selection="$ctrl.onSelection($event, $days, $type, $weekday)"
|
||||
class="vn-pa-md"
|
||||
style="min-width: 250px; flex: 1;">
|
||||
</vn-calendar>
|
||||
</div>
|
||||
</vn-card>
|
|
@ -1,191 +0,0 @@
|
|||
import ngModule from '../module';
|
||||
import Component from 'core/lib/component';
|
||||
import './style.scss';
|
||||
|
||||
class Controller extends Component {
|
||||
constructor($element, $, vnWeekDays) {
|
||||
super($element, $);
|
||||
this.vnWeekDays = vnWeekDays;
|
||||
this.nMonths = 4;
|
||||
|
||||
let date = Date.vnNew();
|
||||
date.setDate(1);
|
||||
date.setHours(0, 0, 0, 0);
|
||||
this.date = date;
|
||||
}
|
||||
|
||||
get date() {
|
||||
return this._date;
|
||||
}
|
||||
|
||||
set date(value) {
|
||||
this._date = value;
|
||||
let stamp = value.getTime();
|
||||
|
||||
let firstDay = new Date(stamp);
|
||||
firstDay.setDate(1);
|
||||
this.firstDay = firstDay;
|
||||
|
||||
let lastDay = new Date(stamp);
|
||||
lastDay.setMonth(lastDay.getMonth() + this.nMonths);
|
||||
lastDay.setDate(0);
|
||||
this.lastDay = lastDay;
|
||||
|
||||
this.months = [];
|
||||
for (let i = 0; i < this.nMonths; i++) {
|
||||
let monthDate = new Date(stamp);
|
||||
monthDate.setMonth(value.getMonth() + i);
|
||||
this.months.push(monthDate);
|
||||
}
|
||||
|
||||
this.refreshEvents();
|
||||
}
|
||||
|
||||
step(direction) {
|
||||
let date = new Date(this.date.getTime());
|
||||
date.setMonth(date.getMonth() + (this.nMonths * direction));
|
||||
this.date = date;
|
||||
|
||||
this.emit('step');
|
||||
}
|
||||
|
||||
get data() {
|
||||
return this._data;
|
||||
}
|
||||
|
||||
set data(value) {
|
||||
this._data = value;
|
||||
|
||||
value = value || {};
|
||||
|
||||
this.events = value.events;
|
||||
|
||||
function toStamp(date) {
|
||||
return date && new Date(date).setHours(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
this.exclusions = {};
|
||||
let exclusions = value.exclusions;
|
||||
|
||||
if (exclusions) {
|
||||
for (let exclusion of exclusions) {
|
||||
let stamp = toStamp(exclusion.dated);
|
||||
if (!this.exclusions[stamp]) this.exclusions[stamp] = [];
|
||||
this.exclusions[stamp].push(exclusion);
|
||||
}
|
||||
}
|
||||
|
||||
this.geoExclusions = {};
|
||||
let geoExclusions = value.geoExclusions;
|
||||
|
||||
if (geoExclusions) {
|
||||
for (let geoExclusion of geoExclusions) {
|
||||
let stamp = toStamp(geoExclusion.dated);
|
||||
if (!this.geoExclusions[stamp]) this.geoExclusions[stamp] = [];
|
||||
this.geoExclusions[stamp].push(geoExclusion);
|
||||
}
|
||||
}
|
||||
|
||||
let events = value.events;
|
||||
|
||||
if (events) {
|
||||
for (let event of events) {
|
||||
event.dated = toStamp(event.dated);
|
||||
event.ended = toStamp(event.ended);
|
||||
event.started = toStamp(event.started);
|
||||
event.wdays = this.vnWeekDays.fromSet(event.weekDays);
|
||||
}
|
||||
}
|
||||
|
||||
this.refreshEvents();
|
||||
|
||||
let calendars = this.element.querySelectorAll('vn-calendar');
|
||||
for (let calendar of calendars)
|
||||
calendar.$ctrl.repaint();
|
||||
}
|
||||
|
||||
refreshEvents() {
|
||||
this.days = {};
|
||||
if (!this.data) return;
|
||||
|
||||
let day = new Date(this.firstDay.getTime());
|
||||
|
||||
while (day <= this.lastDay) {
|
||||
let stamp = day.getTime();
|
||||
let wday = day.getDay();
|
||||
let dayEvents = [];
|
||||
let exclusions = this.exclusions[stamp] || [];
|
||||
|
||||
if (this.events) {
|
||||
for (let event of this.events) {
|
||||
let match;
|
||||
|
||||
switch (event.type) {
|
||||
case 'day':
|
||||
match = event.dated == stamp;
|
||||
break;
|
||||
default:
|
||||
match = event.wdays[wday]
|
||||
&& (!event.started || stamp >= event.started)
|
||||
&& (!event.ended || stamp <= event.ended);
|
||||
break;
|
||||
}
|
||||
|
||||
if (match && !exclusions.find(e => e.zoneFk == event.zoneFk))
|
||||
dayEvents.push(event);
|
||||
}
|
||||
}
|
||||
|
||||
if (dayEvents.length)
|
||||
this.days[stamp] = dayEvents;
|
||||
|
||||
day.setDate(day.getDate() + 1);
|
||||
}
|
||||
}
|
||||
|
||||
onSelection($event, $days, $type, $weekday) {
|
||||
let $events = [];
|
||||
let $exclusions = [];
|
||||
let $geoExclusions = [];
|
||||
|
||||
for (let day of $days) {
|
||||
let stamp = day.getTime();
|
||||
$events = $events.concat(this.days[stamp] || []);
|
||||
$exclusions = $exclusions.concat(this.exclusions[stamp] || []);
|
||||
$geoExclusions = $geoExclusions.concat(this.geoExclusions[stamp] || []);
|
||||
}
|
||||
|
||||
this.emit('selection', {
|
||||
$event,
|
||||
$days,
|
||||
$type,
|
||||
$weekday,
|
||||
$events,
|
||||
$exclusions,
|
||||
$geoExclusions
|
||||
});
|
||||
}
|
||||
|
||||
hasEvents(day) {
|
||||
let stamp = day.getTime();
|
||||
return this.days[stamp] || this.exclusions[stamp] || this.geoExclusions[stamp];
|
||||
}
|
||||
|
||||
getClass(day) {
|
||||
let stamp = day.getTime();
|
||||
if (this.geoExclusions[stamp])
|
||||
return 'geoExcluded';
|
||||
else if (this.exclusions[stamp])
|
||||
return 'excluded';
|
||||
else return '';
|
||||
}
|
||||
}
|
||||
Controller.$inject = ['$element', '$scope', 'vnWeekDays'];
|
||||
|
||||
ngModule.vnComponent('vnZoneCalendar', {
|
||||
template: require('./index.html'),
|
||||
controller: Controller,
|
||||
bindings: {
|
||||
data: '<?'
|
||||
}
|
||||
});
|
|
@ -1,172 +0,0 @@
|
|||
import './index';
|
||||
import crudModel from 'core/mocks/crud-model';
|
||||
|
||||
describe('component vnZoneCalendar', () => {
|
||||
let $scope;
|
||||
let controller;
|
||||
|
||||
beforeEach(ngModule('zone'));
|
||||
|
||||
beforeEach(inject(($componentController, $rootScope) => {
|
||||
$scope = $rootScope.$new();
|
||||
const $element = angular.element(`<vn-zone-calendar></vn-zone-calendar>`);
|
||||
controller = $componentController('vnZoneCalendar', {$element, $scope});
|
||||
controller.$.model = crudModel;
|
||||
controller.zone = {id: 1};
|
||||
controller.days = [];
|
||||
controller.exclusions = [];
|
||||
controller.geoExclusions = [];
|
||||
}));
|
||||
|
||||
describe('date() setter', () => {
|
||||
it('should set the month property and then call the refreshEvents() method', () => {
|
||||
jest.spyOn(controller, 'refreshEvents').mockReturnThis();
|
||||
|
||||
controller.date = Date.vnNew();
|
||||
|
||||
expect(controller.refreshEvents).toHaveBeenCalledWith();
|
||||
expect(controller.months.length).toEqual(4);
|
||||
});
|
||||
});
|
||||
|
||||
describe('step()', () => {
|
||||
it('should set the date month to 4 months backwards', () => {
|
||||
const now = Date.vnNew();
|
||||
now.setDate(15);
|
||||
now.setMonth(now.getMonth() - 4);
|
||||
|
||||
controller.step(-1);
|
||||
|
||||
const expectedMonth = now.getMonth();
|
||||
const currentMonth = controller.date.getMonth();
|
||||
|
||||
expect(currentMonth).toEqual(expectedMonth);
|
||||
});
|
||||
|
||||
it('should set the date month to 4 months forwards', () => {
|
||||
const now = Date.vnNew();
|
||||
now.setDate(15);
|
||||
now.setMonth(now.getMonth() + 4);
|
||||
|
||||
controller.step(1);
|
||||
|
||||
const expectedMonth = now.getMonth();
|
||||
const currentMonth = controller.date.getMonth();
|
||||
|
||||
expect(currentMonth).toEqual(expectedMonth);
|
||||
});
|
||||
});
|
||||
|
||||
describe('data() setter', () => {
|
||||
it('should set the events, exclusions and geoExclusions and then call the refreshEvents() method', () => {
|
||||
jest.spyOn(controller, 'refreshEvents').mockReturnThis();
|
||||
|
||||
controller.data = {
|
||||
exclusions: [{
|
||||
dated: Date.vnNew()
|
||||
}],
|
||||
events: [{
|
||||
dated: Date.vnNew()
|
||||
}],
|
||||
geoExclusions: [{
|
||||
dated: Date.vnNew()
|
||||
}],
|
||||
};
|
||||
|
||||
expect(controller.refreshEvents).toHaveBeenCalledWith();
|
||||
expect(controller.events).toBeDefined();
|
||||
expect(controller.events.length).toEqual(1);
|
||||
expect(controller.exclusions).toBeDefined();
|
||||
expect(controller.geoExclusions).toBeDefined();
|
||||
expect(Object.keys(controller.exclusions).length).toEqual(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('refreshEvents()', () => {
|
||||
it('should fill the days property with the events.', () => {
|
||||
controller.data = [];
|
||||
controller.firstDay = Date.vnNew();
|
||||
|
||||
const lastDay = Date.vnNew();
|
||||
lastDay.setDate(lastDay.getDate() + 10);
|
||||
controller.lastDay = lastDay;
|
||||
|
||||
const firstEventStamp = controller.firstDay.getTime();
|
||||
const lastEventStamp = controller.lastDay.getTime();
|
||||
controller.events = [{
|
||||
type: 'day',
|
||||
dated: firstEventStamp
|
||||
},
|
||||
{
|
||||
type: 'day',
|
||||
dated: lastEventStamp
|
||||
}];
|
||||
|
||||
controller.refreshEvents();
|
||||
const expectedDays = Object.keys(controller.days);
|
||||
|
||||
expect(expectedDays.length).toEqual(2);
|
||||
});
|
||||
});
|
||||
|
||||
describe('onSelection()', () => {
|
||||
it('should call the emit() method', () => {
|
||||
jest.spyOn(controller, 'emit');
|
||||
|
||||
const $event = {};
|
||||
const $days = [Date.vnNew()];
|
||||
const $type = 'day';
|
||||
const $weekday = 1;
|
||||
|
||||
controller.onSelection($event, $days, $type, $weekday);
|
||||
|
||||
expect(controller.emit).toHaveBeenCalledWith('selection',
|
||||
{
|
||||
$days: $days,
|
||||
$event: {},
|
||||
$events: [],
|
||||
$exclusions: [],
|
||||
$type: 'day',
|
||||
$weekday: 1,
|
||||
$geoExclusions: [],
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('hasEvents()', () => {
|
||||
it('should return true for an existing event on a date', () => {
|
||||
const dated = Date.vnNew();
|
||||
|
||||
controller.days[dated.getTime()] = true;
|
||||
|
||||
const result = controller.hasEvents(dated);
|
||||
|
||||
expect(result).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('getClass()', () => {
|
||||
it('should return the className "excluded" for an excluded date', () => {
|
||||
const dated = Date.vnNew();
|
||||
|
||||
controller.exclusions = [];
|
||||
controller.exclusions[dated.getTime()] = true;
|
||||
|
||||
const result = controller.getClass(dated);
|
||||
|
||||
expect(result).toEqual('excluded');
|
||||
});
|
||||
|
||||
it('should return the className "geoExcluded" for a date with geo excluded', () => {
|
||||
const dated = Date.vnNew();
|
||||
|
||||
controller.geoExclusions = [];
|
||||
controller.geoExclusions[dated.getTime()] = true;
|
||||
|
||||
const result = controller.getClass(dated);
|
||||
|
||||
expect(result).toEqual('geoExcluded');
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,43 +0,0 @@
|
|||
@import "variables";
|
||||
|
||||
vn-zone-calendar {
|
||||
display: block;
|
||||
|
||||
& > vn-card {
|
||||
& > .header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
background-color: $color-main;
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
height: 45px;
|
||||
|
||||
& > .vn-button {
|
||||
color: inherit;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
& > .calendars {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-evenly;
|
||||
|
||||
& > .vn-calendar {
|
||||
max-width: 288px;
|
||||
|
||||
#days-container .day {
|
||||
&.event .day-number {
|
||||
background-color: $color-success;
|
||||
}
|
||||
&.excluded .day-number {
|
||||
background-color: $color-alert;
|
||||
}
|
||||
&.geoExcluded .day-number {
|
||||
background-color: $color-main;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +0,0 @@
|
|||
<vn-portal slot="menu">
|
||||
<vn-zone-descriptor zone="$ctrl.zone"></vn-zone-descriptor>
|
||||
<vn-left-menu source="card"></vn-left-menu>
|
||||
</vn-portal>
|
||||
<ui-view></ui-view>
|
|
@ -1,21 +0,0 @@
|
|||
import ngModule from '../module';
|
||||
import ModuleCard from 'salix/components/module-card';
|
||||
|
||||
class Controller extends ModuleCard {
|
||||
reload() {
|
||||
let filter = {
|
||||
include: {
|
||||
relation: 'agencyMode',
|
||||
scope: {fields: ['name']}
|
||||
}
|
||||
};
|
||||
|
||||
this.$http.get(`Zones/${this.$params.id}`, {filter})
|
||||
.then(res => this.zone = res.data);
|
||||
}
|
||||
}
|
||||
|
||||
ngModule.vnComponent('vnZoneCard', {
|
||||
template: require('./index.html'),
|
||||
controller: Controller
|
||||
});
|
|
@ -1,26 +0,0 @@
|
|||
import './index.js';
|
||||
|
||||
describe('Zone Component vnZoneCard', () => {
|
||||
let controller;
|
||||
let $httpBackend;
|
||||
let data = {id: 1, name: 'fooName'};
|
||||
|
||||
beforeEach(ngModule('zone'));
|
||||
|
||||
beforeEach(inject(($componentController, _$httpBackend_, $stateParams) => {
|
||||
$httpBackend = _$httpBackend_;
|
||||
|
||||
let $element = angular.element('<div></div>');
|
||||
controller = $componentController('vnZoneCard', {$element});
|
||||
|
||||
$stateParams.id = data.id;
|
||||
$httpBackend.whenRoute('GET', 'Zones/:id').respond(data);
|
||||
}));
|
||||
|
||||
it('should request data and set it on the controller', () => {
|
||||
controller.reload();
|
||||
$httpBackend.flush();
|
||||
|
||||
expect(controller.zone).toEqual(data);
|
||||
});
|
||||
});
|
|
@ -1,98 +0,0 @@
|
|||
<vn-watcher
|
||||
vn-id="watcher"
|
||||
url="Zones"
|
||||
data="$ctrl.zone"
|
||||
insert-mode="true"
|
||||
form="form">
|
||||
</vn-watcher>
|
||||
<vn-crud-model
|
||||
auto-load="true"
|
||||
url="Warehouses"
|
||||
data="warehouses"
|
||||
order="name">
|
||||
</vn-crud-model>
|
||||
<vn-crud-model
|
||||
auto-load="true"
|
||||
url="AgencyModes/isActive"
|
||||
data="activeAgencyModes"
|
||||
order="name">
|
||||
</vn-crud-model>
|
||||
<form
|
||||
name="form"
|
||||
vn-http-submit="$ctrl.onSubmit()"
|
||||
class="vn-w-md">
|
||||
<vn-card class="vn-pa-lg">
|
||||
<vn-horizontal>
|
||||
<vn-textfield
|
||||
label="Name"
|
||||
ng-model="$ctrl.zone.name"
|
||||
rule
|
||||
vn-focus>
|
||||
</vn-textfield>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-autocomplete
|
||||
label="Warehouse"
|
||||
ng-model="$ctrl.zone.warehouseFk"
|
||||
data="warehouses"
|
||||
show-field="name"
|
||||
value-field="id"
|
||||
label="Warehouse"
|
||||
rule>
|
||||
</vn-autocomplete>
|
||||
<vn-autocomplete
|
||||
label="Agency"
|
||||
ng-model="$ctrl.zone.agencyModeFk"
|
||||
data="activeAgencyModes"
|
||||
show-field="name"
|
||||
value-field="id"
|
||||
label="Agency"
|
||||
rule>
|
||||
</vn-autocomplete>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-input-number
|
||||
label="Traveling days"
|
||||
ng-model="$ctrl.zone.travelingDays"
|
||||
min="0"
|
||||
step="1"
|
||||
rule>
|
||||
</vn-input-number>
|
||||
<vn-input-time
|
||||
label="Closing hour"
|
||||
ng-model="$ctrl.zone.hour"
|
||||
rule>
|
||||
</vn-input-time>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-input-number
|
||||
label="Price"
|
||||
ng-model="$ctrl.zone.price"
|
||||
min="0"
|
||||
step="0.01"
|
||||
rule>
|
||||
</vn-input-number>
|
||||
<vn-input-number
|
||||
label="Bonus"
|
||||
ng-model="$ctrl.zone.bonus"
|
||||
min="0"
|
||||
step="0.01"
|
||||
rule>
|
||||
</vn-input-number>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-check ng-model="$ctrl.zone.isVolumetric" label="Volumetric"></vn-check>
|
||||
</vn-horizontal>
|
||||
</vn-card>
|
||||
<vn-button-bar>
|
||||
<vn-submit
|
||||
disabled="!watcher.dataChanged()"
|
||||
label="Create">
|
||||
</vn-submit>
|
||||
<vn-button
|
||||
class="cancel"
|
||||
label="Cancel"
|
||||
ui-sref="zone.index">
|
||||
</vn-button>
|
||||
</vn-button-bar>
|
||||
</form>
|
|
@ -1,24 +0,0 @@
|
|||
import ngModule from '../module';
|
||||
import Section from 'salix/components/section';
|
||||
|
||||
export default class Controller extends Section {
|
||||
$onInit() {
|
||||
this.zone = {
|
||||
travelingDays: 0,
|
||||
price: 0.20,
|
||||
bonus: 0.20,
|
||||
hour: Date.vnNew()
|
||||
};
|
||||
}
|
||||
|
||||
onSubmit() {
|
||||
return this.$.watcher.submit().then(res =>
|
||||
this.$state.go('zone.card.location', {id: res.data.id})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ngModule.vnComponent('vnZoneCreate', {
|
||||
template: require('./index.html'),
|
||||
controller: Controller
|
||||
});
|
|
@ -1,40 +0,0 @@
|
|||
import './index';
|
||||
import watcher from 'core/mocks/watcher';
|
||||
|
||||
describe('Zone Component vnZoneCreate', () => {
|
||||
let $scope;
|
||||
let $state;
|
||||
let controller;
|
||||
|
||||
beforeEach(ngModule('zone'));
|
||||
|
||||
beforeEach(inject(($componentController, $rootScope, _$state_) => {
|
||||
$scope = $rootScope.$new();
|
||||
$state = _$state_;
|
||||
$scope.watcher = watcher;
|
||||
$scope.watcher.submit = () => {
|
||||
return {
|
||||
then: callback => {
|
||||
callback({data: {id: 1234}});
|
||||
}
|
||||
};
|
||||
};
|
||||
const $element = angular.element('<vn-zone-create></vn-zone-create>');
|
||||
controller = $componentController('vnZoneCreate', {$element, $scope});
|
||||
}));
|
||||
|
||||
describe('onSubmit()', () => {
|
||||
it(`should call submit() on the watcher then expect a callback`, () => {
|
||||
jest.spyOn($state, 'go');
|
||||
|
||||
controller.zone = {
|
||||
name: 'Zone One'
|
||||
};
|
||||
|
||||
controller.onSubmit();
|
||||
|
||||
expect(controller.$state.go).toHaveBeenCalledWith('zone.card.location', Object({id: 1234}));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
Traveling days: Días de viaje
|
||||
Closing hour: Hora de cierre
|
||||
Bonus: Bonificación
|
|
@ -1,102 +0,0 @@
|
|||
<div class="vn-w-md">
|
||||
<vn-zone-calendar
|
||||
data="data"
|
||||
on-selection="$ctrl.onSelection($event, $events, $days)">
|
||||
</vn-zone-calendar>
|
||||
</div>
|
||||
<vn-side-menu side="right">
|
||||
<form ng-submit="$ctrl.fetchData()" class="vn-pa-md">
|
||||
<vn-radio
|
||||
label="Pick up"
|
||||
val="pickUp"
|
||||
ng-model="$ctrl.deliveryMethodFk"
|
||||
on-change="$ctrl.agencyModeFk = null"
|
||||
tabindex="-1">
|
||||
</vn-radio>
|
||||
<vn-radio
|
||||
label="Delivery"
|
||||
val="delivery"
|
||||
ng-model="$ctrl.deliveryMethodFk"
|
||||
on-change="$ctrl.agencyModeFk = null"
|
||||
class="vn-mb-sm"
|
||||
tabindex="-1">
|
||||
</vn-radio>
|
||||
<vn-autocomplete
|
||||
vn-one
|
||||
ng-if="$ctrl.deliveryMethodFk === 'delivery'"
|
||||
vn-focus
|
||||
label="Postcode"
|
||||
ng-model="$ctrl.geoFk"
|
||||
url="Postcodes/location"
|
||||
fields="['code','townFk']"
|
||||
order="code, townFk"
|
||||
value-field="geoFk"
|
||||
show-field="code">
|
||||
<tpl-item>
|
||||
<div>
|
||||
{{code}} {{town.name}}
|
||||
</div>
|
||||
<div class="text-caption text-secondary">
|
||||
{{town.province.name}}, {{town.province.country.name}}
|
||||
</div>
|
||||
</tpl-item>
|
||||
</vn-autocomplete>
|
||||
<vn-autocomplete
|
||||
label="{{$ctrl.deliveryMethodFk == 'delivery' ? 'Agency' : 'Warehouse'}}"
|
||||
ng-model="$ctrl.agencyModeFk"
|
||||
url="AgencyModes/isActive"
|
||||
where="$ctrl.agencyFilter"
|
||||
vn-id="agencymode">
|
||||
</vn-autocomplete>
|
||||
<vn-submit label="Query" class="vn-mt-sm"></vn-submit>
|
||||
</form>
|
||||
</vn-side-menu>
|
||||
|
||||
<!-- Zone Popover -->
|
||||
<vn-popover vn-id="zoneEvents">
|
||||
<div class="zoneEvents">
|
||||
<div class="header vn-pa-sm" translate>Zones</div>
|
||||
<vn-data-viewer
|
||||
data="::$ctrl.zoneClosing"
|
||||
class="vn-w-md vn-mb-xl">
|
||||
<vn-card>
|
||||
<vn-table>
|
||||
<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="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 $ctrl.zoneClosing"
|
||||
ui-sref="zone.card.summary({id: zone.id})"
|
||||
class="clickable search-result">
|
||||
<vn-td number>{{::zone.id}}</vn-td>
|
||||
<vn-td expand>{{::zone.name}}</vn-td>
|
||||
<vn-td>{{::zone.agencyModeName}}</vn-td>
|
||||
<vn-td shrink>{{::zone.hour | date: 'HH:mm'}}</vn-td>
|
||||
<vn-td number>{{::zone.price | currency: 'EUR':2}}</vn-td>
|
||||
<vn-td shrink>
|
||||
<vn-horizontal class="buttons">
|
||||
<vn-icon-button
|
||||
vn-click-stop="$ctrl.preview(zone)"
|
||||
vn-tooltip="Preview"
|
||||
icon="preview">
|
||||
</vn-icon-button>
|
||||
</vn-horizontal>
|
||||
</vn-td>
|
||||
</vn-tr>
|
||||
</vn-tbody>
|
||||
</vn-table>
|
||||
</vn-card>
|
||||
</vn-data-viewer>
|
||||
</div>
|
||||
</vn-popover>
|
||||
<vn-popup vn-id="summary">
|
||||
<vn-zone-summary zone="$ctrl.selectedZone"></vn-zone-summary>
|
||||
</vn-popup>
|
|
@ -1,95 +0,0 @@
|
|||
import ngModule from '../module';
|
||||
import Section from 'salix/components/section';
|
||||
import './style.scss';
|
||||
|
||||
class Controller extends Section {
|
||||
$onInit() {
|
||||
this.setParams();
|
||||
}
|
||||
|
||||
$postLink() {
|
||||
this.deliveryMethodFk = 'delivery';
|
||||
}
|
||||
|
||||
setParams() {
|
||||
const hasParams = this.$params.deliveryMethodFk || this.$params.geoFk || this.$params.agencyModeFk;
|
||||
if (hasParams) {
|
||||
if (this.$params.deliveryMethodFk)
|
||||
this.deliveryMethodFk = this.$params.deliveryMethodFk;
|
||||
|
||||
if (this.$params.geoFk)
|
||||
this.geoFk = this.$params.geoFk;
|
||||
|
||||
if (this.$params.agencyModeFk)
|
||||
this.agencyModeFk = this.$params.agencyModeFk;
|
||||
|
||||
this.fetchData();
|
||||
}
|
||||
}
|
||||
|
||||
fetchData() {
|
||||
const params = {
|
||||
deliveryMethodFk: this.deliveryMethodFk,
|
||||
geoFk: this.geoFk,
|
||||
agencyModeFk: this.agencyModeFk
|
||||
};
|
||||
this.$.data = null;
|
||||
this.$http.get(`Zones/getEvents`, {params})
|
||||
.then(res => {
|
||||
let data = res.data;
|
||||
this.$.data = data;
|
||||
if (!data.events.length)
|
||||
this.vnApp.showMessage(this.$t('No service for the specified zone'));
|
||||
|
||||
this.$state.go(this.$state.current.name, params);
|
||||
});
|
||||
}
|
||||
|
||||
get deliveryMethodFk() {
|
||||
return this._deliveryMethodFk;
|
||||
}
|
||||
|
||||
set deliveryMethodFk(value) {
|
||||
this._deliveryMethodFk = value;
|
||||
|
||||
let filter;
|
||||
|
||||
if (value === 'pickUp')
|
||||
filter = {where: {code: 'PICKUP'}};
|
||||
else
|
||||
filter = {where: {code: {inq: ['DELIVERY', 'AGENCY']}}};
|
||||
|
||||
this.$http.get(`DeliveryMethods`, {filter}).then(res => {
|
||||
const deliveryMethods = res.data.map(deliveryMethod => deliveryMethod.id);
|
||||
this.agencyFilter = {deliveryMethodFk: {inq: deliveryMethods}};
|
||||
});
|
||||
}
|
||||
|
||||
onSelection($event, $events, $days) {
|
||||
if (!$events.length) return;
|
||||
|
||||
const day = $days[0];
|
||||
const zoneIds = [];
|
||||
for (let event of $events)
|
||||
zoneIds.push(event.zoneFk);
|
||||
|
||||
const params = {
|
||||
zoneIds: zoneIds,
|
||||
date: day
|
||||
};
|
||||
|
||||
this.$http.post(`Zones/getZoneClosing`, params)
|
||||
.then(res => this.zoneClosing = res.data)
|
||||
.then(() => this.$.zoneEvents.show($event.target));
|
||||
}
|
||||
|
||||
preview(zone) {
|
||||
this.selectedZone = zone;
|
||||
this.$.summary.show();
|
||||
}
|
||||
}
|
||||
|
||||
ngModule.vnComponent('vnZoneDeliveryDays', {
|
||||
template: require('./index.html'),
|
||||
controller: Controller
|
||||
});
|
|
@ -1,126 +0,0 @@
|
|||
import './index.js';
|
||||
import popover from 'core/mocks/popover';
|
||||
import crudModel from 'core/mocks/crud-model';
|
||||
|
||||
describe('Zone Component vnZoneDeliveryDays', () => {
|
||||
let $httpBackend;
|
||||
let controller;
|
||||
let $element;
|
||||
|
||||
beforeEach(ngModule('zone'));
|
||||
|
||||
beforeEach(inject(($componentController, _$httpBackend_) => {
|
||||
$httpBackend = _$httpBackend_;
|
||||
$element = angular.element('<vn-zone-delivery-days></vn-zone-delivery-days');
|
||||
controller = $componentController('vnZoneDeliveryDays', {$element});
|
||||
controller.$.zoneEvents = popover;
|
||||
controller.$.params = {};
|
||||
controller.$.zoneModel = crudModel;
|
||||
}));
|
||||
|
||||
describe('deliveryMethodFk() setter', () => {
|
||||
it('should set the deliveryMethodFk property as pickup and then perform a query that sets the filter', () => {
|
||||
$httpBackend.expect('GET', 'DeliveryMethods').respond([{id: 999}]);
|
||||
controller.deliveryMethodFk = 'pickUp';
|
||||
$httpBackend.flush();
|
||||
|
||||
expect(controller.agencyFilter).toEqual({deliveryMethodFk: {inq: [999]}});
|
||||
});
|
||||
});
|
||||
|
||||
describe('setParams()', () => {
|
||||
it('should do nothing when no params are received', () => {
|
||||
controller.setParams();
|
||||
|
||||
expect(controller.deliveryMethodFk).toBeUndefined();
|
||||
expect(controller.geoFk).toBeUndefined();
|
||||
expect(controller.agencyModeFk).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should set the controller properties when the params are provided', () => {
|
||||
controller.$params = {
|
||||
deliveryMethodFk: 3,
|
||||
geoFk: 2,
|
||||
agencyModeFk: 1
|
||||
};
|
||||
controller.setParams();
|
||||
|
||||
expect(controller.deliveryMethodFk).toEqual(controller.$params.deliveryMethodFk);
|
||||
expect(controller.geoFk).toEqual(controller.$params.geoFk);
|
||||
expect(controller.agencyModeFk).toEqual(controller.$params.agencyModeFk);
|
||||
});
|
||||
});
|
||||
|
||||
describe('fetchData()', () => {
|
||||
it('should make an HTTP GET query and then call the showMessage() method', () => {
|
||||
jest.spyOn(controller.vnApp, 'showMessage');
|
||||
jest.spyOn(controller.$state, 'go');
|
||||
|
||||
controller.agencyModeFk = 1;
|
||||
controller.deliveryMethodFk = 2;
|
||||
controller.geoFk = 3;
|
||||
controller.$state.current.name = 'myState';
|
||||
|
||||
const expectedData = {events: []};
|
||||
|
||||
const url = 'Zones/getEvents?agencyModeFk=1&deliveryMethodFk=2&geoFk=3';
|
||||
|
||||
$httpBackend.when('GET', 'DeliveryMethods').respond([]);
|
||||
$httpBackend.expect('GET', url).respond({events: []});
|
||||
controller.fetchData();
|
||||
$httpBackend.flush();
|
||||
|
||||
expect(controller.$.data).toEqual(expectedData);
|
||||
expect(controller.vnApp.showMessage).toHaveBeenCalledWith('No service for the specified zone');
|
||||
expect(controller.$state.go).toHaveBeenCalledWith(
|
||||
controller.$state.current.name,
|
||||
{
|
||||
agencyModeFk: 1,
|
||||
deliveryMethodFk: 2,
|
||||
geoFk: 3
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('onSelection()', () => {
|
||||
it('should not call the show popover method if events array is empty', () => {
|
||||
jest.spyOn(controller.$.zoneEvents, 'show');
|
||||
|
||||
const event = new Event('click');
|
||||
const target = document.createElement('div');
|
||||
target.dispatchEvent(event);
|
||||
const events = [];
|
||||
controller.onSelection(event, events);
|
||||
|
||||
expect(controller.$.zoneEvents.show).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should call the show() method and call getZoneClosing() with the expected ids', () => {
|
||||
jest.spyOn(controller.$.zoneEvents, 'show');
|
||||
|
||||
const event = new Event('click');
|
||||
const target = document.createElement('div');
|
||||
target.dispatchEvent(event);
|
||||
|
||||
const day = Date.vnNew();
|
||||
const events = [
|
||||
{zoneFk: 1},
|
||||
{zoneFk: 2},
|
||||
{zoneFk: 8}
|
||||
];
|
||||
const params = {
|
||||
zoneIds: [1, 2, 8],
|
||||
date: [day][0]
|
||||
};
|
||||
const response = [{id: 1, hour: ''}];
|
||||
|
||||
$httpBackend.when('POST', 'Zones/getZoneClosing', params).respond({response});
|
||||
controller.onSelection(event, events, [day]);
|
||||
$httpBackend.flush();
|
||||
|
||||
expect(controller.$.zoneEvents.show).toHaveBeenCalledWith(target);
|
||||
expect(controller.zoneClosing.id).toEqual(response.id);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,36 +0,0 @@
|
|||
@import "variables";
|
||||
|
||||
vn-zone-delivery-days {
|
||||
vn-zone-calendar {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
flex-wrap: wrap;
|
||||
|
||||
& > vn-calendar {
|
||||
min-width: 264px;
|
||||
}
|
||||
}
|
||||
form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
|
||||
.zoneEvents {
|
||||
width: 700px;
|
||||
max-height: 450px;
|
||||
|
||||
vn-data-viewer {
|
||||
margin-bottom: 0;
|
||||
vn-pagination {
|
||||
padding: 0
|
||||
}
|
||||
}
|
||||
|
||||
& > .header {
|
||||
background-color: $color-main;
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
text-align: center
|
||||
}
|
||||
}
|
|
@ -1,4 +0,0 @@
|
|||
<slot-descriptor>
|
||||
<vn-zone-descriptor>
|
||||
</vn-zone-descriptor>
|
||||
</slot-descriptor>
|
|
@ -1,9 +0,0 @@
|
|||
import ngModule from '../module';
|
||||
import DescriptorPopover from 'salix/components/descriptor-popover';
|
||||
|
||||
class Controller extends DescriptorPopover {}
|
||||
|
||||
ngModule.vnComponent('vnZoneDescriptorPopover', {
|
||||
slotTemplate: require('./index.html'),
|
||||
controller: Controller
|
||||
});
|
|
@ -1,57 +0,0 @@
|
|||
<vn-descriptor-content
|
||||
module="zone"
|
||||
description="$ctrl.zone.name"
|
||||
summary="$ctrl.$.summary">
|
||||
<slot-menu>
|
||||
<vn-item class="vn-item"
|
||||
ng-click="$ctrl.onDelete()"
|
||||
translate>
|
||||
Delete
|
||||
</vn-item>
|
||||
<vn-item
|
||||
ng-click="clone.show()"
|
||||
name="cloneZone"
|
||||
translate>
|
||||
Clone
|
||||
</vn-item>
|
||||
</slot-menu>
|
||||
<slot-body>
|
||||
<div class="attributes">
|
||||
<vn-label-value
|
||||
label="Agency"
|
||||
value="{{$ctrl.zone.agencyMode.name}}">
|
||||
</vn-label-value>
|
||||
<vn-label-value
|
||||
label="Closing hour"
|
||||
value="{{$ctrl.zone.hour | date: 'HH:mm'}}">
|
||||
</vn-label-value>
|
||||
<vn-label-value
|
||||
label="Traveling days"
|
||||
value="{{$ctrl.zone.travelingDays}}">
|
||||
</vn-label-value>
|
||||
<vn-label-value
|
||||
label="Price"
|
||||
value="{{$ctrl.zone.price | currency: 'EUR': 2}}">
|
||||
</vn-label-value>
|
||||
<vn-label-value
|
||||
label="Bonus"
|
||||
value="{{$ctrl.zone.bonus | currency: 'EUR': 2}}">
|
||||
</vn-label-value>
|
||||
</div>
|
||||
</slot-body>
|
||||
</vn-descriptor-content>
|
||||
<vn-popup vn-id="summary">
|
||||
<vn-zone-summary zone="$ctrl.zone"></vn-zone-summary>
|
||||
</vn-popup>
|
||||
|
||||
<vn-confirm
|
||||
vn-id="deleteZone"
|
||||
on-accept="$ctrl.deleteZone()"
|
||||
message="This zone will be removed">
|
||||
</vn-confirm>
|
||||
<vn-confirm
|
||||
vn-id="clone"
|
||||
on-accept="$ctrl.onCloneAccept()"
|
||||
question="Do you want to clone this zone?"
|
||||
message="All it's properties will be copied">
|
||||
</vn-confirm>
|
|
@ -1,65 +0,0 @@
|
|||
import ngModule from '../module';
|
||||
import Descriptor from 'salix/components/descriptor';
|
||||
|
||||
class Controller extends Descriptor {
|
||||
get zone() {
|
||||
return this.entity;
|
||||
}
|
||||
|
||||
set zone(value) {
|
||||
this.entity = value;
|
||||
}
|
||||
|
||||
loadData() {
|
||||
const filter = {
|
||||
include: [
|
||||
{
|
||||
relation: 'agencyMode',
|
||||
scope: {
|
||||
fields: ['name'],
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
return this.getData(`Zones/${this.id}`, {filter})
|
||||
.then(res => this.entity = res.data);
|
||||
}
|
||||
|
||||
onDelete() {
|
||||
const $t = this.$translate.instant;
|
||||
const today = Date.vnNew();
|
||||
today.setHours(0, 0, 0, 0);
|
||||
const filter = {where: {zoneFk: this.id, shipped: {gte: today}}};
|
||||
this.$http.get(`Tickets`, {filter}).then(res => {
|
||||
const ticketsAmount = res.data.length;
|
||||
if (ticketsAmount) {
|
||||
const params = {ticketsAmount};
|
||||
const question = $t('This zone contains tickets', params, null, null, 'sanitizeParameters');
|
||||
this.$.deleteZone.question = question;
|
||||
this.$.deleteZone.show();
|
||||
} else
|
||||
this.deleteZone();
|
||||
});
|
||||
}
|
||||
|
||||
deleteZone() {
|
||||
return this.$http.post(`Zones/${this.id}/deleteZone`).then(() => {
|
||||
this.$state.go('zone.index');
|
||||
this.vnApp.showSuccess(this.$t('Zone deleted'));
|
||||
});
|
||||
}
|
||||
|
||||
onCloneAccept() {
|
||||
return this.$http.post(`Zones/${this.id}/clone`).
|
||||
then(res => this.$state.go('zone.card.basicData', {id: res.data.id}));
|
||||
}
|
||||
}
|
||||
|
||||
ngModule.vnComponent('vnZoneDescriptor', {
|
||||
template: require('./index.html'),
|
||||
controller: Controller,
|
||||
bindings: {
|
||||
zone: '<'
|
||||
}
|
||||
});
|
|
@ -1,74 +0,0 @@
|
|||
import './index.js';
|
||||
|
||||
describe('Zone descriptor', () => {
|
||||
let $httpBackend;
|
||||
let controller;
|
||||
let $element;
|
||||
|
||||
beforeEach(ngModule('zone'));
|
||||
|
||||
beforeEach(inject(($componentController, _$httpBackend_) => {
|
||||
$httpBackend = _$httpBackend_;
|
||||
$element = angular.element('<vn-zone-descriptor></vn-zone-descriptor');
|
||||
controller = $componentController('vnZoneDescriptor', {$element});
|
||||
controller.zone = {id: 1};
|
||||
controller.id = 1;
|
||||
controller.$.deleteZone = {
|
||||
hide: () => {},
|
||||
show: () => {}
|
||||
};
|
||||
}));
|
||||
|
||||
describe('onDelete()', () => {
|
||||
it('should make an HTTP POST query and then call the deleteZone show() method', () => {
|
||||
jest.spyOn(controller.$.deleteZone, 'show');
|
||||
|
||||
const expectedData = [{id: 16}];
|
||||
$httpBackend.when('GET', 'Tickets').respond(expectedData);
|
||||
controller.onDelete();
|
||||
$httpBackend.flush();
|
||||
|
||||
expect(controller.$.deleteZone.show).toHaveBeenCalledWith();
|
||||
});
|
||||
|
||||
it('should make an HTTP POST query and then call the deleteZone() method', () => {
|
||||
jest.spyOn(controller, 'deleteZone').mockReturnThis();
|
||||
|
||||
const expectedData = [];
|
||||
$httpBackend.when('GET', 'Tickets').respond(expectedData);
|
||||
controller.onDelete();
|
||||
$httpBackend.flush();
|
||||
|
||||
expect(controller.deleteZone).toHaveBeenCalledWith();
|
||||
});
|
||||
});
|
||||
|
||||
describe('deleteZone()', () => {
|
||||
it('should make an HTTP POST query and then call the showMessage() method', () => {
|
||||
jest.spyOn(controller.$state, 'go').mockReturnThis();
|
||||
jest.spyOn(controller.vnApp, 'showSuccess');
|
||||
|
||||
const stateName = 'zone.index';
|
||||
$httpBackend.when('POST', 'Zones/1/deleteZone').respond(200);
|
||||
controller.deleteZone();
|
||||
$httpBackend.flush();
|
||||
|
||||
expect(controller.$state.go).toHaveBeenCalledWith(stateName);
|
||||
expect(controller.vnApp.showSuccess).toHaveBeenCalledWith('Zone deleted');
|
||||
});
|
||||
});
|
||||
|
||||
describe('onCloneAccept()', () => {
|
||||
it('should make an HTTP POST query and then call the state go() method', () => {
|
||||
jest.spyOn(controller.$state, 'go').mockReturnThis();
|
||||
|
||||
const stateName = 'zone.card.basicData';
|
||||
const expectedData = {id: 1};
|
||||
$httpBackend.when('POST', 'Zones/1/clone').respond(expectedData);
|
||||
controller.onCloneAccept();
|
||||
$httpBackend.flush();
|
||||
|
||||
expect(controller.$state.go).toHaveBeenCalledWith(stateName, expectedData);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,4 +0,0 @@
|
|||
This zone contains tickets: Esta zona contiene {{ticketsAmount}} tickets por servir. ¿Seguro que quieres eliminar esta zona?
|
||||
Do you want to clone this zone?: ¿Quieres clonar esta zona?
|
||||
All it's properties will be copied: Todas sus propiedades serán copiadas
|
||||
Zone deleted: Zona eliminada
|
|
@ -1,277 +0,0 @@
|
|||
<vn-zone-calendar
|
||||
id="calendar"
|
||||
vn-id="calendar"
|
||||
data="data"
|
||||
on-selection="$ctrl.onSelection($days, $type, $weekday, $events, $exclusions, $geoExclusions)"
|
||||
on-step="$ctrl.refresh()"
|
||||
class="vn-w-md">
|
||||
</vn-zone-calendar>
|
||||
<vn-side-menu side="right">
|
||||
<div class="vn-pa-md">
|
||||
<h6
|
||||
class="text-secondary"
|
||||
style="font-weight: normal;"
|
||||
translate>
|
||||
Edit mode
|
||||
</h6>
|
||||
<vn-vertical>
|
||||
<vn-radio
|
||||
label="Include"
|
||||
val="include"
|
||||
ng-model="$ctrl.editMode">
|
||||
</vn-radio>
|
||||
<vn-radio
|
||||
label="Exclude"
|
||||
val="exclude"
|
||||
ng-model="$ctrl.editMode">
|
||||
</vn-radio>
|
||||
</vn-vertical>
|
||||
</div>
|
||||
<h6
|
||||
class="text-secondary vn-px-md"
|
||||
style="font-weight: normal;"
|
||||
translate>
|
||||
Events
|
||||
</h6>
|
||||
<vn-data-viewer
|
||||
data="data.events"
|
||||
is-loading="!data.events">
|
||||
<div class="vn-list separated">
|
||||
<a
|
||||
ng-repeat="row in data.events"
|
||||
translate-attr="{title: 'Edit'}"
|
||||
ng-click="$ctrl.onEditClick(row, $event)"
|
||||
class="vn-item">
|
||||
<vn-item-section>
|
||||
<div
|
||||
ng-if="::row.type == 'day'"
|
||||
class="vn-mb-sm">
|
||||
{{::row.dated | date:'dd/MM/yy'}}
|
||||
</div>
|
||||
<div
|
||||
ng-if="::row.type != 'day'"
|
||||
class="vn-mb-sm ellipsize">
|
||||
<span ng-if="row.weekDays">
|
||||
{{::$ctrl.formatWdays(row.weekDays)}}
|
||||
</span>
|
||||
<span ng-if="row.type == 'range'">
|
||||
({{::row.started | date:'dd/MM/yy'}} - {{::row.ended | date:'dd/MM/yy'}})
|
||||
</span>
|
||||
</div>
|
||||
<vn-label-value
|
||||
label="Closing"
|
||||
value="{{::row.hour | date:'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-label-value
|
||||
label="Max m³"
|
||||
value="{{::row.m3Max}}">
|
||||
</vn-label-value>
|
||||
</vn-item-section>
|
||||
<vn-item-section side>
|
||||
<vn-icon-button
|
||||
icon="delete"
|
||||
translate-attr="{title: 'Delete'}"
|
||||
ng-click="$ctrl.onDeleteClick(row.id, $event)">
|
||||
</vn-icon-button>
|
||||
</vn-item-section>
|
||||
</a>
|
||||
</div>
|
||||
</vn-data-viewer>
|
||||
</vn-side-menu>
|
||||
<vn-float-button
|
||||
ng-click="$ctrl.createInclusion('weekday')"
|
||||
icon="add"
|
||||
vn-tooltip="Add event"
|
||||
vn-bind="+"
|
||||
fixed-bottom-right>
|
||||
</vn-float-button>
|
||||
<vn-dialog
|
||||
vn-id="includeDialog"
|
||||
on-response="$ctrl.onIncludeResponse($response)"
|
||||
message="{{$ctrl.isNew ? 'Add event' : 'Edit event'}}">
|
||||
<tpl-body>
|
||||
<vn-vertical>
|
||||
<vn-vertical class="vn-pb-md">
|
||||
<vn-radio
|
||||
ng-model="$ctrl.selected.type"
|
||||
label="One day"
|
||||
val="day">
|
||||
</vn-radio>
|
||||
<vn-radio
|
||||
ng-model="$ctrl.selected.type"
|
||||
label="Indefinitely"
|
||||
val="indefinitely">
|
||||
</vn-radio>
|
||||
<vn-radio
|
||||
ng-model="$ctrl.selected.type"
|
||||
label="Range of dates"
|
||||
val="range">
|
||||
</vn-radio>
|
||||
</vn-vertical>
|
||||
<vn-wday-picker
|
||||
ng-if="$ctrl.selected.type != 'day'"
|
||||
ng-model="$ctrl.selected.wdays"
|
||||
class="vn-mt-sm vn-mb-md">
|
||||
</vn-wday-picker>
|
||||
<vn-date-picker
|
||||
ng-if="$ctrl.selected.type == 'day'"
|
||||
label="Day"
|
||||
ng-model="$ctrl.selected.dated">
|
||||
</vn-date-picker>
|
||||
<vn-horizontal
|
||||
ng-if="$ctrl.selected.type == 'range'">
|
||||
<vn-date-picker
|
||||
label="From"
|
||||
ng-model="$ctrl.selected.started">
|
||||
</vn-date-picker>
|
||||
<vn-date-picker
|
||||
label="To"
|
||||
ng-model="$ctrl.selected.ended">
|
||||
</vn-date-picker>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-input-time
|
||||
label="Closing"
|
||||
ng-model="$ctrl.selected.hour">
|
||||
</vn-input-time>
|
||||
<vn-input-number
|
||||
label="Traveling days"
|
||||
ng-model="$ctrl.selected.travelingDays"
|
||||
min="0"
|
||||
step="1">
|
||||
</vn-input-number>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-input-number
|
||||
label="Price"
|
||||
ng-model="$ctrl.selected.price"
|
||||
min="0"
|
||||
step="0.01">
|
||||
</vn-input-number>
|
||||
<vn-input-number
|
||||
label="Bonus"
|
||||
ng-model="$ctrl.selected.bonus"
|
||||
min="0"
|
||||
step="0.01">
|
||||
</vn-input-number>
|
||||
</vn-horizontal>
|
||||
<vn-input-number
|
||||
label="Max m³"
|
||||
ng-model="$ctrl.selected.m3Max"
|
||||
min="0"
|
||||
step="0.01">
|
||||
</vn-input-number>
|
||||
</vn-vertical>
|
||||
</tpl-body>
|
||||
<tpl-buttons>
|
||||
<input
|
||||
type="button"
|
||||
response="cancel"
|
||||
translate-attr="{value: 'Cancel'}">
|
||||
</input>
|
||||
<input
|
||||
type="button"
|
||||
ng-if="!$ctrl.isNew"
|
||||
response="delete"
|
||||
translate-attr="{value: 'Delete'}">
|
||||
</input>
|
||||
<button response="accept">
|
||||
<span ng-if="$ctrl.isNew" translate>Add</span>
|
||||
<span ng-if="!$ctrl.isNew" translate>Save</span>
|
||||
</button>
|
||||
</tpl-buttons>
|
||||
</vn-dialog>
|
||||
<vn-confirm
|
||||
vn-id="confirm"
|
||||
message="This item will be deleted"
|
||||
question="Are you sure you want to continue?">
|
||||
</vn-confirm>
|
||||
<vn-dialog
|
||||
vn-id="excludeDialog"
|
||||
on-response="$ctrl.onExcludeResponse($response)"
|
||||
message="{{$ctrl.isNew ? 'Add exclusion' : 'Edit exclusion'}}"
|
||||
on-open="$ctrl.onSearch($params)"
|
||||
on-close="$ctrl.resetExclusions()">
|
||||
<tpl-body>
|
||||
<vn-date-picker
|
||||
label="Day"
|
||||
ng-model="$ctrl.excludeSelected.dated">
|
||||
</vn-date-picker>
|
||||
<vn-vertical class="width">
|
||||
<vn-vertical class="vn-pb-md">
|
||||
<vn-radio
|
||||
ng-model="$ctrl.excludeSelected.type"
|
||||
label="All"
|
||||
on-change="$ctrl.test()"
|
||||
val="all">
|
||||
</vn-radio>
|
||||
<vn-radio
|
||||
ng-model="$ctrl.excludeSelected.type"
|
||||
label="Specific locations"
|
||||
on-change="$ctrl.onSearch($params)"
|
||||
val="specificLocations">
|
||||
</vn-radio>
|
||||
</vn-vertical>
|
||||
<vn-crud-model
|
||||
vn-id="model"
|
||||
url="Zones/{{$ctrl.$params.id}}/getLeaves"
|
||||
filter="$ctrl.filter">
|
||||
</vn-crud-model>
|
||||
<div ng-if="$ctrl.excludeSelected.type == 'specificLocations'">
|
||||
<vn-textfield
|
||||
label="Search"
|
||||
ng-keydown="$ctrl.onKeyDown($event)"
|
||||
ng-model="$ctrl.excludeSearch">
|
||||
<prepend>
|
||||
<vn-icon icon="search"></vn-icon>
|
||||
</prepend>
|
||||
</vn-textfield>
|
||||
<div class="treeview">
|
||||
<vn-treeview
|
||||
vn-id="treeview"
|
||||
root-label="Locations where it is not distributed"
|
||||
fetch-func="$ctrl.onFetch($item)"
|
||||
sort-func="$ctrl.onSort($a, $b)">
|
||||
<vn-check
|
||||
ng-model="item.checked"
|
||||
ng-click="$event.preventDefault()"
|
||||
on-change="$ctrl.onItemCheck(item.id, value)"
|
||||
label="{{::item.name}}">
|
||||
</vn-check>
|
||||
</vn-treeview>
|
||||
</div>
|
||||
</div>
|
||||
</vn-vertical>
|
||||
</tpl-body>
|
||||
<tpl-buttons>
|
||||
<input
|
||||
type="button"
|
||||
response="cancel"
|
||||
translate-attr="{value: 'Cancel'}"
|
||||
tabindex="0">
|
||||
</input>
|
||||
<input
|
||||
type="button"
|
||||
ng-if="!$ctrl.isNew"
|
||||
response="delete"
|
||||
translate-attr="{value: 'Delete'}"
|
||||
tabindex="0">
|
||||
</input>
|
||||
<button response="accept">
|
||||
<span ng-if="$ctrl.isNew" translate>Add</span>
|
||||
<span ng-if="!$ctrl.isNew" translate>Save</span>
|
||||
</button>
|
||||
</tpl-buttons>
|
||||
</vn-dialog>
|
|
@ -1,316 +0,0 @@
|
|||
import ngModule from '../module';
|
||||
import Section from 'salix/components/section';
|
||||
import './style.scss';
|
||||
|
||||
class Controller extends Section {
|
||||
constructor($element, $, vnWeekDays) {
|
||||
super($element, $);
|
||||
this.vnWeekDays = vnWeekDays;
|
||||
this.editMode = 'include';
|
||||
}
|
||||
|
||||
$onInit() {
|
||||
this.refresh();
|
||||
}
|
||||
|
||||
get path() {
|
||||
return `Zones/${this.$params.id}/events`;
|
||||
}
|
||||
|
||||
get exclusionsPath() {
|
||||
return `Zones/${this.$params.id}/exclusions`;
|
||||
}
|
||||
|
||||
get checked() {
|
||||
const geos = this.$.model.data || [];
|
||||
const checkedLines = [];
|
||||
for (let geo of geos) {
|
||||
if (geo.checked)
|
||||
checkedLines.push(geo);
|
||||
}
|
||||
return checkedLines;
|
||||
}
|
||||
|
||||
refresh() {
|
||||
this.$.data = null;
|
||||
this.$.$applyAsync(() => {
|
||||
const params = {
|
||||
zoneFk: this.$params.id,
|
||||
started: this.$.calendar.firstDay,
|
||||
ended: this.$.calendar.lastDay
|
||||
};
|
||||
|
||||
this.$http.get(`Zones/getEventsFiltered`, {params}).then(res => {
|
||||
const data = res.data;
|
||||
this.$.data = data;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
formatWdays(weekDays) {
|
||||
if (!weekDays) return;
|
||||
|
||||
let abrWdays = weekDays
|
||||
.split(',')
|
||||
.map(wday => this.vnWeekDays.map[wday].localeAbr);
|
||||
|
||||
return abrWdays.length < 7
|
||||
? abrWdays.join(', ')
|
||||
: this.$t('Everyday');
|
||||
}
|
||||
|
||||
onSelection(days, type, weekday, events, exclusions, exclusionGeos) {
|
||||
if (this.editMode == 'include') {
|
||||
if (events.length)
|
||||
return this.editInclusion(events[0]);
|
||||
return this.createInclusion(type, days, weekday);
|
||||
} else if (this.editMode == 'exclude') {
|
||||
if (exclusions.length || exclusionGeos.length)
|
||||
return this.editExclusion(exclusions[0] || {}, exclusionGeos);
|
||||
return this.createExclusion(days);
|
||||
}
|
||||
}
|
||||
|
||||
editExclusion(exclusion, exclusionGeos) {
|
||||
this.isNew = false;
|
||||
this.excludeSelected = angular.copy(exclusion);
|
||||
this.excludeSelected.type = exclusionGeos.length ?
|
||||
'specificLocations' : 'all';
|
||||
|
||||
this.exclusionGeos = new Set();
|
||||
if (exclusionGeos.length) {
|
||||
this.excludeSelected.id = exclusionGeos[0].zoneExclusionFk;
|
||||
exclusionGeos.forEach(x => this.exclusionGeos.add(x.geoFk));
|
||||
}
|
||||
|
||||
this.$.excludeDialog.show();
|
||||
}
|
||||
|
||||
createExclusion(days) {
|
||||
this.isNew = true;
|
||||
this.excludeSelected = {
|
||||
type: 'all',
|
||||
dated: days[0]
|
||||
};
|
||||
this.exclusionGeos = new Set();
|
||||
this.$.excludeDialog.show();
|
||||
}
|
||||
|
||||
onEditClick(row, event) {
|
||||
if (event.defaultPrevented) return;
|
||||
this.editInclusion(row);
|
||||
}
|
||||
|
||||
editInclusion(row) {
|
||||
this.isNew = false;
|
||||
this.selected = angular.copy(row);
|
||||
this.selected.wdays = this.vnWeekDays.fromSet(row.weekDays);
|
||||
this.$.includeDialog.show();
|
||||
}
|
||||
|
||||
createInclusion(type, days, weekday) {
|
||||
this.isNew = true;
|
||||
|
||||
if (type == 'weekday') {
|
||||
let wdays = [];
|
||||
if (weekday) wdays[weekday] = true;
|
||||
|
||||
this.selected = {
|
||||
type: 'indefinitely',
|
||||
wdays
|
||||
};
|
||||
} else {
|
||||
this.selected = {
|
||||
type: 'day',
|
||||
dated: days[0]
|
||||
};
|
||||
}
|
||||
|
||||
this.$.includeDialog.show();
|
||||
}
|
||||
|
||||
onIncludeResponse(response) {
|
||||
switch (response) {
|
||||
case 'accept': {
|
||||
let selected = this.selected;
|
||||
let type = selected.type;
|
||||
|
||||
selected.weekDays = this.vnWeekDays.toSet(selected.wdays);
|
||||
|
||||
if (type == 'day')
|
||||
selected.weekDays = '';
|
||||
else
|
||||
selected.dated = null;
|
||||
|
||||
if (type != 'range') {
|
||||
selected.started = null;
|
||||
selected.ended = null;
|
||||
}
|
||||
|
||||
let req;
|
||||
|
||||
if (this.isNew)
|
||||
req = this.$http.post(this.path, selected);
|
||||
else
|
||||
req = this.$http.put(`${this.path}/${selected.id}`, selected);
|
||||
|
||||
return req.then(() => {
|
||||
this.selected = null;
|
||||
this.isNew = null;
|
||||
this.refresh();
|
||||
});
|
||||
}
|
||||
case 'delete':
|
||||
return this.onDelete(this.selected.id)
|
||||
.then(response => response == 'accept');
|
||||
}
|
||||
}
|
||||
|
||||
onExcludeResponse(response) {
|
||||
const type = this.excludeSelected.type;
|
||||
switch (response) {
|
||||
case 'accept': {
|
||||
if (type == 'all')
|
||||
return this.exclusionCreate();
|
||||
return this.exclusionGeoCreate();
|
||||
}
|
||||
case 'delete':
|
||||
return this.exclusionDelete(this.excludeSelected);
|
||||
}
|
||||
}
|
||||
|
||||
onDeleteClick(id, event) {
|
||||
if (event.defaultPrevented) return;
|
||||
event.preventDefault();
|
||||
this.onDelete(id);
|
||||
}
|
||||
|
||||
onDelete(id) {
|
||||
return this.$.confirm.show(
|
||||
response => this.onDeleteResponse(response, id));
|
||||
}
|
||||
|
||||
onDeleteResponse(response, id) {
|
||||
if (response != 'accept' || !id) return;
|
||||
return this.$http.delete(`${this.path}/${id}`)
|
||||
.then(() => this.refresh());
|
||||
}
|
||||
|
||||
exclusionCreate() {
|
||||
const excludeSelected = this.excludeSelected;
|
||||
const dated = excludeSelected.dated;
|
||||
let req;
|
||||
|
||||
if (this.isNew)
|
||||
req = this.$http.post(this.exclusionsPath, [{dated}]);
|
||||
if (!this.isNew)
|
||||
req = this.$http.put(`${this.exclusionsPath}/${excludeSelected.id}`, {dated});
|
||||
|
||||
return req.then(() => {
|
||||
this.refresh();
|
||||
});
|
||||
}
|
||||
|
||||
exclusionGeoCreate() {
|
||||
const excludeSelected = this.excludeSelected;
|
||||
let req;
|
||||
const geoIds = [];
|
||||
this.exclusionGeos.forEach(id => geoIds.push(id));
|
||||
|
||||
if (this.isNew) {
|
||||
const params = {
|
||||
zoneFk: parseInt(this.$params.id),
|
||||
date: excludeSelected.dated,
|
||||
geoIds
|
||||
};
|
||||
req = this.$http.post(`Zones/exclusionGeo`, params);
|
||||
} else {
|
||||
const params = {
|
||||
zoneExclusionFk: this.excludeSelected.id,
|
||||
geoIds
|
||||
};
|
||||
req = this.$http.post(`Zones/updateExclusionGeo`, params);
|
||||
}
|
||||
return req.then(() => this.refresh());
|
||||
}
|
||||
|
||||
exclusionDelete(exclusion) {
|
||||
const path = `${this.exclusionsPath}/${exclusion.id}`;
|
||||
return this.$http.delete(path)
|
||||
.then(() => this.refresh());
|
||||
}
|
||||
|
||||
set excludeSearch(value) {
|
||||
this._excludeSearch = value;
|
||||
if (!value) this.onSearch();
|
||||
}
|
||||
|
||||
get excludeSearch() {
|
||||
return this._excludeSearch;
|
||||
}
|
||||
|
||||
onKeyDown(event) {
|
||||
if (event.key == 'Enter') {
|
||||
event.preventDefault();
|
||||
this.onSearch();
|
||||
}
|
||||
}
|
||||
|
||||
onSearch() {
|
||||
const params = {search: this._excludeSearch};
|
||||
if (this.excludeSelected.type == 'specificLocations') {
|
||||
this.$.model.applyFilter({}, params).then(() => {
|
||||
const data = this.$.model.data;
|
||||
this.getChecked(data);
|
||||
this.$.treeview.data = data;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
onFetch(item) {
|
||||
const params = item ? {parentId: item.id} : null;
|
||||
return this.$.model.applyFilter({}, params).then(() => {
|
||||
const data = this.$.model.data;
|
||||
this.getChecked(data);
|
||||
return data;
|
||||
});
|
||||
}
|
||||
|
||||
onSort(a, b) {
|
||||
if (b.selected !== a.selected) {
|
||||
if (a.selected == null)
|
||||
return 1;
|
||||
if (b.selected == null)
|
||||
return -1;
|
||||
return b.selected - a.selected;
|
||||
}
|
||||
|
||||
return a.name.localeCompare(b.name);
|
||||
}
|
||||
|
||||
getChecked(data) {
|
||||
for (let geo of data) {
|
||||
geo.checked = this.exclusionGeos.has(geo.id);
|
||||
if (geo.childs) this.getChecked(geo.childs);
|
||||
}
|
||||
}
|
||||
|
||||
onItemCheck(geoId, checked) {
|
||||
if (checked)
|
||||
this.exclusionGeos.add(geoId);
|
||||
else
|
||||
this.exclusionGeos.delete(geoId);
|
||||
}
|
||||
}
|
||||
Controller.$inject = ['$element', '$scope', 'vnWeekDays'];
|
||||
|
||||
ngModule.vnComponent('vnZoneEvents', {
|
||||
template: require('./index.html'),
|
||||
controller: Controller,
|
||||
bindings: {
|
||||
zone: '<'
|
||||
},
|
||||
require: {
|
||||
card: '^vnZoneCard'
|
||||
}
|
||||
});
|
|
@ -1,340 +0,0 @@
|
|||
import './index';
|
||||
import crudModel from 'core/mocks/crud-model';
|
||||
|
||||
describe('component vnZoneEvents', () => {
|
||||
let $scope;
|
||||
let controller;
|
||||
let $httpBackend;
|
||||
|
||||
beforeEach(ngModule('zone'));
|
||||
|
||||
beforeEach(inject(($componentController, $rootScope, _$httpBackend_) => {
|
||||
$httpBackend = _$httpBackend_;
|
||||
$scope = $rootScope.$new();
|
||||
const $element = angular.element(`<vn-zone-events></vn-zone-events>`);
|
||||
controller = $componentController('vnZoneEvents', {$element, $scope});
|
||||
controller.$params = {id: 1};
|
||||
}));
|
||||
|
||||
describe('refresh()', () => {
|
||||
it('should set the zone and then call both getSummary() and getWarehouses()', () => {
|
||||
const date = '2021-10-01';
|
||||
|
||||
controller.$params.id = 999;
|
||||
controller.$.calendar = {
|
||||
firstDay: date,
|
||||
lastDay: date
|
||||
};
|
||||
|
||||
const params = {
|
||||
zoneFk: controller.$params.id,
|
||||
started: date,
|
||||
ended: date
|
||||
};
|
||||
|
||||
const query = `Zones/getEventsFiltered?ended=${date}&started=${date}&zoneFk=${params.zoneFk}`;
|
||||
const response = {
|
||||
events: 'myEvents',
|
||||
exclusions: 'myExclusions',
|
||||
geoExclusions: 'myGeoExclusions',
|
||||
};
|
||||
$httpBackend.whenGET(query).respond(response);
|
||||
controller.refresh();
|
||||
$httpBackend.flush();
|
||||
|
||||
const data = controller.$.data;
|
||||
|
||||
expect(data.events).toBeDefined();
|
||||
expect(data.exclusions).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('onSelection()', () => {
|
||||
it('should call the editInclusion() method', () => {
|
||||
jest.spyOn(controller, 'editInclusion').mockReturnThis();
|
||||
|
||||
const weekday = {};
|
||||
const days = [];
|
||||
const type = 'EventType';
|
||||
const events = [{name: 'Event'}];
|
||||
const exclusions = [];
|
||||
const exclusionsGeo = [];
|
||||
controller.editMode = 'include';
|
||||
controller.onSelection(days, type, weekday, events, exclusions, exclusionsGeo);
|
||||
|
||||
expect(controller.editInclusion).toHaveBeenCalledWith({name: 'Event'});
|
||||
});
|
||||
|
||||
it('should call the createInclusion() method', () => {
|
||||
jest.spyOn(controller, 'createInclusion').mockReturnThis();
|
||||
|
||||
const weekday = {dated: Date.vnNew()};
|
||||
const days = [weekday];
|
||||
const type = 'EventType';
|
||||
const events = [];
|
||||
const exclusions = [];
|
||||
const exclusionsGeo = [];
|
||||
controller.editMode = 'include';
|
||||
controller.onSelection(days, type, weekday, events, exclusions, exclusionsGeo);
|
||||
|
||||
expect(controller.createInclusion).toHaveBeenCalledWith(type, days, weekday);
|
||||
});
|
||||
|
||||
it('should call the editExclusion() method with exclusions', () => {
|
||||
jest.spyOn(controller, 'editExclusion').mockReturnThis();
|
||||
|
||||
const weekday = {};
|
||||
const days = [];
|
||||
const type = 'EventType';
|
||||
const events = [];
|
||||
const exclusions = [{name: 'Exclusion'}];
|
||||
const exclusionsGeo = [];
|
||||
controller.editMode = 'exclude';
|
||||
controller.onSelection(days, type, weekday, events, exclusions, exclusionsGeo);
|
||||
|
||||
expect(controller.editExclusion).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should call the editExclusion() method with exclusionsGeo', () => {
|
||||
jest.spyOn(controller, 'editExclusion').mockReturnThis();
|
||||
|
||||
const weekday = {};
|
||||
const days = [];
|
||||
const type = 'EventType';
|
||||
const events = [];
|
||||
const exclusions = [];
|
||||
const exclusionsGeo = [{name: 'GeoExclusion'}];
|
||||
controller.editMode = 'exclude';
|
||||
controller.onSelection(days, type, weekday, events, exclusions, exclusionsGeo);
|
||||
|
||||
expect(controller.editExclusion).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should call the createExclusion() method', () => {
|
||||
jest.spyOn(controller, 'createExclusion').mockReturnThis();
|
||||
|
||||
const weekday = {};
|
||||
const days = [{dated: Date.vnNew()}];
|
||||
const type = 'EventType';
|
||||
const events = [];
|
||||
const exclusions = [];
|
||||
const exclusionsGeo = [];
|
||||
controller.editMode = 'exclude';
|
||||
controller.onSelection(days, type, weekday, events, exclusions, exclusionsGeo);
|
||||
|
||||
expect(controller.createExclusion).toHaveBeenCalledWith(days);
|
||||
});
|
||||
});
|
||||
|
||||
describe('editExclusion()', () => {
|
||||
it('shoud set the excludeSelected.type = "specificLocations" and then call the excludeDialog show() method', () => {
|
||||
controller.$.excludeDialog = {show: jest.fn()};
|
||||
|
||||
const exclusionGeos = [{id: 1}];
|
||||
const exclusions = [];
|
||||
|
||||
controller.editExclusion(exclusions, exclusionGeos);
|
||||
|
||||
expect(controller.excludeSelected.type).toEqual('specificLocations');
|
||||
expect(controller.$.excludeDialog.show).toHaveBeenCalledWith();
|
||||
});
|
||||
|
||||
it('shoud set the excludeSelected.type = "all" and then call the excludeDialog show() method', () => {
|
||||
controller.$.excludeDialog = {show: jest.fn()};
|
||||
|
||||
const exclusionGeos = [];
|
||||
const exclusions = [{id: 1}];
|
||||
|
||||
controller.editExclusion(exclusions, exclusionGeos);
|
||||
|
||||
expect(controller.excludeSelected.type).toEqual('all');
|
||||
expect(controller.$.excludeDialog.show).toHaveBeenCalledWith();
|
||||
});
|
||||
});
|
||||
|
||||
describe('createExclusion()', () => {
|
||||
it('shoud set the excludeSelected property and then call the excludeDialog show() method', () => {
|
||||
controller.$.excludeDialog = {show: jest.fn()};
|
||||
|
||||
const days = [Date.vnNew()];
|
||||
controller.createExclusion(days);
|
||||
|
||||
expect(controller.excludeSelected).toBeDefined();
|
||||
expect(controller.isNew).toBeTruthy();
|
||||
expect(controller.$.excludeDialog.show).toHaveBeenCalledWith();
|
||||
});
|
||||
});
|
||||
|
||||
describe('createInclusion()', () => {
|
||||
it('shoud set the selected property and then call the includeDialog show() method', () => {
|
||||
controller.$.includeDialog = {show: jest.fn()};
|
||||
|
||||
const type = 'weekday';
|
||||
const days = [Date.vnNew()];
|
||||
const weekday = 1;
|
||||
controller.createInclusion(type, days, weekday);
|
||||
|
||||
const selection = controller.selected;
|
||||
const firstWeekday = selection.wdays[weekday];
|
||||
|
||||
expect(selection.type).toEqual('indefinitely');
|
||||
expect(firstWeekday).toBeTruthy();
|
||||
expect(controller.isNew).toBeTruthy();
|
||||
expect(controller.$.includeDialog.show).toHaveBeenCalledWith();
|
||||
});
|
||||
|
||||
it('shoud set the selected property with the first day and then call the includeDialog show() method', () => {
|
||||
controller.$.includeDialog = {show: jest.fn()};
|
||||
|
||||
const type = 'nonListedType';
|
||||
const days = [Date.vnNew()];
|
||||
const weekday = 1;
|
||||
controller.createInclusion(type, days, weekday);
|
||||
|
||||
const selection = controller.selected;
|
||||
|
||||
expect(selection.type).toEqual('day');
|
||||
expect(selection.dated).toEqual(days[0]);
|
||||
expect(controller.isNew).toBeTruthy();
|
||||
expect(controller.$.includeDialog.show).toHaveBeenCalledWith();
|
||||
});
|
||||
});
|
||||
|
||||
describe('onIncludeResponse()', () => {
|
||||
it('shoud call the onDelete() method', () => {
|
||||
jest.spyOn(controller, 'onDelete').mockReturnValue(
|
||||
new Promise(accept => accept())
|
||||
);
|
||||
|
||||
controller.selected = {id: 1};
|
||||
controller.onIncludeResponse('delete');
|
||||
|
||||
expect(controller.onDelete).toHaveBeenCalledWith(1);
|
||||
});
|
||||
|
||||
it('shoud make an HTTP POST query to create a new one and then call the refresh() method', () => {
|
||||
jest.spyOn(controller, 'refresh').mockReturnThis();
|
||||
|
||||
controller.selected = {id: 1};
|
||||
controller.isNew = true;
|
||||
|
||||
$httpBackend.when('POST', `Zones/1/events`).respond(200);
|
||||
controller.onIncludeResponse('accept');
|
||||
$httpBackend.flush();
|
||||
|
||||
expect(controller.refresh).toHaveBeenCalledWith();
|
||||
});
|
||||
|
||||
it('shoud make an HTTP PUT query and then call the refresh() method', () => {
|
||||
jest.spyOn(controller, 'refresh').mockReturnThis();
|
||||
|
||||
controller.selected = {id: 1};
|
||||
controller.isNew = false;
|
||||
|
||||
const eventId = 1;
|
||||
$httpBackend.when('PUT', `Zones/1/events/${eventId}`).respond(200);
|
||||
controller.onIncludeResponse('accept');
|
||||
$httpBackend.flush();
|
||||
|
||||
expect(controller.refresh).toHaveBeenCalledWith();
|
||||
});
|
||||
});
|
||||
|
||||
describe('onExcludeResponse()', () => {
|
||||
it('should call the exclusionCreate() method', () => {
|
||||
jest.spyOn(controller, 'exclusionCreate').mockReturnThis();
|
||||
|
||||
controller.excludeSelected = {type: 'all'};
|
||||
controller.onExcludeResponse('accept');
|
||||
|
||||
expect(controller.exclusionCreate).toHaveBeenCalledWith();
|
||||
});
|
||||
|
||||
it('should call the exclusionGeoCreate() method', () => {
|
||||
jest.spyOn(controller, 'exclusionGeoCreate').mockReturnThis();
|
||||
|
||||
controller.excludeSelected = {type: 'specificLocations'};
|
||||
controller.onExcludeResponse('accept');
|
||||
|
||||
expect(controller.exclusionGeoCreate).toHaveBeenCalledWith();
|
||||
});
|
||||
|
||||
it('should call the exclusionDelete() method', () => {
|
||||
jest.spyOn(controller, 'exclusionDelete').mockReturnThis();
|
||||
|
||||
controller.excludeSelected = {id: 1, type: 'all'};
|
||||
controller.onExcludeResponse('delete');
|
||||
|
||||
expect(controller.exclusionDelete).toHaveBeenCalledWith(controller.excludeSelected);
|
||||
});
|
||||
});
|
||||
|
||||
describe('onDeleteResponse()', () => {
|
||||
it('shoud make an HTTP DELETE query and then call the refresh() method', () => {
|
||||
jest.spyOn(controller, 'refresh').mockReturnThis();
|
||||
|
||||
const eventId = 1;
|
||||
$httpBackend.expect('DELETE', `Zones/1/events/1`).respond({id: 1});
|
||||
controller.onDeleteResponse('accept', eventId);
|
||||
$httpBackend.flush();
|
||||
|
||||
expect(controller.refresh).toHaveBeenCalledWith();
|
||||
});
|
||||
});
|
||||
|
||||
describe('exclusionCreate()', () => {
|
||||
it('shoud make an HTTP POST query and then call the refresh() method', () => {
|
||||
jest.spyOn(controller, 'refresh').mockReturnThis();
|
||||
|
||||
controller.excludeSelected = {};
|
||||
controller.isNew = true;
|
||||
$httpBackend.expect('POST', `Zones/1/exclusions`).respond({id: 1});
|
||||
controller.exclusionCreate();
|
||||
$httpBackend.flush();
|
||||
|
||||
expect(controller.refresh).toHaveBeenCalledWith();
|
||||
});
|
||||
});
|
||||
|
||||
describe('exclusionDelete()', () => {
|
||||
it('shoud make an HTTP DELETE query once and then call the refresh() method', () => {
|
||||
jest.spyOn(controller, 'refresh').mockReturnThis();
|
||||
|
||||
const exclusions = {id: 1};
|
||||
const firstExclusionId = 1;
|
||||
$httpBackend.expectDELETE(`Zones/1/exclusions/${firstExclusionId}`).respond(200);
|
||||
controller.exclusionDelete(exclusions);
|
||||
$httpBackend.flush();
|
||||
|
||||
expect(controller.refresh).toHaveBeenCalledWith();
|
||||
});
|
||||
});
|
||||
|
||||
describe('onSearch()', () => {
|
||||
it('should call the applyFilter() method and then set the data', () => {
|
||||
jest.spyOn(controller, 'getChecked').mockReturnValue([1, 2, 3]);
|
||||
|
||||
controller.$.treeview = {};
|
||||
controller.$.model = crudModel;
|
||||
controller.excludeSelected = {type: 'specificLocations'};
|
||||
controller._excludeSearch = 'es';
|
||||
|
||||
controller.onSearch();
|
||||
const treeviewData = controller.$.treeview.data;
|
||||
|
||||
expect(treeviewData).toBeDefined();
|
||||
expect(treeviewData.length).toEqual(3);
|
||||
});
|
||||
});
|
||||
|
||||
describe('onFetch()', () => {
|
||||
it('should call the applyFilter() method and then return the model data', () => {
|
||||
jest.spyOn(controller, 'getChecked').mockReturnValue([1, 2, 3]);
|
||||
|
||||
controller.$.model = crudModel;
|
||||
const result = controller.onFetch();
|
||||
|
||||
expect(result.length).toEqual(3);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,12 +0,0 @@
|
|||
Edit mode: Modo de edición
|
||||
Include: Incluir
|
||||
Exclude: Excluir
|
||||
Events: Eventos
|
||||
Add event: Añadir evento
|
||||
Edit event: Editar evento
|
||||
All: Todo
|
||||
Specific locations: Localizaciones concretas
|
||||
Locations where it is not distributed: Localizaciones en las que no se reparte
|
||||
You must select a location: Debes seleccionar una localización
|
||||
Add exclusion: Añadir exclusión
|
||||
Edit exclusion: Editar exclusión
|
|
@ -1,11 +0,0 @@
|
|||
@import "variables";
|
||||
|
||||
.width{
|
||||
width: 600px
|
||||
}
|
||||
|
||||
.treeview{
|
||||
max-height: 300px;
|
||||
overflow: auto;
|
||||
}
|
||||
|
|
@ -1,19 +1,3 @@
|
|||
export * from './module';
|
||||
|
||||
import './main';
|
||||
import './index/';
|
||||
import './delivery-days';
|
||||
import './summary';
|
||||
import './card';
|
||||
import './descriptor';
|
||||
import './descriptor-popover';
|
||||
import './search-panel';
|
||||
import './create';
|
||||
import './basic-data';
|
||||
import './warehouses';
|
||||
import './events';
|
||||
import './calendar';
|
||||
import './location';
|
||||
import './calendar';
|
||||
import './upcoming-deliveries';
|
||||
import './log';
|
||||
|
|
|
@ -1,68 +0,0 @@
|
|||
<vn-auto-search
|
||||
model="model">
|
||||
</vn-auto-search>
|
||||
<vn-data-viewer
|
||||
model="model"
|
||||
class="vn-w-md vn-mb-xl">
|
||||
<vn-card>
|
||||
<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="hour" shrink>Closing</vn-th>
|
||||
<vn-th field="price" number>Price</vn-th>
|
||||
<vn-th shrink></vn-th>
|
||||
</vn-tr>
|
||||
</vn-thead>
|
||||
<vn-tbody>
|
||||
<a
|
||||
ng-repeat="zone in model.data"
|
||||
ui-sref="zone.card.summary({id: zone.id})"
|
||||
class="clickable vn-tr search-result">
|
||||
<vn-td number>{{::zone.id}}</vn-td>
|
||||
<vn-td expand>{{::zone.name}}</vn-td>
|
||||
<vn-td expand>{{::zone.agencyMode.name}}</vn-td>
|
||||
<vn-td shrink>{{::zone.hour | date: 'HH:mm'}}</vn-td>
|
||||
<vn-td number>{{::zone.price | currency: 'EUR':2}}</vn-td>
|
||||
<vn-td shrink>
|
||||
<vn-horizontal class="buttons">
|
||||
<vn-icon-button
|
||||
vn-click-stop="clone.show(zone)"
|
||||
vn-tooltip="Clone"
|
||||
icon="icon-clone"
|
||||
vn-acl="deliveryAssistant"
|
||||
vn-acl-action="remove">
|
||||
</vn-icon-button>
|
||||
<vn-icon-button
|
||||
vn-click-stop="$ctrl.preview(zone)"
|
||||
vn-tooltip="Preview"
|
||||
icon="preview">
|
||||
</vn-icon-button>
|
||||
</vn-horizontal>
|
||||
</vn-td>
|
||||
</a>
|
||||
</vn-tbody>
|
||||
</vn-table>
|
||||
</vn-card>
|
||||
</vn-data-viewer>
|
||||
<vn-popup vn-id="summary">
|
||||
<vn-zone-summary zone="$ctrl.selectedZone"></vn-zone-summary>
|
||||
</vn-popup>
|
||||
<vn-confirm
|
||||
vn-id="clone"
|
||||
on-accept="$ctrl.onCloneAccept($data)"
|
||||
question="Do you want to clone this zone?"
|
||||
message="All it's properties will be copied">
|
||||
</vn-confirm>
|
||||
<a ui-sref="zone.create"
|
||||
vn-tooltip="New zone"
|
||||
vn-bind="+"
|
||||
fixed-bottom-right>
|
||||
<vn-float-button
|
||||
icon="add"
|
||||
vn-acl="deliveryAssistant"
|
||||
vn-acl-action="remove">
|
||||
</vn-float-button>
|
||||
</a>
|
|
@ -1,21 +0,0 @@
|
|||
import ngModule from '../module';
|
||||
import Section from 'salix/components/section';
|
||||
|
||||
export default class Controller extends Section {
|
||||
preview(zone) {
|
||||
this.selectedZone = zone;
|
||||
this.$.summary.show();
|
||||
}
|
||||
|
||||
onCloneAccept(zone) {
|
||||
return this.$http.post(`Zones/${zone.id}/clone`)
|
||||
.then(res => {
|
||||
this.$state.go('zone.card.basicData', {id: res.data.id});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
ngModule.vnComponent('vnZoneIndex', {
|
||||
template: require('./index.html'),
|
||||
controller: Controller
|
||||
});
|
|
@ -1,2 +0,0 @@
|
|||
Do you want to clone this zone?: ¿Seguro que quieres clonar esta zona?
|
||||
All it's properties will be copied: Todas sus propiedades serán copiadas
|
|
@ -13,7 +13,7 @@ Indefinitely: Indefinido
|
|||
Inflation: Inflación
|
||||
Locations: Localizaciones
|
||||
Maximum m³: M³ máximo
|
||||
Max m³: Medida máxima
|
||||
Max m³: Medida máxima
|
||||
New zone: Nueva zona
|
||||
One day: Un día
|
||||
Pick up: Recogida
|
||||
|
@ -32,4 +32,4 @@ Warehouses: Almacenes
|
|||
Week days: Días de la semana
|
||||
Zones: Zonas
|
||||
zone: zona
|
||||
Go to the zone: Ir a la zona
|
||||
Go to the zone: Ir a la zona
|
||||
|
|
|
@ -1,28 +0,0 @@
|
|||
<vn-crud-model
|
||||
vn-id="model"
|
||||
url="Zones/{{$ctrl.$params.id}}/getLeaves"
|
||||
filter="$ctrl.filter">
|
||||
</vn-crud-model>
|
||||
<vn-portal slot="topbar">
|
||||
<vn-searchbar
|
||||
on-search="$ctrl.onSearch($params)"
|
||||
auto-state="false">
|
||||
</vn-searchbar>
|
||||
</vn-portal>
|
||||
<div class="vn-w-md">
|
||||
<vn-card class="vn-pa-lg">
|
||||
<vn-treeview
|
||||
vn-id="treeview"
|
||||
root-label="Locations"
|
||||
fetch-func="$ctrl.onFetch($item)"
|
||||
sort-func="$ctrl.onSort($a, $b)">
|
||||
<vn-check acl-role="deliveryAssistant"
|
||||
ng-model="item.selected"
|
||||
on-change="$ctrl.onSelection(value, item)"
|
||||
triple-state="true"
|
||||
ng-click="$event.preventDefault()"
|
||||
label="{{::item.name}}">
|
||||
</vn-check>
|
||||
</vn-treeview>
|
||||
</vn-card>
|
||||
</div>
|
|
@ -1,56 +0,0 @@
|
|||
import ngModule from '../module';
|
||||
import Section from 'salix/components/section';
|
||||
import './style.scss';
|
||||
|
||||
class Controller extends Section {
|
||||
onSearch(params) {
|
||||
this.$.model.applyFilter({}, params).then(() => {
|
||||
const data = this.$.model.data;
|
||||
this.$.treeview.data = data;
|
||||
});
|
||||
}
|
||||
|
||||
onFetch(item) {
|
||||
const params = item ? {parentId: item.id} : null;
|
||||
return this.$.model.applyFilter({}, params)
|
||||
.then(() => this.$.model.data);
|
||||
}
|
||||
|
||||
onSort(a, b) {
|
||||
if (b.selected !== a.selected) {
|
||||
if (a.selected == null)
|
||||
return 1;
|
||||
if (b.selected == null)
|
||||
return -1;
|
||||
return b.selected - a.selected;
|
||||
}
|
||||
|
||||
return a.name.localeCompare(b.name);
|
||||
}
|
||||
|
||||
exprBuilder(param, value) {
|
||||
switch (param) {
|
||||
case 'search':
|
||||
return {name: {like: `%${value}%`}};
|
||||
}
|
||||
}
|
||||
|
||||
onSelection(value, item) {
|
||||
if (value == null)
|
||||
value = undefined;
|
||||
const params = {geoId: item.id, isIncluded: value};
|
||||
const path = `zones/${this.zone.id}/toggleIsIncluded`;
|
||||
this.$http.post(path, params);
|
||||
}
|
||||
}
|
||||
|
||||
ngModule.vnComponent('vnZoneLocation', {
|
||||
template: require('./index.html'),
|
||||
controller: Controller,
|
||||
bindings: {
|
||||
zone: '<'
|
||||
},
|
||||
require: {
|
||||
card: '^vnZoneCard'
|
||||
}
|
||||
});
|
|
@ -1,50 +0,0 @@
|
|||
import './index';
|
||||
import crudModel from 'core/mocks/crud-model';
|
||||
|
||||
describe('component vnZoneLocation', () => {
|
||||
let $scope;
|
||||
let controller;
|
||||
let $httpBackend;
|
||||
|
||||
beforeEach(ngModule('zone'));
|
||||
|
||||
beforeEach(inject(($componentController, $rootScope, _$httpBackend_) => {
|
||||
$httpBackend = _$httpBackend_;
|
||||
$scope = $rootScope.$new();
|
||||
const $element = angular.element(`<vn-zone-location></vn-zone-location>`);
|
||||
controller = $componentController('vnZoneLocation', {$element, $scope});
|
||||
controller.$.model = crudModel;
|
||||
controller.zone = {id: 1};
|
||||
}));
|
||||
|
||||
describe('onSearch()', () => {
|
||||
it('should call the applyFilter() method and then set the data', () => {
|
||||
controller.$.treeview = {};
|
||||
controller.onSearch({});
|
||||
|
||||
const treeviewData = controller.$.treeview.data;
|
||||
|
||||
expect(treeviewData).toBeDefined();
|
||||
expect(treeviewData.length).toEqual(3);
|
||||
});
|
||||
});
|
||||
|
||||
describe('onFetch()', () => {
|
||||
it('should call the applyFilter() method and then return the model data', () => {
|
||||
const result = controller.onFetch();
|
||||
|
||||
expect(result.length).toEqual(3);
|
||||
});
|
||||
});
|
||||
|
||||
describe('onSelection()', () => {
|
||||
it('should make an HTTP POST query', () => {
|
||||
const item = {id: 123};
|
||||
|
||||
const expectedParams = {geoId: 123, isIncluded: true};
|
||||
$httpBackend.expect('POST', `zones/1/toggleIsIncluded`, expectedParams).respond(200);
|
||||
controller.onSelection(true, item);
|
||||
$httpBackend.flush();
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,21 +0,0 @@
|
|||
@import "variables";
|
||||
|
||||
vn-zone-location {
|
||||
vn-treeview-child {
|
||||
.content > .vn-check:not(.indeterminate):not(.checked) {
|
||||
color: $color-alert;
|
||||
|
||||
& > .btn {
|
||||
border-color: $color-alert;
|
||||
}
|
||||
}
|
||||
.content > .vn-check.checked {
|
||||
color: $color-notice;
|
||||
|
||||
& > .btn {
|
||||
background-color: $color-notice;
|
||||
border-color: $color-notice
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
<vn-log url="ZoneLogs" origin-id="$ctrl.$params.id"></vn-log>
|
|
@ -1,7 +0,0 @@
|
|||
import ngModule from '../module';
|
||||
import Section from 'salix/components/section';
|
||||
|
||||
ngModule.vnComponent('vnZoneLog', {
|
||||
template: require('./index.html'),
|
||||
controller: Section,
|
||||
});
|
|
@ -1,19 +0,0 @@
|
|||
<vn-crud-model
|
||||
vn-id="model"
|
||||
url="Zones"
|
||||
filter="::$ctrl.filter"
|
||||
limit="20">
|
||||
</vn-crud-model>
|
||||
<vn-portal slot="topbar">
|
||||
<vn-searchbar
|
||||
vn-focus
|
||||
info="Search zone by id or name"
|
||||
panel="vn-zone-search-panel"
|
||||
model="model"
|
||||
expr-builder="$ctrl.exprBuilder(param, value)">
|
||||
</vn-searchbar>
|
||||
</vn-portal>
|
||||
<vn-portal slot="menu">
|
||||
<vn-left-menu></vn-left-menu>
|
||||
</vn-portal>
|
||||
<ui-view></ui-view>
|
|
@ -4,25 +4,10 @@ import ModuleMain from 'salix/components/module-main';
|
|||
export default class Zone extends ModuleMain {
|
||||
constructor($element, $) {
|
||||
super($element, $);
|
||||
this.filter = {
|
||||
include: {
|
||||
relation: 'agencyMode',
|
||||
scope: {fields: ['name']}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
exprBuilder(param, value) {
|
||||
switch (param) {
|
||||
case 'search':
|
||||
return /^\d+$/.test(value)
|
||||
? {id: value}
|
||||
: {name: {like: `%${value}%`}};
|
||||
case 'name':
|
||||
return {[param]: {like: `%${value}%`}};
|
||||
case 'agencyModeFk':
|
||||
return {[param]: value};
|
||||
}
|
||||
async $onInit() {
|
||||
this.$state.go('home');
|
||||
window.location.href = await this.vnApp.getUrl(`zone/`);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,30 +0,0 @@
|
|||
import './index.js';
|
||||
|
||||
describe('Zone Component vnZone', () => {
|
||||
let controller;
|
||||
|
||||
beforeEach(ngModule('zone'));
|
||||
|
||||
beforeEach(inject($componentController => {
|
||||
const $element = angular.element('<vn-zone></vn-zone>');
|
||||
controller = $componentController('vnZone', {$element});
|
||||
}));
|
||||
|
||||
describe('exprBuilder()', () => {
|
||||
it('should return a formated object with the id in case of search', () => {
|
||||
let param = 'search';
|
||||
let value = 1;
|
||||
let result = controller.exprBuilder(param, value);
|
||||
|
||||
expect(result).toEqual({id: 1});
|
||||
});
|
||||
|
||||
it('should return a formated object with the agencyModeFk in case of agencyModeFk', () => {
|
||||
let param = 'agencyModeFk';
|
||||
let value = 'My Delivery';
|
||||
let result = controller.exprBuilder(param, value);
|
||||
|
||||
expect(result).toEqual({agencyModeFk: 'My Delivery'});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -7,15 +7,6 @@
|
|||
"menus": {
|
||||
"main": [
|
||||
{"state": "zone.index", "icon": "icon-zone"},
|
||||
{"state": "zone.deliveryDays", "icon": "today"},
|
||||
{"state": "zone.upcomingDeliveries", "icon": "today"}
|
||||
],
|
||||
"card": [
|
||||
{"state": "zone.card.basicData", "icon": "settings"},
|
||||
{"state": "zone.card.location", "icon": "my_location"},
|
||||
{"state": "zone.card.warehouses", "icon": "home"},
|
||||
{"state": "zone.card.log", "icon": "history"},
|
||||
{"state": "zone.card.events", "icon": "today"}
|
||||
]
|
||||
},
|
||||
"keybindings": [
|
||||
|
@ -34,79 +25,6 @@
|
|||
"state": "zone.index",
|
||||
"component": "vn-zone-index",
|
||||
"description": "Zones"
|
||||
},
|
||||
{
|
||||
"url": "/delivery-days?q&deliveryMethodFk&geoFk&agencyModeFk",
|
||||
"state": "zone.deliveryDays",
|
||||
"component": "vn-zone-delivery-days",
|
||||
"description": "Delivery days"
|
||||
},
|
||||
{
|
||||
"url": "/upcoming-deliveries",
|
||||
"state": "zone.upcomingDeliveries",
|
||||
"component": "vn-upcoming-deliveries",
|
||||
"description": "Upcoming deliveries"
|
||||
},
|
||||
{
|
||||
"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",
|
||||
"description": "Summary",
|
||||
"params": {
|
||||
"zone": "$ctrl.zone"
|
||||
}
|
||||
},
|
||||
{
|
||||
"url": "/basic-data",
|
||||
"state": "zone.card.basicData",
|
||||
"component": "vn-zone-basic-data",
|
||||
"description": "Basic data",
|
||||
"params": {
|
||||
"zone": "$ctrl.zone"
|
||||
}
|
||||
},
|
||||
{
|
||||
"url": "/warehouses",
|
||||
"state": "zone.card.warehouses",
|
||||
"component": "vn-zone-warehouses",
|
||||
"description": "Warehouses"
|
||||
},
|
||||
{
|
||||
"url": "/events?q",
|
||||
"state": "zone.card.events",
|
||||
"component": "vn-zone-events",
|
||||
"description": "Calendar",
|
||||
"params": {
|
||||
"zone": "$ctrl.zone"
|
||||
}
|
||||
},
|
||||
{
|
||||
"url": "/location?q",
|
||||
"state": "zone.card.location",
|
||||
"component": "vn-zone-location",
|
||||
"description": "Locations",
|
||||
"params": {
|
||||
"zone": "$ctrl.zone"
|
||||
}
|
||||
},
|
||||
{
|
||||
"url" : "/log",
|
||||
"state": "zone.card.log",
|
||||
"component": "vn-zone-log",
|
||||
"description": "Log"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,34 +0,0 @@
|
|||
<div class="search-panel">
|
||||
<form ng-submit="$ctrl.onSearch()">
|
||||
<vn-horizontal>
|
||||
<vn-textfield
|
||||
vn-one
|
||||
label="General search"
|
||||
ng-model="filter.search"
|
||||
info="Search zone by id or name"
|
||||
vn-focus>
|
||||
</vn-textfield>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-textfield
|
||||
vn-one
|
||||
label="Name"
|
||||
ng-model="filter.name">
|
||||
</vn-textfield>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-autocomplete
|
||||
vn-one
|
||||
label="Agency"
|
||||
ng-model="filter.agencyModeFk"
|
||||
url="AgencyModes/isActive"
|
||||
where="{deliveryMethodFk: {neq: null}}"
|
||||
value-field="id"
|
||||
show-field="name">
|
||||
</vn-autocomplete>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal class="vn-mt-lg">
|
||||
<vn-submit label="Search"></vn-submit>
|
||||
</vn-horizontal>
|
||||
</form>
|
||||
</div>
|
|
@ -1,7 +0,0 @@
|
|||
import ngModule from '../module';
|
||||
import SearchPanel from 'core/components/searchbar/search-panel';
|
||||
|
||||
ngModule.vnComponent('vnZoneSearchPanel', {
|
||||
template: require('./index.html'),
|
||||
controller: SearchPanel
|
||||
});
|
|
@ -1,59 +0,0 @@
|
|||
<vn-card class="summary">
|
||||
<h5>
|
||||
<a
|
||||
ng-if="::$ctrl.summary.id"
|
||||
vn-tooltip="Go to the zone"
|
||||
ui-sref="zone.card.summary({id: {{::$ctrl.summary.id}}})"
|
||||
name="goToSummary">
|
||||
<vn-icon-button icon="launch"></vn-icon-button>
|
||||
</a>
|
||||
<span>#{{$ctrl.summary.id}} - {{$ctrl.summary.name}}</span>
|
||||
</h5>
|
||||
<vn-horizontal class="vn-pa-md">
|
||||
<vn-one>
|
||||
<vn-label-value label="Agency"
|
||||
value="{{$ctrl.summary.agencyMode.name}}">
|
||||
</vn-label-value>
|
||||
<vn-label-value label="Price"
|
||||
value="{{$ctrl.summary.price | currency: 'EUR': 2}}">
|
||||
</vn-label-value>
|
||||
<vn-label-value label="Bonus"
|
||||
value="{{$ctrl.summary.bonus | currency: 'EUR': 2}}">
|
||||
</vn-label-value>
|
||||
</vn-one>
|
||||
<vn-one>
|
||||
<vn-label-value label="Closing hour"
|
||||
value="{{$ctrl.summary.hour | date: 'HH:mm'}}">
|
||||
</vn-label-value>
|
||||
<vn-label-value label="Traveling days"
|
||||
value="{{$ctrl.summary.travelingDays}}">
|
||||
</vn-label-value>
|
||||
<vn-vertical>
|
||||
<vn-check label="Volumetric" disabled="true"
|
||||
ng-model="$ctrl.summary.isVolumetric">
|
||||
</vn-check>
|
||||
</vn-vertical>
|
||||
</vn-one>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal class="vn-pa-md">
|
||||
<vn-auto>
|
||||
<h4>
|
||||
<a ui-sref="zone.card.warehouses({id:$ctrl.zone.id})">
|
||||
<span translate vn-tooltip="Go to">Warehouse</span>
|
||||
</a>
|
||||
</h4>
|
||||
<vn-table model="model" auto-load="false">
|
||||
<vn-thead>
|
||||
<vn-tr>
|
||||
<vn-th>Name</vn-th>
|
||||
</vn-tr>
|
||||
</vn-thead>
|
||||
<vn-tbody>
|
||||
<vn-tr ng-repeat="zoneWarehouse in $ctrl.zoneWarehouses">
|
||||
<vn-td>{{zoneWarehouse.warehouse.name}}</vn-td>
|
||||
</vn-tr>
|
||||
</vn-tbody>
|
||||
</vn-table>
|
||||
</vn-auto>
|
||||
</vn-horizontal>
|
||||
</vn-card>
|
|
@ -1,56 +0,0 @@
|
|||
import ngModule from '../module';
|
||||
import Summary from 'salix/components/summary';
|
||||
|
||||
class Controller extends Summary {
|
||||
get zone() {
|
||||
return this._zone;
|
||||
}
|
||||
|
||||
set zone(value) {
|
||||
this._zone = value;
|
||||
|
||||
if (!value) return;
|
||||
|
||||
this.getSummary();
|
||||
this.getWarehouses();
|
||||
}
|
||||
|
||||
getSummary() {
|
||||
const params = {
|
||||
filter: {
|
||||
include: {
|
||||
relation: 'agencyMode',
|
||||
fields: ['name']
|
||||
},
|
||||
where: {
|
||||
id: this.zone.id
|
||||
}
|
||||
}
|
||||
};
|
||||
this.$http.get(`Zones/findOne`, {params}).then(res => {
|
||||
this.summary = res.data;
|
||||
});
|
||||
}
|
||||
|
||||
getWarehouses() {
|
||||
const params = {
|
||||
filter: {
|
||||
include: {
|
||||
relation: 'warehouse',
|
||||
fields: ['name']
|
||||
}
|
||||
}
|
||||
};
|
||||
this.$http.get(`Zones/${this.zone.id}/warehouses`, {params}).then(res => {
|
||||
this.zoneWarehouses = res.data;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
ngModule.vnComponent('vnZoneSummary', {
|
||||
template: require('./index.html'),
|
||||
controller: Controller,
|
||||
bindings: {
|
||||
zone: '<'
|
||||
}
|
||||
});
|
|
@ -1,76 +0,0 @@
|
|||
import './index';
|
||||
|
||||
describe('component vnZoneSummary', () => {
|
||||
let $scope;
|
||||
let controller;
|
||||
let $httpBackend;
|
||||
let $httpParamSerializer;
|
||||
|
||||
beforeEach(ngModule('zone'));
|
||||
|
||||
beforeEach(inject(($componentController, $rootScope, _$httpBackend_, _$httpParamSerializer_) => {
|
||||
$httpBackend = _$httpBackend_;
|
||||
$httpParamSerializer = _$httpParamSerializer_;
|
||||
$scope = $rootScope.$new();
|
||||
const $element = angular.element(`<vn-zone-summary></vn-zone-summary>`);
|
||||
controller = $componentController('vnZoneSummary', {$element, $scope});
|
||||
}));
|
||||
|
||||
describe('zone setter', () => {
|
||||
it('should set the zone and then call both getSummary() and getWarehouses()', () => {
|
||||
jest.spyOn(controller, 'getSummary');
|
||||
jest.spyOn(controller, 'getWarehouses');
|
||||
|
||||
controller.zone = {id: 1};
|
||||
|
||||
expect(controller.getSummary).toHaveBeenCalledWith();
|
||||
expect(controller.getWarehouses).toHaveBeenCalledWith();
|
||||
});
|
||||
});
|
||||
|
||||
describe('getSummary()', () => {
|
||||
it('should perform a get and then store data on the controller', () => {
|
||||
controller._zone = {id: 1};
|
||||
let params = {
|
||||
filter: {
|
||||
include: {
|
||||
relation: 'agencyMode',
|
||||
fields: ['name']
|
||||
},
|
||||
where: {
|
||||
id: controller._zone.id
|
||||
}
|
||||
}
|
||||
};
|
||||
const serializedParams = $httpParamSerializer(params);
|
||||
const query = `Zones/findOne?${serializedParams}`;
|
||||
$httpBackend.expectGET(query).respond({id: 1});
|
||||
controller.getSummary();
|
||||
$httpBackend.flush();
|
||||
|
||||
expect(controller.summary).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('getWarehouses()', () => {
|
||||
it('should make an HTTP get query and then store data on the controller', () => {
|
||||
controller._zone = {id: 1};
|
||||
const params = {
|
||||
filter: {
|
||||
include: {
|
||||
relation: 'warehouse',
|
||||
fields: ['name']
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const serializedParams = $httpParamSerializer(params);
|
||||
const query = `Zones/1/warehouses?${serializedParams}`;
|
||||
$httpBackend.expect('GET', query).respond([{id: 1}]);
|
||||
controller.getWarehouses();
|
||||
$httpBackend.flush();
|
||||
|
||||
expect(controller.zoneWarehouses.length).toEqual(1);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,31 +0,0 @@
|
|||
<vn-crud-model
|
||||
vn-id="model"
|
||||
url="Zones/getUpcomingDeliveries"
|
||||
data="details"
|
||||
auto-load="true">
|
||||
</vn-crud-model>
|
||||
<vn-data-viewer model="model">
|
||||
<vn-card>
|
||||
<section ng-repeat="detail in details" class="vn-pa-md">
|
||||
<vn-horizontal class="header">
|
||||
<h5>{{$ctrl.getWeekDay(detail.shipped)}} - {{detail.shipped | date: 'dd/MM/yyyy'}}</h5>
|
||||
</vn-horizontal>
|
||||
<vn-table>
|
||||
<vn-thead>
|
||||
<vn-tr>
|
||||
<vn-th class="waste-family">Province</vn-th>
|
||||
<vn-th number>Closing</vn-th>
|
||||
<vn-th number>Id</vn-th>
|
||||
</vn-tr>
|
||||
</vn-thead>
|
||||
<vn-tbody>
|
||||
<vn-tr ng-repeat="zone in detail.lines">
|
||||
<vn-td class="waste-family">{{::zone.name}}</vn-td>
|
||||
<vn-td number>{{::zone.hour}}</vn-td>
|
||||
<vn-td number>{{::zone.zoneFk}}</vn-td>
|
||||
</vn-tr>
|
||||
</vn-tbody>
|
||||
</vn-table>
|
||||
</section>
|
||||
</vn-card>
|
||||
</vn-data-viewer>
|
|
@ -1,23 +0,0 @@
|
|||
import ngModule from '../module';
|
||||
import Section from 'salix/components/section';
|
||||
import './style.scss';
|
||||
|
||||
class Controller extends Section {
|
||||
constructor($element, $, vnWeekDays) {
|
||||
super($element, $);
|
||||
this.days = vnWeekDays.days;
|
||||
}
|
||||
|
||||
getWeekDay(jsonDate) {
|
||||
const weekDay = new Date(jsonDate).getDay();
|
||||
|
||||
return this.days[weekDay].locale;
|
||||
}
|
||||
}
|
||||
|
||||
Controller.$inject = ['$element', '$scope', 'vnWeekDays'];
|
||||
|
||||
ngModule.vnComponent('vnUpcomingDeliveries', {
|
||||
template: require('./index.html'),
|
||||
controller: Controller
|
||||
});
|
|
@ -1,22 +0,0 @@
|
|||
import './index';
|
||||
|
||||
describe('component vnUpcomingDeliveries', () => {
|
||||
let $scope;
|
||||
let controller;
|
||||
|
||||
beforeEach(ngModule('zone'));
|
||||
|
||||
beforeEach(inject(($componentController, $rootScope) => {
|
||||
$scope = $rootScope.$new();
|
||||
const $element = angular.element(`<vn-upcoming-deliveries></vn-upcoming-deliveries>`);
|
||||
controller = $componentController('vnUpcomingDeliveries', {$element, $scope});
|
||||
}));
|
||||
|
||||
describe('getWeekDay()', () => {
|
||||
it('should retrieve a weekday for a json passed', () => {
|
||||
let jsonDate = '1970-01-01T22:00:00.000Z';
|
||||
|
||||
expect(controller.getWeekDay(jsonDate)).toEqual('Thursday');
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,3 +0,0 @@
|
|||
Family: Familia
|
||||
Percentage: Porcentaje
|
||||
Dwindle: Mermas
|
|
@ -1,26 +0,0 @@
|
|||
@import "variables";
|
||||
|
||||
vn-upcoming-deliveries {
|
||||
.header {
|
||||
margin-bottom: 16px;
|
||||
text-transform: uppercase;
|
||||
font-size: 1.25rem;
|
||||
line-height: 1;
|
||||
padding: 7px;
|
||||
padding-bottom: 7px;
|
||||
padding-bottom: 4px;
|
||||
font-weight: lighter;
|
||||
background-color: $color-main-light;
|
||||
border-bottom: 1px solid $color-primary;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
background-color: $color-bg;
|
||||
}
|
||||
|
||||
vn-table vn-th.waste-family,
|
||||
vn-table vn-td.waste-family {
|
||||
max-width: 64px;
|
||||
width: 64px
|
||||
}
|
||||
}
|
|
@ -1,57 +0,0 @@
|
|||
<vn-data-viewer
|
||||
data="data"
|
||||
is-loading="!data"
|
||||
class="vn-w-xs">
|
||||
<vn-card>
|
||||
<vn-table>
|
||||
<vn-tbody>
|
||||
<vn-tr ng-repeat="row in data | orderBy:'warehouse.name'">
|
||||
<vn-td>{{::row.warehouse.name}}</vn-td>
|
||||
<vn-td shrink>
|
||||
<vn-icon-button
|
||||
icon="delete"
|
||||
translate-attr="{title: 'Delete'}"
|
||||
ng-click="$ctrl.onDelete(row)">
|
||||
</vn-icon-button>
|
||||
</vn-td>
|
||||
</vn-tr>
|
||||
</vn-tbody>
|
||||
</vn-table>
|
||||
</vn-card>
|
||||
</vn-data-viewer>
|
||||
<vn-float-button
|
||||
icon="add"
|
||||
translate-attr="{title: 'Add'}"
|
||||
vn-bind="+"
|
||||
ng-click="$ctrl.onCreate()"
|
||||
fixed-bottom-right>
|
||||
</vn-float-button>
|
||||
<vn-crud-model
|
||||
auto-load="true"
|
||||
url="Warehouses"
|
||||
data="warehouses"
|
||||
order="name">
|
||||
</vn-crud-model>
|
||||
<vn-dialog
|
||||
vn-id="dialog"
|
||||
on-accept="$ctrl.onSave()">
|
||||
<tpl-body>
|
||||
<vn-autocomplete
|
||||
ng-model="$ctrl.selected.warehouseFk"
|
||||
data="warehouses"
|
||||
show-field="name"
|
||||
value-field="id"
|
||||
label="Warehouse">
|
||||
</vn-autocomplete>
|
||||
</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-accept="$ctrl.delete()">
|
||||
</vn-confirm>
|
|
@ -1,56 +0,0 @@
|
|||
import ngModule from '../module';
|
||||
import Section from 'salix/components/section';
|
||||
|
||||
class Controller extends Section {
|
||||
$onInit() {
|
||||
this.refresh();
|
||||
}
|
||||
|
||||
get path() {
|
||||
return `Zones/${this.$params.id}/warehouses`;
|
||||
}
|
||||
|
||||
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() {
|
||||
this.$http.post(this.path, this.selected)
|
||||
.then(() => {
|
||||
this.selected = null;
|
||||
this.isNew = null;
|
||||
this.$.dialog.hide();
|
||||
this.refresh();
|
||||
});
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
onDelete(row) {
|
||||
this.$.confirm.show();
|
||||
this.deleteRow = row;
|
||||
}
|
||||
|
||||
delete() {
|
||||
let row = this.deleteRow;
|
||||
if (!row) return;
|
||||
return this.$http.delete(`${this.path}/${row.id}`)
|
||||
.then(() => {
|
||||
let index = this.$.data.indexOf(row);
|
||||
if (index !== -1) this.$.data.splice(index, 1);
|
||||
this.deleteRow = null;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
ngModule.vnComponent('vnZoneWarehouses', {
|
||||
template: require('./index.html'),
|
||||
controller: Controller
|
||||
});
|
|
@ -1,60 +0,0 @@
|
|||
import './index.js';
|
||||
|
||||
describe('Zone warehouses', () => {
|
||||
let $httpBackend;
|
||||
let $httpParamSerializer;
|
||||
let controller;
|
||||
let $element;
|
||||
|
||||
beforeEach(ngModule('zone'));
|
||||
|
||||
beforeEach(inject(($componentController, _$httpBackend_, _$httpParamSerializer_) => {
|
||||
$httpBackend = _$httpBackend_;
|
||||
$httpParamSerializer = _$httpParamSerializer_;
|
||||
$element = angular.element('<vn-zone-warehouses></vn-zone-warehouses');
|
||||
controller = $componentController('vnZoneWarehouses', {$element});
|
||||
controller.zone = {id: 1};
|
||||
controller.$params = {id: 1};
|
||||
controller.$.dialog = {hide: jest.fn()};
|
||||
}));
|
||||
|
||||
describe('refresh()', () => {
|
||||
it('should make an HTTP GET query and then set the data', () => {
|
||||
const params = {filter: {include: 'warehouse'}};
|
||||
const serializedParams = $httpParamSerializer(params);
|
||||
const path = `Zones/1/warehouses?${serializedParams}`;
|
||||
$httpBackend.expect('GET', path).respond([{id: 1, name: 'Warehouse one'}]);
|
||||
controller.refresh();
|
||||
$httpBackend.flush();
|
||||
|
||||
expect(controller.$.data).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('onSave()', () => {
|
||||
it('should make an HTTP POST query and then call the refresh() method', () => {
|
||||
jest.spyOn(controller, 'refresh').mockReturnThis();
|
||||
|
||||
$httpBackend.expect('POST', `Zones/1/warehouses`).respond(200);
|
||||
controller.onSave();
|
||||
$httpBackend.flush();
|
||||
|
||||
expect(controller.selected).toBeNull();
|
||||
expect(controller.isNew).toBeNull();
|
||||
expect(controller.$.dialog.hide).toHaveBeenCalledWith();
|
||||
expect(controller.refresh).toHaveBeenCalledWith();
|
||||
});
|
||||
});
|
||||
|
||||
describe('delete()', () => {
|
||||
it('should make an HTTP DELETE query and then set deleteRow property to null value', () => {
|
||||
controller.deleteRow = {id: 1};
|
||||
controller.$.data = [{id: 1}];
|
||||
$httpBackend.expect('DELETE', `Zones/1/warehouses/1`).respond(200);
|
||||
controller.delete();
|
||||
$httpBackend.flush();
|
||||
|
||||
expect(controller.deleteRow).toBeNull();
|
||||
});
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue