added zone prices, radio-group and calendar refactor #1320
gitea/salix/dev This commit looks good
Details
gitea/salix/dev This commit looks good
Details
This commit is contained in:
parent
b0c34f8e29
commit
8ff61a5d3a
|
@ -1,5 +1,4 @@
|
|||
const UserError = require('vn-loopback/util/user-error');
|
||||
const fs = require('fs-extra');
|
||||
|
||||
module.exports = Self => {
|
||||
Self.remoteMethodCtx('downloadFile', {
|
||||
|
@ -8,7 +7,7 @@ module.exports = Self => {
|
|||
accepts: [
|
||||
{
|
||||
arg: 'id',
|
||||
type: 'String',
|
||||
type: 'Number',
|
||||
description: 'The document id',
|
||||
http: {source: 'path'}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
const UserError = require('vn-loopback/util/user-error');
|
||||
const fs = require('fs-extra');
|
||||
const md5 = require('md5');
|
||||
|
||||
module.exports = Self => {
|
||||
Self.remoteMethodCtx('uploadFile', {
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
ALTER TABLE `vn`.`zoneCalendar`
|
||||
ADD COLUMN `price` DOUBLE NOT NULL AFTER `delivered`,
|
||||
ADD COLUMN `bonus` DOUBLE NOT NULL AFTER `price`;
|
|
@ -26,37 +26,55 @@
|
|||
|
||||
<vn-vertical class="body">
|
||||
<vn-horizontal class="weekdays">
|
||||
<section class="day" ng-click="$ctrl.selectAll(1)">
|
||||
<section title="{{'Monday' | translate}}"
|
||||
ng-click="$ctrl.selectAll(1)">
|
||||
<span>L</span>
|
||||
</section>
|
||||
<section class="day" ng-click="$ctrl.selectAll(2)">
|
||||
<section title="{{'Tuesday' | translate}}"
|
||||
ng-click="$ctrl.selectAll(2)">
|
||||
<span>M</span>
|
||||
</section>
|
||||
<section class="day" ng-click="$ctrl.selectAll(3)">
|
||||
<section title="{{'Wednesday' | translate}}"
|
||||
ng-click="$ctrl.selectAll(3)">
|
||||
<span>X</span>
|
||||
</section>
|
||||
<section class="day" ng-click="$ctrl.selectAll(4)">
|
||||
<section title="{{'Thursday' | translate}}"
|
||||
ng-click="$ctrl.selectAll(4)">
|
||||
<span>J</span>
|
||||
</section>
|
||||
<section class="day" ng-click="$ctrl.selectAll(5)">
|
||||
<section title="{{'Friday' | translate}}"
|
||||
ng-click="$ctrl.selectAll(5)">
|
||||
<span>V</span>
|
||||
</section>
|
||||
<section class="day" ng-click="$ctrl.selectAll(6)">
|
||||
<section title="{{'Saturday' | translate}}"
|
||||
ng-click="$ctrl.selectAll(6)">
|
||||
<span>S</span>
|
||||
</section>
|
||||
<section class="day" ng-click="$ctrl.selectAll(0)">
|
||||
<section title="{{'Sunday' | translate}}"
|
||||
ng-click="$ctrl.selectAll(0)">
|
||||
<span>D</span>
|
||||
</section>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal class="days">
|
||||
<section ng-repeat="day in $ctrl.days" class="day {{day.event.className || day.className}}"
|
||||
ng-click="$ctrl.select($index)"
|
||||
ng-style="{'color': day.event.style.color}">
|
||||
<span ng-if="day.event" vn-tooltip="{{day.event.title}}"
|
||||
ng-style="{'background-color': day.event.style.background}">
|
||||
<section ng-repeat="day in $ctrl.days" class="day"
|
||||
ng-class="{'primary': day.events.length > 0}">
|
||||
<div class="content">
|
||||
<div class="day-number"
|
||||
title="{{(day.events[0].description || day.events[0].name) | translate}}"
|
||||
ng-style="$ctrl.renderStyle(day.style || day.events[0].style)"
|
||||
ng-click="$ctrl.select($index)">
|
||||
{{::day.dated | date: 'd'}}
|
||||
</div>
|
||||
<div ng-if="day.events" class="events">
|
||||
<div ng-repeat="event in day.events" class="event"
|
||||
title="{{(event.description || event.name) | translate}}">
|
||||
<span class="chip ellipsize"
|
||||
ng-style="::$ctrl.renderStyle(event.style)">
|
||||
{{::event.name}}
|
||||
</span>
|
||||
<span ng-if="!day.event">{{::day.dated | date: 'd'}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</vn-horizontal>
|
||||
</vn-vertical>
|
||||
|
|
|
@ -13,6 +13,23 @@ export default class Calendar extends Component {
|
|||
this.defaultDate = new Date();
|
||||
this.displayControls = true;
|
||||
this.skip = 1;
|
||||
|
||||
this.window.addEventListener('resize', () => {
|
||||
this.checkSize();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Resizes the calendar
|
||||
* based on component height
|
||||
*/
|
||||
checkSize() {
|
||||
const height = this.$element[0].clientHeight;
|
||||
|
||||
if (height < 530)
|
||||
this.$element.addClass('small');
|
||||
else
|
||||
this.$element.removeClass('small');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -49,8 +66,10 @@ export default class Calendar extends Component {
|
|||
this.addEvent(event);
|
||||
});
|
||||
|
||||
if (value.length && this.defaultDate)
|
||||
if (value.length && this.defaultDate) {
|
||||
this.repaint();
|
||||
this.checkSize();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -165,16 +184,28 @@ export default class Calendar extends Component {
|
|||
* @param {Date} dated - Date of month
|
||||
* @param {String} className - Default class style
|
||||
*/
|
||||
insertDay(dated, className = '') {
|
||||
let event = this.events.find(event => {
|
||||
insertDay(dated) {
|
||||
let events = this.events.filter(event => {
|
||||
return event.dated >= dated && event.dated <= dated;
|
||||
});
|
||||
|
||||
// Weeekends
|
||||
if (dated.getMonth() === this.currentMonth.getMonth() && dated.getDay() == 0)
|
||||
className = 'red';
|
||||
const params = {dated, events};
|
||||
|
||||
this.days.push({dated, className, event});
|
||||
const isSaturday = dated.getDay() === 6;
|
||||
const isSunday = dated.getDay() === 0;
|
||||
const isCurrentMonth = dated.getMonth() === this.currentMonth.getMonth();
|
||||
const hasEvents = events.length > 0;
|
||||
|
||||
if (isCurrentMonth && isSunday && !hasEvents)
|
||||
params.style = {color: '#f42121'};
|
||||
|
||||
if (isCurrentMonth && isSaturday && !hasEvents)
|
||||
params.style = {color: '#666666'};
|
||||
|
||||
if (!isCurrentMonth && !hasEvents)
|
||||
params.style = {color: '#9b9b9b'};
|
||||
|
||||
this.days.push(params);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -182,7 +213,7 @@ export default class Calendar extends Component {
|
|||
*
|
||||
* @param {Object} options - Event params
|
||||
* @param {Date} options.dated - Day to add event
|
||||
* @param {String} options.title - Tooltip description
|
||||
* @param {String} options.name - Tooltip description
|
||||
* @param {String} options.className - ClassName style
|
||||
* @param {Object} options.style - Style properties
|
||||
* @param {Boolean} options.isRemovable - True if is removable by users
|
||||
|
@ -194,11 +225,6 @@ export default class Calendar extends Component {
|
|||
options.dated = new Date(options.dated);
|
||||
options.dated.setHours(0, 0, 0, 0);
|
||||
|
||||
const event = this.events.findIndex(event => {
|
||||
return event.dated >= options.dated && event.dated <= options.dated;
|
||||
});
|
||||
|
||||
if (event < 0)
|
||||
this.events.push(options);
|
||||
}
|
||||
|
||||
|
@ -274,6 +300,16 @@ export default class Calendar extends Component {
|
|||
}
|
||||
this.emit('selection', {values: selected});
|
||||
}
|
||||
|
||||
renderStyle(style) {
|
||||
if (style) {
|
||||
return {
|
||||
'background-color': style.backgroundColor,
|
||||
'font-weight': style.fontWeight,
|
||||
'color': style.color
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Calendar.$inject = ['$element', '$scope'];
|
||||
|
|
|
@ -20,8 +20,8 @@ describe('Component vnCalendar', () => {
|
|||
|
||||
let currentDate = new Date().toString();
|
||||
controller.data = [
|
||||
{dated: currentDate, title: 'Event 1'},
|
||||
{dated: currentDate, title: 'Event 2'},
|
||||
{dated: currentDate, name: 'Event 1'},
|
||||
{dated: currentDate, name: 'Event 2'},
|
||||
];
|
||||
|
||||
expect(controller.events[0].dated instanceof Object).toBeTruthy();
|
||||
|
@ -34,12 +34,11 @@ describe('Component vnCalendar', () => {
|
|||
controller.events = [];
|
||||
controller.addEvent({
|
||||
dated: new Date(),
|
||||
title: 'My event',
|
||||
className: 'color'
|
||||
name: 'My event'
|
||||
});
|
||||
const firstEvent = controller.events[0];
|
||||
|
||||
expect(firstEvent.title).toEqual('My event');
|
||||
expect(firstEvent.name).toEqual('My event');
|
||||
expect(firstEvent.isRemovable).toBeDefined();
|
||||
expect(firstEvent.isRemovable).toBeTruthy();
|
||||
});
|
||||
|
@ -50,19 +49,17 @@ describe('Component vnCalendar', () => {
|
|||
|
||||
controller.events = [{
|
||||
dated: curDate,
|
||||
title: 'My event 1',
|
||||
className: 'color'
|
||||
name: 'My event 1'
|
||||
}];
|
||||
controller.addEvent({
|
||||
dated: curDate,
|
||||
title: 'My event 2',
|
||||
className: 'color'
|
||||
name: 'My event 2'
|
||||
});
|
||||
|
||||
const firstEvent = controller.events[0];
|
||||
|
||||
expect(controller.events.length).toEqual(1);
|
||||
expect(firstEvent.title).toEqual('My event 1');
|
||||
expect(controller.events.length).toEqual(2);
|
||||
expect(firstEvent.name).toEqual('My event 1');
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -71,7 +68,7 @@ describe('Component vnCalendar', () => {
|
|||
const curDate = new Date();
|
||||
controller._events = [{
|
||||
dated: curDate,
|
||||
title: 'My event 1',
|
||||
name: 'My event 1',
|
||||
className: 'color'
|
||||
}];
|
||||
controller.removeEvent(curDate);
|
||||
|
|
|
@ -1,143 +1,123 @@
|
|||
@import "variables";
|
||||
|
||||
vn-calendar.small {
|
||||
.events {
|
||||
display: none
|
||||
}
|
||||
}
|
||||
|
||||
vn-calendar {
|
||||
display: block;
|
||||
max-width: 250px;
|
||||
|
||||
.header vn-one {
|
||||
text-align: center;
|
||||
padding: 0.2em 0
|
||||
padding: 0.2em 0;
|
||||
height: 1.5em
|
||||
}
|
||||
|
||||
|
||||
.weekdays {
|
||||
color: $color-font-secondary;
|
||||
margin-bottom: 0.5em;
|
||||
padding: 0.5em 0;
|
||||
font-weight: bold;
|
||||
font-size: 0.8em;
|
||||
}
|
||||
|
||||
.weekdays section {
|
||||
cursor: pointer
|
||||
}
|
||||
|
||||
.weekdays section, .day {
|
||||
position: relative;
|
||||
text-align: center;
|
||||
box-sizing: border-box;
|
||||
width: 14.28%;
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
.body {
|
||||
.days {
|
||||
justify-content: flex-start;
|
||||
align-items: flex-start;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.weekdays {
|
||||
border-bottom: 1px solid $color-hover-cd;
|
||||
border-top: 1px solid $color-hover-cd;
|
||||
color: $color-font-secondary;
|
||||
font-weight: bold
|
||||
}
|
||||
|
||||
.day {
|
||||
box-sizing: border-box;
|
||||
padding: 0.1em;
|
||||
width: 14.2857143%;
|
||||
line-height: 1.5em;
|
||||
outline: 0;
|
||||
.content {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
top: 0
|
||||
}
|
||||
|
||||
span {
|
||||
.day-number {
|
||||
transition: background-color 0.3s;
|
||||
text-align: center;
|
||||
font-size: .8em;
|
||||
text-align:center;
|
||||
float:inline-end;
|
||||
margin: 0 auto;
|
||||
border-radius: 50%;
|
||||
display: block;
|
||||
padding: 0.2em;
|
||||
cursor: pointer
|
||||
font-size: 0.85em;
|
||||
width:2.2em;
|
||||
height: 1.2em;
|
||||
padding: 0.5em 0;
|
||||
cursor: pointer;
|
||||
outline: 0
|
||||
}
|
||||
|
||||
.day-number:hover {
|
||||
background-color: lighten($color-font-secondary, 20%);
|
||||
opacity: 0.8
|
||||
}
|
||||
}
|
||||
|
||||
.day:hover span {
|
||||
background-color: #DDD
|
||||
.day::after {
|
||||
content: "";
|
||||
display: block;
|
||||
padding-top: 100%;
|
||||
}
|
||||
|
||||
.day.primary .day-number {
|
||||
background-color: $color-main;
|
||||
color: $color-font-bg;
|
||||
}
|
||||
|
||||
.events {
|
||||
margin-top: 0.5em;
|
||||
font-size: 0.6em
|
||||
}
|
||||
|
||||
|
||||
.events {
|
||||
color: $color-font-secondary;
|
||||
|
||||
.event {
|
||||
margin-bottom: .1em;
|
||||
}
|
||||
}
|
||||
|
||||
.chip {
|
||||
background-color: $color-main;
|
||||
color: $color-font-bg;
|
||||
display: inline-block;
|
||||
border-radius: .3em;
|
||||
padding: 0.3em .8em;
|
||||
max-width: 5em;
|
||||
}
|
||||
|
||||
.day.gray {
|
||||
.day-number {
|
||||
color: $color-font-secondary
|
||||
}
|
||||
|
||||
.day.orange {
|
||||
font-weight: bold;
|
||||
color: $color-main;
|
||||
}
|
||||
|
||||
.day.orange-circle {
|
||||
color: $color-font;
|
||||
& > span {
|
||||
background-color: $color-main
|
||||
}
|
||||
}
|
||||
|
||||
.day.orange-circle:hover {
|
||||
& > span {
|
||||
background-color: $color-main-medium
|
||||
}
|
||||
}
|
||||
|
||||
.day.light-orange {
|
||||
color: $color-main-medium
|
||||
}
|
||||
|
||||
.day.green {
|
||||
font-weight: bold;
|
||||
color: $color-success;
|
||||
}
|
||||
|
||||
.day.green-circle {
|
||||
color: $color-font;
|
||||
& > span {
|
||||
background-color: $color-success
|
||||
}
|
||||
}
|
||||
|
||||
.day.green-circle:hover {
|
||||
& > span {
|
||||
background-color: $color-success-medium
|
||||
}
|
||||
}
|
||||
|
||||
.day.light-green {
|
||||
font-weight: bold;
|
||||
color: $color-success-medium
|
||||
}
|
||||
|
||||
.day.blue {
|
||||
font-weight: bold;
|
||||
color: $color-notice;
|
||||
}
|
||||
|
||||
.day.blue-circle {
|
||||
color: $color-font;
|
||||
& > span {
|
||||
background-color: $color-notice
|
||||
}
|
||||
}
|
||||
|
||||
.day.blue-circle:hover {
|
||||
& > span {
|
||||
background-color: $color-notice-medium
|
||||
}
|
||||
}
|
||||
|
||||
.day.light-blue {
|
||||
font-weight: bold;
|
||||
color: $color-notice-medium
|
||||
}
|
||||
|
||||
.day.red {
|
||||
font-weight: bold;
|
||||
color: $color-alert
|
||||
}
|
||||
|
||||
.day.red-circle {
|
||||
color: $color-font;
|
||||
& > span {
|
||||
background-color: $color-alert
|
||||
}
|
||||
}
|
||||
|
||||
.day.red-circle:hover {
|
||||
& > span {
|
||||
background-color: $color-alert-medium
|
||||
}
|
||||
}
|
||||
|
||||
.day.light-red {
|
||||
font-weight: bold;
|
||||
color: $color-alert-medium;
|
||||
.day.sunday {
|
||||
.day-number {
|
||||
color: $color-alert;
|
||||
font-weight: bold
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,8 +45,7 @@ export default class Dialog extends Component {
|
|||
this.element.style.display = 'flex';
|
||||
this.transitionTimeout = setTimeout(() => this.$element.addClass('shown'), 30);
|
||||
|
||||
if (this.onOpen)
|
||||
this.onOpen();
|
||||
this.emit('open');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -55,6 +54,7 @@ export default class Dialog extends Component {
|
|||
hide() {
|
||||
this.fireResponse();
|
||||
this.realHide();
|
||||
this.emit('close');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -120,7 +120,6 @@ ngModule.component('vnDialog', {
|
|||
buttons: '?tplButtons'
|
||||
},
|
||||
bindings: {
|
||||
onOpen: '&?',
|
||||
onResponse: '&?'
|
||||
},
|
||||
controller: Dialog
|
||||
|
|
|
@ -7,7 +7,7 @@ describe('Component vnDialog', () => {
|
|||
beforeEach(angular.mock.inject($componentController => {
|
||||
$element = angular.element('<vn-dialog></vn-dialog>');
|
||||
controller = $componentController('vnDialog', {$element, $transclude: null});
|
||||
controller.onOpen = jasmine.createSpy('onOpen');
|
||||
controller.emit = jasmine.createSpy('emit');
|
||||
}));
|
||||
|
||||
describe('show()', () => {
|
||||
|
@ -17,15 +17,15 @@ describe('Component vnDialog', () => {
|
|||
controller.show();
|
||||
|
||||
expect(controller.element.style.display).toEqual('none');
|
||||
expect(controller.onOpen).not.toHaveBeenCalledWith();
|
||||
expect(controller.emit).not.toHaveBeenCalledWith('open');
|
||||
});
|
||||
|
||||
it(`should set shown on the controller, set style.display on the element and call onOpen()`, () => {
|
||||
it(`should set shown on the controller, set style.display on the element and emit onOpen() event`, () => {
|
||||
controller.show();
|
||||
|
||||
expect(controller.element.style.display).toEqual('flex');
|
||||
expect(controller.shown).toBeTruthy();
|
||||
expect(controller.onOpen).toHaveBeenCalledWith();
|
||||
expect(controller.emit).toHaveBeenCalledWith('open');
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ import './multi-check/multi-check';
|
|||
import './date-picker/date-picker';
|
||||
import './button/button';
|
||||
import './check/check';
|
||||
import './radio/radio';
|
||||
import './radio-group/radio-group';
|
||||
import './textarea/textarea';
|
||||
import './icon-button/icon-button';
|
||||
import './submit/submit';
|
||||
|
|
|
@ -22,7 +22,10 @@
|
|||
ng-focus="$ctrl.hasFocus = true"
|
||||
ng-blur="$ctrl.hasFocus = false"
|
||||
tabindex="{{$ctrl.input.tabindex}}"/>
|
||||
<label class="label" translate>{{::$ctrl.label}}</label>
|
||||
<label class="label">
|
||||
<span translate>{{::$ctrl.label}}</span>
|
||||
<span translate ng-show="::$ctrl.required">*</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="underline"></div>
|
||||
<div class="selected underline"></div>
|
||||
|
|
|
@ -192,6 +192,7 @@ ngModule.component('vnInputNumber', {
|
|||
label: '@?',
|
||||
name: '@?',
|
||||
disabled: '<?',
|
||||
required: '@?',
|
||||
min: '<?',
|
||||
max: '<?',
|
||||
step: '<?',
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
<md-radio-group ng-model="$ctrl.model">
|
||||
<md-radio-button aria-label="::option.label"
|
||||
ng-repeat="option in $ctrl.options"
|
||||
ng-value="option.value"
|
||||
ng-disabled="$ctrl.disabled">
|
||||
<span translate>{{::option.label}}</span>
|
||||
</md-radio-button>
|
||||
</md-radio-group>
|
|
@ -0,0 +1,41 @@
|
|||
import ngModule from '../../module';
|
||||
import Component from '../../lib/component';
|
||||
import './style.scss';
|
||||
|
||||
export default class Controller extends Component {
|
||||
constructor($element, $scope, $attrs) {
|
||||
super($element, $scope);
|
||||
this.hasInfo = Boolean($attrs.info);
|
||||
this.info = $attrs.info || null;
|
||||
}
|
||||
|
||||
get model() {
|
||||
return this._model;
|
||||
}
|
||||
|
||||
set model(value) {
|
||||
this._model = value;
|
||||
}
|
||||
|
||||
get field() {
|
||||
return this._model;
|
||||
}
|
||||
|
||||
set field(value) {
|
||||
this._model = value;
|
||||
}
|
||||
}
|
||||
|
||||
Controller.$inject = ['$element', '$scope', '$attrs'];
|
||||
|
||||
ngModule.component('vnRadioGroup', {
|
||||
template: require('./radio-group.html'),
|
||||
controller: Controller,
|
||||
|
||||
bindings: {
|
||||
field: '=?',
|
||||
options: '<?',
|
||||
disabled: '<?',
|
||||
checked: '<?'
|
||||
}
|
||||
});
|
|
@ -0,0 +1,11 @@
|
|||
@import "variables";
|
||||
|
||||
md-radio-group md-radio-button.md-checked .md-container {
|
||||
.md-on {
|
||||
background-color: $color-main
|
||||
}
|
||||
|
||||
.md-off {
|
||||
border-color: $color-main
|
||||
}
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
<input
|
||||
type="radio"
|
||||
class="*[className]*"
|
||||
name="*[name]*"
|
||||
ng-model="*[model]*.*[name]*"
|
||||
*[enabled]*>
|
||||
<span class="mdl-radio__label" translate>*[text]*</span>
|
|
@ -1,15 +0,0 @@
|
|||
import ngModule from '../../module';
|
||||
import template from './radio.html';
|
||||
|
||||
directive.$inject = ['vnTemplate'];
|
||||
export default function directive(vnTemplate) {
|
||||
return {
|
||||
restrict: 'E',
|
||||
template: (_, $attrs) =>
|
||||
vnTemplate.get(template, $attrs, {
|
||||
enabled: 'true',
|
||||
className: 'mdl-radio mdl-js-radio mdl-js-ripple-effect'
|
||||
})
|
||||
};
|
||||
}
|
||||
ngModule.directive('vnRadio', directive);
|
|
@ -16,7 +16,7 @@
|
|||
tabindex="{{$ctrl.input.tabindex}}"/>
|
||||
<label class="label">
|
||||
<span translate>{{::$ctrl.label}}</span>
|
||||
<span translate ng-show="::$ctrl.required">(*)</span>
|
||||
<span translate vn-tooltip="Required" ng-show="::$ctrl.required">*</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="underline"></div>
|
||||
|
|
|
@ -52,6 +52,8 @@ $color-hover-cd: rgba(0, 0, 0, .1);
|
|||
$color-hover-dc: .7;
|
||||
$color-disabled: .6;
|
||||
|
||||
$color-font-link-medium: lighten($color-font-link, 20%);
|
||||
$color-font-link-light: lighten($color-font-link, 35%);
|
||||
$color-main-medium: lighten($color-main, 20%);
|
||||
$color-main-light: lighten($color-main, 35%);
|
||||
$color-success-medium: lighten($color-success, 20%);
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
const mergeFilters = require('vn-loopback/util/filter').mergeFilters;
|
||||
|
||||
module.exports = Self => {
|
||||
Self.remoteMethod('editPrices', {
|
||||
description: 'Changes the price and bonus of a delivery day',
|
||||
accessType: 'WRITE',
|
||||
accepts: [{
|
||||
arg: 'id',
|
||||
type: 'Number',
|
||||
description: 'The zone id',
|
||||
http: {source: 'path'}
|
||||
},
|
||||
{
|
||||
arg: 'delivered',
|
||||
type: 'Date',
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
arg: 'price',
|
||||
type: 'Number',
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
arg: 'bonus',
|
||||
type: 'Number',
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
arg: 'option',
|
||||
type: 'String',
|
||||
required: true,
|
||||
}],
|
||||
returns: {
|
||||
type: 'object',
|
||||
root: true
|
||||
},
|
||||
http: {
|
||||
path: `/:id/editPrices`,
|
||||
verb: 'POST'
|
||||
}
|
||||
});
|
||||
|
||||
Self.editPrices = async(id, delivered, price, bonus, option) => {
|
||||
const models = Self.app.models;
|
||||
|
||||
let filter = {
|
||||
where: {
|
||||
zoneFk: id
|
||||
}
|
||||
};
|
||||
|
||||
let where;
|
||||
let shouldPropagate = true;
|
||||
|
||||
if (option == 'Only this day') {
|
||||
shouldPropagate = false;
|
||||
where = {delivered};
|
||||
} else if (option == 'From this day') {
|
||||
where = {
|
||||
delivered: {
|
||||
gte: delivered
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
filter = mergeFilters(filter, {where});
|
||||
|
||||
const days = await models.ZoneCalendar.find(filter);
|
||||
const areAllFromSameZone = days.every(day => day.zoneFk === id);
|
||||
|
||||
if (!areAllFromSameZone)
|
||||
throw new UserError('All delivery days must belong to the same zone');
|
||||
|
||||
if (shouldPropagate) {
|
||||
const zone = await models.Zone.findById(id);
|
||||
zone.updateAttributes({price, bonus});
|
||||
}
|
||||
|
||||
return models.ZoneCalendar.updateAll(filter.where, {price, bonus});
|
||||
};
|
||||
};
|
|
@ -0,0 +1,84 @@
|
|||
const app = require('vn-loopback/server/server');
|
||||
|
||||
describe('agency editPrices()', () => {
|
||||
const zoneId = 1;
|
||||
let originalZone;
|
||||
|
||||
beforeAll(async done => {
|
||||
originalZone = await app.models.Zone.findById(zoneId);
|
||||
done();
|
||||
});
|
||||
|
||||
afterAll(async done => {
|
||||
await await app.models.ZoneCalendar.updateAll({zoneFk: zoneId}, {
|
||||
price: originalZone.price,
|
||||
bonus: originalZone.bonus
|
||||
});
|
||||
done();
|
||||
});
|
||||
|
||||
it('should apply price and bonus for a selected day', async() => {
|
||||
const delivered = new Date();
|
||||
delivered.setHours(0, 0, 0, 0);
|
||||
delivered.setDate(delivered.getDate() + 1);
|
||||
await app.models.Zone.editPrices(zoneId, delivered, 4.00, 2.00, 'Only this day');
|
||||
|
||||
const editedDays = await app.models.ZoneCalendar.find({
|
||||
where: {
|
||||
zoneFk: zoneId,
|
||||
delivered: delivered
|
||||
}
|
||||
});
|
||||
const firstEditedDay = editedDays[0];
|
||||
|
||||
expect(editedDays.length).toEqual(1);
|
||||
expect(firstEditedDay.price).toEqual(4.00);
|
||||
expect(firstEditedDay.bonus).toEqual(2.00);
|
||||
});
|
||||
|
||||
it('should apply price and bonus for all delivery days starting from selected day', async() => {
|
||||
const delivered = new Date();
|
||||
delivered.setHours(0, 0, 0, 0);
|
||||
delivered.setDate(delivered.getDate() + 1);
|
||||
await app.models.Zone.editPrices(1, delivered, 5.50, 1.00, 'From this day');
|
||||
|
||||
const editedDays = await app.models.ZoneCalendar.find({
|
||||
where: {
|
||||
zoneFk: zoneId,
|
||||
delivered: {
|
||||
gte: delivered
|
||||
}
|
||||
}
|
||||
});
|
||||
const firstEditedDay = editedDays[0];
|
||||
const lastEditedDay = editedDays[editedDays.length - 1];
|
||||
|
||||
expect(editedDays.length).toEqual(4);
|
||||
expect(firstEditedDay.price).toEqual(5.50);
|
||||
expect(firstEditedDay.bonus).toEqual(1.00);
|
||||
expect(lastEditedDay.price).toEqual(5.50);
|
||||
expect(lastEditedDay.bonus).toEqual(1.00);
|
||||
});
|
||||
|
||||
it('should apply price and bonus for all delivery days', async() => {
|
||||
const delivered = new Date();
|
||||
delivered.setHours(0, 0, 0, 0);
|
||||
delivered.setDate(delivered.getDate() + 1);
|
||||
await app.models.Zone.editPrices(1, delivered, 7.00, 0.00, 'All days');
|
||||
|
||||
const editedDays = await app.models.ZoneCalendar.find({
|
||||
where: {
|
||||
zoneFk: zoneId
|
||||
}
|
||||
});
|
||||
const firstEditedDay = editedDays[0];
|
||||
const lastEditedDay = editedDays[editedDays.length - 1];
|
||||
|
||||
expect(editedDays.length).toEqual(5);
|
||||
expect(firstEditedDay.price).toEqual(7.00);
|
||||
expect(firstEditedDay.bonus).toEqual(0.00);
|
||||
expect(lastEditedDay.price).toEqual(7.00);
|
||||
expect(lastEditedDay.bonus).toEqual(0.00);
|
||||
});
|
||||
});
|
||||
|
|
@ -14,6 +14,12 @@
|
|||
"delivered": {
|
||||
"id": true,
|
||||
"type": "Date"
|
||||
},
|
||||
"price": {
|
||||
"type": "Number"
|
||||
},
|
||||
"bonus": {
|
||||
"type": "Number"
|
||||
}
|
||||
},
|
||||
"relations": {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
module.exports = Self => {
|
||||
require('../methods/zone/clone')(Self);
|
||||
require('../methods/zone/editPrices')(Self);
|
||||
|
||||
Self.validatesPresenceOf('warehouseFk', {
|
||||
message: `Warehouse cannot be blank`
|
||||
|
|
|
@ -1,21 +1,74 @@
|
|||
<vn-crud-model
|
||||
vn-id="model"
|
||||
url="/agency/api/ZoneCalendars"
|
||||
fields="['zoneFk', 'delivered']"
|
||||
link="{zoneFk: $ctrl.$stateParams.id}"
|
||||
data="$ctrl.data"
|
||||
primary-key="zoneFk"
|
||||
auto-load="true">
|
||||
</vn-crud-model>
|
||||
<vn-calendar pad-small vn-id="stMonth" skip="2"
|
||||
data="$ctrl.events"
|
||||
on-selection="$ctrl.onSelection(stMonth, values)"
|
||||
on-move-next="$ctrl.onMoveNext(ndMonth)"
|
||||
on-move-previous="$ctrl.onMovePrevious(ndMonth)">
|
||||
</vn-calendar>
|
||||
<vn-calendar pad-small vn-id="ndMonth" skip="2"
|
||||
<vn-watcher
|
||||
vn-id="watcher"
|
||||
data="$ctrl.selectedDay">
|
||||
</vn-watcher>
|
||||
|
||||
<vn-card pad-large>
|
||||
<vn-horizontal pad-medium style="justify-content: space-between;">
|
||||
<vn-icon-button icon="keyboard_arrow_left"
|
||||
ng-click="$ctrl.onMovePrevious([stMonth, ndMonth])"
|
||||
vn-tooltip="Previous">
|
||||
</vn-icon-button>
|
||||
<vn-icon-button icon="keyboard_arrow_right"
|
||||
ng-click="$ctrl.onMoveNext([stMonth, ndMonth])"
|
||||
vn-tooltip="Next">
|
||||
</vn-icon-button>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-calendar vn-id="stMonth" vn-one pad-medium
|
||||
data="$ctrl.events"
|
||||
display-controls="false"
|
||||
on-selection="$ctrl.onSelection(ndMonth, values)"
|
||||
default-date="$ctrl.ndMonthDate">
|
||||
</vn-calendar>
|
||||
on-selection="$ctrl.onSelection(values)"
|
||||
skip="2">
|
||||
</vn-calendar>
|
||||
<vn-calendar vn-id="ndMonth" vn-one pad-medium
|
||||
data="$ctrl.events"
|
||||
display-controls="false"
|
||||
on-selection="$ctrl.onSelection(values)"
|
||||
default-date="$ctrl.ndMonthDate"
|
||||
skip="2">
|
||||
</vn-calendar>
|
||||
</vn-horizontal>
|
||||
</vn-card>
|
||||
|
||||
<!-- Edit price dialog -->
|
||||
<vn-dialog class="edit"
|
||||
vn-id="priceDialog"
|
||||
on-close="$ctrl.onClose()"
|
||||
on-response="$ctrl.onResponse(response)">
|
||||
<tpl-body>
|
||||
<h5 pad-small-v translate>Edit price</h5>
|
||||
<vn-horizontal>
|
||||
<vn-input-number vn-one
|
||||
label="Price"
|
||||
model="$ctrl.selectedDay.price"
|
||||
min="0" step="0.01"
|
||||
required="true">
|
||||
</vn-input-number>
|
||||
<vn-input-number vn-one
|
||||
label="Bonus"
|
||||
model="$ctrl.selectedDay.bonus"
|
||||
min="0" step="0.01"
|
||||
required="true">
|
||||
</vn-input-number>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-radio-group vn-one
|
||||
field="$ctrl.selectedDay.option"
|
||||
options="$ctrl.options">
|
||||
</vn-radio-group>
|
||||
</vn-horizontal>
|
||||
</tpl-body>
|
||||
<tpl-buttons>
|
||||
<input type="button" response="CANCEL" translate-attr="{value: 'Cancel'}"/>
|
||||
<button response="ACCEPT" translate>Save</button>
|
||||
</tpl-buttons>
|
||||
</vn-dialog>
|
|
@ -1,49 +1,26 @@
|
|||
import ngModule from '../module';
|
||||
import './style.scss';
|
||||
|
||||
class Controller {
|
||||
constructor($element, $scope, $stateParams, $http) {
|
||||
constructor($element, $scope, $http, $filter, $translate, $stateParams, vnApp) {
|
||||
this.$element = $element;
|
||||
this.$stateParams = $stateParams;
|
||||
this.$scope = $scope;
|
||||
this.$ = $scope;
|
||||
this.$http = $http;
|
||||
this.$filter = $filter;
|
||||
this.$translate = $translate;
|
||||
this.$stateParams = $stateParams;
|
||||
this.vnApp = vnApp;
|
||||
this.stMonthDate = new Date();
|
||||
this.ndMonthDate = new Date();
|
||||
this.ndMonthDate.setMonth(this.ndMonthDate.getMonth() + 1);
|
||||
this.selectedDay = {};
|
||||
}
|
||||
|
||||
$postLink() {
|
||||
this.stMonth = this.$scope.stMonth;
|
||||
this.ndMonth = this.$scope.ndMonth;
|
||||
this.stMonth = this.$.stMonth;
|
||||
this.ndMonth = this.$.ndMonth;
|
||||
}
|
||||
|
||||
// Disabled until implementation
|
||||
// of holidays by node
|
||||
/* get zone() {
|
||||
return this._zone;
|
||||
}
|
||||
|
||||
set zone(value) {
|
||||
this._zone = value;
|
||||
|
||||
if (!value) return;
|
||||
|
||||
let query = '/agency/api/LabourHolidays/getByWarehouse';
|
||||
this.$http.get(query, {params: {warehouseFk: value.warehouseFk}}).then(res => {
|
||||
if (!res.data) return;
|
||||
const events = [];
|
||||
res.data.forEach(holiday => {
|
||||
events.push({
|
||||
date: holiday.dated,
|
||||
className: 'red',
|
||||
title: holiday.description || holiday.name,
|
||||
isRemovable: false
|
||||
});
|
||||
});
|
||||
|
||||
this.events = this.events.concat(events);
|
||||
});
|
||||
} */
|
||||
|
||||
get data() {
|
||||
return this._data;
|
||||
}
|
||||
|
@ -52,97 +29,106 @@ class Controller {
|
|||
this._data = value;
|
||||
|
||||
if (!value) return;
|
||||
|
||||
const events = [];
|
||||
value.forEach(event => {
|
||||
events.push({
|
||||
name: `P: ${this.$filter('currency')(event.price)}`,
|
||||
description: 'Price',
|
||||
dated: event.delivered,
|
||||
className: 'green-circle',
|
||||
title: 'Has delivery'
|
||||
style: {backgroundColor: '#a3d131'},
|
||||
data: {price: event.price}
|
||||
});
|
||||
events.push({
|
||||
name: `B: ${this.$filter('currency')(event.bonus)}`,
|
||||
description: 'Bonus',
|
||||
dated: event.delivered,
|
||||
data: {bonus: event.bonus}
|
||||
});
|
||||
});
|
||||
|
||||
this.events = events;
|
||||
}
|
||||
|
||||
onSelection(calendar, values) {
|
||||
let totalEvents = 0;
|
||||
values.forEach(day => {
|
||||
const exists = calendar.events.findIndex(event => {
|
||||
return event.dated >= day.dated && event.dated <= day.dated
|
||||
&& event.isRemovable;
|
||||
});
|
||||
onSelection(values) {
|
||||
if (values.length > 1) return false;
|
||||
|
||||
if (exists > -1) totalEvents++;
|
||||
});
|
||||
this.options = [
|
||||
{label: 'Only this day', value: 'Only this day'},
|
||||
{label: 'From this day', value: 'From this day'},
|
||||
{label: 'All days', value: 'All days'}
|
||||
];
|
||||
const selection = values[0];
|
||||
const events = selection.events;
|
||||
const hasEvents = events.length > 0;
|
||||
|
||||
if (totalEvents > (values.length / 2))
|
||||
this.removeEvents(calendar, values);
|
||||
else
|
||||
this.insertEvents(calendar, values);
|
||||
if (!hasEvents)
|
||||
return this.vnApp.showMessage(this.$translate.instant(`There's no delivery for this day`));
|
||||
|
||||
this.selectedDay = {
|
||||
delivered: selection.dated,
|
||||
option: 'Only this day'
|
||||
};
|
||||
|
||||
events.forEach(event => {
|
||||
this.selectedDay = Object.assign(this.selectedDay, event.data);
|
||||
});
|
||||
this.$.priceDialog.show();
|
||||
}
|
||||
|
||||
insertEvents(calendar, days) {
|
||||
days.forEach(day => {
|
||||
const event = calendar.events.find(event => {
|
||||
return event.dated >= day.dated && event.dated <= day.dated;
|
||||
});
|
||||
onResponse(response) {
|
||||
if (response == 'ACCEPT') {
|
||||
try {
|
||||
const data = {
|
||||
delivered: this.selectedDay.delivered,
|
||||
price: this.selectedDay.price,
|
||||
bonus: this.selectedDay.bonus,
|
||||
option: this.selectedDay.option
|
||||
};
|
||||
|
||||
if (event) return false;
|
||||
this.$.watcher.check();
|
||||
|
||||
this.$scope.model.insert({
|
||||
zoneFk: this.zone.id,
|
||||
delivered: day.dated
|
||||
const path = `/api/Zones/${this.zone.id}/editPrices`;
|
||||
this.$http.post(path, data).then(() => {
|
||||
this.vnApp.showSuccess(this.$translate.instant('Data saved!'));
|
||||
this.$.model.refresh();
|
||||
this.card.reload();
|
||||
});
|
||||
|
||||
calendar.addEvent({
|
||||
dated: day.dated,
|
||||
className: 'green-circle',
|
||||
title: 'Has delivery'
|
||||
});
|
||||
});
|
||||
|
||||
this.$scope.model.save().then(() => {
|
||||
this.events = calendar.events;
|
||||
});
|
||||
}
|
||||
|
||||
removeEvents(calendar, days) {
|
||||
let dates = [];
|
||||
days.forEach(day => {
|
||||
const event = calendar.events.find(event => {
|
||||
return event.dated >= day.dated && event.dated <= day.dated;
|
||||
});
|
||||
|
||||
if (event && !event.isRemovable)
|
||||
} catch (e) {
|
||||
this.vnApp.showError(this.$translate.instant(e.message));
|
||||
return false;
|
||||
|
||||
dates.push(day.dated);
|
||||
|
||||
calendar.removeEvent(day.dated);
|
||||
});
|
||||
|
||||
if (dates.length == 0) return;
|
||||
const params = {zoneFk: this.zone.id, dates};
|
||||
this.$http.post('/agency/api/zoneCalendars/removeByDate', params).then(() => {
|
||||
this.events = calendar.events;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
onMoveNext(calendar) {
|
||||
return this.onClose();
|
||||
}
|
||||
|
||||
onClose() {
|
||||
this.$.watcher.updateOriginalData();
|
||||
}
|
||||
|
||||
onMoveNext(calendars) {
|
||||
calendars.forEach(calendar => {
|
||||
calendar.moveNext(2);
|
||||
});
|
||||
}
|
||||
|
||||
onMovePrevious(calendar) {
|
||||
onMovePrevious(calendars) {
|
||||
calendars.forEach(calendar => {
|
||||
calendar.movePrevious(2);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Controller.$inject = ['$element', '$scope', '$stateParams', '$http'];
|
||||
Controller.$inject = ['$element', '$scope', '$http', '$filter', '$translate', '$stateParams', 'vnApp'];
|
||||
|
||||
ngModule.component('vnZoneCalendar', {
|
||||
template: require('./index.html'),
|
||||
controller: Controller,
|
||||
bindings: {
|
||||
zone: '<'
|
||||
},
|
||||
require: {
|
||||
card: '^vnZoneCard'
|
||||
}
|
||||
});
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
Prices: Precios
|
||||
Edit price: Modificar precio
|
||||
Only this day: Solo este día
|
||||
From this day: A partir de este día
|
||||
All days: Todos los días
|
||||
There's no delivery for this day: No hay reparto para este día
|
|
@ -0,0 +1,3 @@
|
|||
vn-calendar:nth-child(2n + 1) {
|
||||
border-right:1px solid #ddd
|
||||
}
|
|
@ -8,4 +8,5 @@ import './search-panel';
|
|||
import './create';
|
||||
import './basic-data';
|
||||
import './location';
|
||||
import './location/calendar';
|
||||
import './calendar';
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
<vn-crud-model
|
||||
vn-id="model"
|
||||
url="/agency/api/ZoneCalendars"
|
||||
fields="['zoneFk', 'delivered']"
|
||||
link="{zoneFk: $ctrl.$stateParams.id}"
|
||||
data="$ctrl.data"
|
||||
primary-key="zoneFk"
|
||||
auto-load="true">
|
||||
</vn-crud-model>
|
||||
<vn-calendar pad-small vn-id="stMonth" skip="2"
|
||||
data="$ctrl.events"
|
||||
on-selection="$ctrl.onSelection(values, stMonth)"
|
||||
on-move-next="$ctrl.onMoveNext(ndMonth)"
|
||||
on-move-previous="$ctrl.onMovePrevious(ndMonth)">
|
||||
</vn-calendar>
|
||||
<vn-calendar pad-small vn-id="ndMonth" skip="2"
|
||||
data="$ctrl.events"
|
||||
display-controls="false"
|
||||
on-selection="$ctrl.onSelection(values, ndMonth)"
|
||||
default-date="$ctrl.ndMonthDate">
|
||||
</vn-calendar>
|
|
@ -0,0 +1,150 @@
|
|||
import ngModule from '../module';
|
||||
|
||||
class Controller {
|
||||
constructor($element, $scope, $stateParams, $http) {
|
||||
this.$element = $element;
|
||||
this.$stateParams = $stateParams;
|
||||
this.$scope = $scope;
|
||||
this.$http = $http;
|
||||
this.stMonthDate = new Date();
|
||||
this.ndMonthDate = new Date();
|
||||
this.ndMonthDate.setMonth(this.ndMonthDate.getMonth() + 1);
|
||||
}
|
||||
|
||||
$postLink() {
|
||||
this.stMonth = this.$scope.stMonth;
|
||||
this.ndMonth = this.$scope.ndMonth;
|
||||
}
|
||||
|
||||
// Disabled until implementation
|
||||
// of holidays by node
|
||||
/* get zone() {
|
||||
return this._zone;
|
||||
}
|
||||
|
||||
set zone(value) {
|
||||
this._zone = value;
|
||||
|
||||
if (!value) return;
|
||||
|
||||
let query = '/agency/api/LabourHolidays/getByWarehouse';
|
||||
this.$http.get(query, {params: {warehouseFk: value.warehouseFk}}).then(res => {
|
||||
if (!res.data) return;
|
||||
const events = [];
|
||||
res.data.forEach(holiday => {
|
||||
events.push({
|
||||
date: holiday.dated,
|
||||
className: 'red',
|
||||
title: holiday.description || holiday.name,
|
||||
isRemovable: false
|
||||
});
|
||||
});
|
||||
|
||||
this.events = this.events.concat(events);
|
||||
});
|
||||
} */
|
||||
|
||||
get data() {
|
||||
return this._data;
|
||||
}
|
||||
|
||||
set data(value) {
|
||||
this._data = value;
|
||||
|
||||
if (!value) return;
|
||||
const events = [];
|
||||
value.forEach(event => {
|
||||
events.push({
|
||||
name: 'Has delivery',
|
||||
dated: event.delivered,
|
||||
style: {backgroundColor: '#a3d131'}
|
||||
});
|
||||
});
|
||||
|
||||
this.events = events;
|
||||
}
|
||||
|
||||
onSelection(values, calendar) {
|
||||
let totalEvents = 0;
|
||||
values.forEach(day => {
|
||||
const exists = calendar.events.findIndex(event => {
|
||||
return event.dated >= day.dated && event.dated <= day.dated
|
||||
&& event.isRemovable;
|
||||
});
|
||||
|
||||
if (exists > -1) totalEvents++;
|
||||
});
|
||||
|
||||
if (totalEvents > (values.length / 2))
|
||||
this.removeEvents(calendar, values);
|
||||
else
|
||||
this.insertEvents(calendar, values);
|
||||
}
|
||||
|
||||
insertEvents(calendar, days) {
|
||||
days.forEach(day => {
|
||||
const event = calendar.events.find(event => {
|
||||
return event.dated >= day.dated && event.dated <= day.dated;
|
||||
});
|
||||
|
||||
if (event) return false;
|
||||
|
||||
this.$scope.model.insert({
|
||||
zoneFk: this.zone.id,
|
||||
delivered: day.dated,
|
||||
price: this.zone.price,
|
||||
bonus: this.zone.bonus
|
||||
});
|
||||
|
||||
calendar.addEvent({
|
||||
name: 'Has delivery',
|
||||
dated: day.dated,
|
||||
style: {backgroundColor: '#a3d131'}
|
||||
});
|
||||
});
|
||||
|
||||
this.$scope.model.save().then(() => {
|
||||
this.events = calendar.events;
|
||||
});
|
||||
}
|
||||
|
||||
removeEvents(calendar, days) {
|
||||
let dates = [];
|
||||
days.forEach(day => {
|
||||
const event = calendar.events.find(event => {
|
||||
return event.dated >= day.dated && event.dated <= day.dated;
|
||||
});
|
||||
|
||||
if (event && !event.isRemovable)
|
||||
return false;
|
||||
|
||||
dates.push(day.dated);
|
||||
|
||||
calendar.removeEvent(day.dated);
|
||||
});
|
||||
|
||||
if (dates.length == 0) return;
|
||||
const params = {zoneFk: this.zone.id, dates};
|
||||
this.$http.post('/agency/api/zoneCalendars/removeByDate', params).then(() => {
|
||||
this.events = calendar.events;
|
||||
});
|
||||
}
|
||||
|
||||
onMoveNext(calendar) {
|
||||
calendar.moveNext(2);
|
||||
}
|
||||
|
||||
onMovePrevious(calendar) {
|
||||
calendar.movePrevious(2);
|
||||
}
|
||||
}
|
||||
|
||||
Controller.$inject = ['$element', '$scope', '$stateParams', '$http'];
|
||||
|
||||
ngModule.component('vnZoneLocationCalendar', {
|
||||
template: require('./calendar.html'),
|
||||
controller: Controller,
|
||||
bindings: {
|
||||
zone: '<'
|
||||
}
|
||||
});
|
|
@ -18,6 +18,6 @@
|
|||
</vn-treeview>
|
||||
</vn-card>
|
||||
<vn-side-menu side="right">
|
||||
<vn-zone-calendar zone="::$ctrl.zone"></vn-zone-calendar>
|
||||
<vn-zone-location-calendar zone="::$ctrl.zone"></vn-zone-location-calendar>
|
||||
</vn-side-menu>
|
||||
</div>
|
|
@ -6,7 +6,8 @@
|
|||
"dependencies": ["worker"],
|
||||
"menu": [
|
||||
{"state": "zone.card.basicData", "icon": "settings"},
|
||||
{"state": "zone.card.location", "icon": "my_location"}
|
||||
{"state": "zone.card.location", "icon": "my_location"},
|
||||
{"state": "zone.card.calendar"}
|
||||
],
|
||||
"routes": [
|
||||
{
|
||||
|
@ -15,27 +16,31 @@
|
|||
"abstract": true,
|
||||
"component": "ui-view",
|
||||
"description": "Zones"
|
||||
}, {
|
||||
},
|
||||
{
|
||||
"url": "/index?q",
|
||||
"state": "zone.index",
|
||||
"component": "vn-zone-index",
|
||||
"description": "Zones"
|
||||
}, {
|
||||
},
|
||||
{
|
||||
"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": "/location?q",
|
||||
"state": "zone.card.location",
|
||||
"component": "vn-zone-location",
|
||||
"description": "Locations",
|
||||
},
|
||||
{
|
||||
"url": "/summary",
|
||||
"state": "zone.card.summary",
|
||||
"component": "vn-zone-summary",
|
||||
"description": "Summary",
|
||||
"params": {
|
||||
"zone": "$ctrl.zone"
|
||||
}
|
||||
|
@ -50,10 +55,19 @@
|
|||
}
|
||||
},
|
||||
{
|
||||
"url": "/summary",
|
||||
"state": "zone.card.summary",
|
||||
"component": "vn-zone-summary",
|
||||
"description": "Summary",
|
||||
"url": "/location?q",
|
||||
"state": "zone.card.location",
|
||||
"component": "vn-zone-location",
|
||||
"description": "Locations",
|
||||
"params": {
|
||||
"zone": "$ctrl.zone"
|
||||
}
|
||||
},
|
||||
{
|
||||
"url": "/calendar",
|
||||
"state": "zone.card.calendar",
|
||||
"component": "vn-zone-calendar",
|
||||
"description": "Prices",
|
||||
"params": {
|
||||
"zone": "$ctrl.zone"
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
data="$ctrl.absenceTypes" auto-load="true">
|
||||
</vn-crud-model>
|
||||
<div class="main-with-right-menu">
|
||||
<vn-card compact pad-large>
|
||||
<vn-card pad-large>
|
||||
<vn-horizontal class="calendar-list">
|
||||
<section class="calendar" ng-repeat="month in $ctrl.months">
|
||||
<vn-calendar
|
||||
|
|
|
@ -45,10 +45,11 @@ class Controller {
|
|||
const holidayName = holidayDetail || holidayType;
|
||||
|
||||
events.push({
|
||||
name: holidayName,
|
||||
description: holidayName,
|
||||
dated: holiday.dated,
|
||||
className: 'red',
|
||||
title: holidayName,
|
||||
isRemovable: false
|
||||
isRemovable: false,
|
||||
style: {backgroundColor: '#FFFF00'}
|
||||
});
|
||||
});
|
||||
this.events = this.events.concat(events);
|
||||
|
@ -62,11 +63,10 @@ class Controller {
|
|||
absences.forEach(absence => {
|
||||
const absenceType = absence.absenceType;
|
||||
events.push({
|
||||
name: absenceType.name,
|
||||
description: absenceType.name,
|
||||
dated: absence.dated,
|
||||
title: absenceType.name,
|
||||
style: {
|
||||
background: absenceType.rgb
|
||||
}
|
||||
style: {backgroundColor: absenceType.rgb}
|
||||
});
|
||||
});
|
||||
this.events = this.events.concat(events);
|
||||
|
|
|
@ -93,7 +93,7 @@ describe('Worker', () => {
|
|||
controller.setHolidays(data);
|
||||
|
||||
expect(controller.events.length).toEqual(2);
|
||||
expect(controller.events[0].title).toEqual('New year');
|
||||
expect(controller.events[0].name).toEqual('New year');
|
||||
expect(controller.events[0].isRemovable).toEqual(false);
|
||||
});
|
||||
});
|
||||
|
@ -107,9 +107,9 @@ describe('Worker', () => {
|
|||
controller.setWorkerCalendar(data);
|
||||
|
||||
expect(controller.events.length).toEqual(2);
|
||||
expect(controller.events[0].title).toEqual('Holiday');
|
||||
expect(controller.events[0].name).toEqual('Holiday');
|
||||
expect(controller.events[0].style).toBeDefined();
|
||||
expect(controller.events[1].title).toEqual('Leave');
|
||||
expect(controller.events[1].name).toEqual('Leave');
|
||||
expect(controller.events[1].style).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,5 +1,13 @@
|
|||
@import "variables";
|
||||
|
||||
.calendar-list .calendar {
|
||||
border-bottom:1px solid #ddd
|
||||
}
|
||||
|
||||
.calendar-list .calendar:nth-child(2n + 1) {
|
||||
border-right:1px solid #ddd
|
||||
}
|
||||
|
||||
.calendar-list {
|
||||
align-items: flex-start;
|
||||
flex-wrap: wrap;
|
||||
|
@ -9,7 +17,7 @@
|
|||
box-sizing: border-box;
|
||||
padding: $pad-medium;
|
||||
overflow: hidden;
|
||||
width: 20em
|
||||
width: 50%
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue