@oveasoft/planning
Version:
An AngularJS planning component
196 lines (176 loc) • 7.43 kB
JavaScript
import template from './ovaPlanningDay.template.html';
import moment from 'moment';
import { Slot } from '../classes/slot.class';
import { MomentHelper } from '../classes/moment.helper';
import angular from 'angular';
import _ from 'lodash';
import './ovaPlanningDay.scss';
/**
* @name OvaPlanningDayComponent
* @class OvaPlanningDayComponent
* @module day
* @description Represent a day of the planning.
*/
class OvaPlanningDayComponent {
/**
* @constructor
* @property {moment.Moment|String} date The moment object or a string of a date.
* @property {Array} data Data to be sorted in slots.
*/
constructor () {
this.slots = [];
/**
* Build a moment object.
* @private
*/
this._buildDate = () => {
if (moment(this.date).isValid()) {
this.date = moment(this.date);
} else {
throw new Error(`[ova-planning] Trying to build a day from an invalid date parameter ${this.date} (${typeof date}).`);
}
};
/**
* Build slots.
* @private
*/
this._buildSlots = () => {
_.each(this.ovaPlanning.config.slot, (slotRanges, index) => {
let start = slotRanges[0];
let end = slotRanges[1];
let currentSlot = MomentHelper.buildSlot(this.date, start);
let lastSlot = MomentHelper.buildSlot(this.date, end);
/**
* Build breaking slots if config.showPause = true
*/
if (this.ovaPlanning.config.showPause && index > 0) {
this._buildBreakSlot(currentSlot, index);
}
while (currentSlot.isBefore(lastSlot)) {
let actualSlot = moment(currentSlot);
let nextSlot = moment(currentSlot.add(this.ovaPlanning.config.slotInterval, 'minutes'));
let targetSlot = nextSlot.isAfter(lastSlot) ? lastSlot : nextSlot;
let slot = new Slot(actualSlot, targetSlot, [], 'slot');
this._dataToSlot(slot);
this.slots.push(slot);
}
});
/**
* Build waiting slots.
*/
this.waitingSlot = new Slot(moment(this.date).hour(0), moment(this.date).hour(1), [], 'slot waiting');
this._missPlacedAppointment();
this.slots.push(this.waitingSlot);
};
this._buildBreakSlot = (currentSlot, index) => {
let previousMaxHour = this.ovaPlanning.config.slot[index - 1][1];
let previousSlot = MomentHelper.buildSlot(this.date, previousMaxHour);
this.slots.push(new Slot(previousSlot, moment(currentSlot), [], 'break'));
};
/**
* Put data in the rights slots.
* We must iterate through each slot of this day and find the between.
* example: 8:14 must go in 8:00's slot because 8:14 > 8:00 AND 8:14 < 8:15.
* @param {Slot} slot
* @private
*/
this._dataToSlot = (slot) => {
if (this.data) {
_.each(this.data, appointment => {
_.set(appointment, this.ovaPlanning.config.datePath, moment(_.get(appointment, this.ovaPlanning.config.datePath)));
// _.get(appointment, this.ovaPlanning.config.datePath) = _.get(appointment, this.ovaPlanning.config.datePath) instanceof moment ? _.get(appointment, this.ovaPlanning.config.datePath) : moment(_.get(appointment, this.ovaPlanning.config.datePath));
if (_.get(appointment, this.ovaPlanning.config.datePath) instanceof moment) {
if (_.get(appointment, this.ovaPlanning.config.datePath).isSame(this.date, 'day')) {
this._placeAppointment(appointment, slot);
}
} else {
throw new Error(`[ova-planning] ${_.get(appointment, this.ovaPlanning.config.datePath)} is not an instance of moment.`);
}
});
}
};
/**
* Place the appointment without slot.
* @private
*/
this._missPlacedAppointment = () => {
let missplacedAppointment = _.filter(this.data, appointment => {
let isBetween = null;
_.each(this.ovaPlanning.config.slot, ranges => {
let start = ranges[0];
let end = ranges[1];
let startSlot = MomentHelper.buildSlot(this.date, start);
let endSlot = MomentHelper.buildSlot(this.date, end);
isBetween = _.get(appointment, this.ovaPlanning.config.datePath).isBetween(startSlot, endSlot, null, '[)');
if (isBetween) {
return false;
}
});
return !isBetween;
});
_.each(missplacedAppointment, appointment => {
if (_.get(appointment, this.ovaPlanning.config.datePath) instanceof moment && _.get(appointment, this.ovaPlanning.config.datePath).isSame(this.date, 'day')) {
this.ovaPlanning.pushToInformations(appointment, 'missplaced');
// appointment._isPlaced = false;
this.waitingSlot.data.push(appointment);
}
});
};
/**
* Place an appointment in a slot.
* @param appointment
* @param {Slot} slot
* @private
*/
this._placeAppointment = (appointment, slot) => {
if (slot.start instanceof moment && slot.state === 'slot') {
if (this._appointmentFitInSlot(slot, appointment)) {
this.ovaPlanning.pushToInformations(appointment, 'placed');
// appointment._isPlaced = true;
slot.data.push(appointment);
}
}
};
/**
* Check if the appointment date is between the slot start and end.
* @param {Object} slot
* @param {Object} appointment
* @private
*/
this._appointmentFitInSlot = (slot, appointment) => {
return _.get(appointment, this.ovaPlanning.config.datePath).isSameOrAfter(slot.start) && _.get(appointment, this.ovaPlanning.config.datePath).isBefore(slot.end);
};
}
/**
* Event
*/
$onInit () {
this.ovaPlanning.Debugger.output(`Day ${this.date.day()} $onInit`);
this.theme = `theme-${this.ovaPlanning.config.theme}`;
this.oldData = angular.copy(this.data);
this._buildDate();
this._buildSlots();
}
$doCheck () {
if (!angular.equals(this.data, this.oldData)) {
this.ovaPlanning.Debugger.output(`Data for day ${this.date.day()} has changed.`);
this.slots = [];
this._buildSlots();
this.oldData = angular.copy(this.data);
}
}
slotClicked (slot) {
this.ovaPlanning.config.selectSlot(slot);
}
}
export default {
controller: OvaPlanningDayComponent,
template,
require: {
ovaPlanning: '^ovaPlanning'
},
bindings: {
date: '<?',
data: '='
}
};