import ngModule from '../module'; import Section from 'salix/components/section'; import './style.scss'; class Controller extends Section { constructor($element, $) { super($element, $); this.date = new Date(); this.events = {}; this.buildYearFilter(); } get year() { return this.date.getFullYear(); } set year(value) { const newYear = new Date(); newYear.setFullYear(value); this.date = newYear; this.refresh() .then(() => this.repaint()) .then(() => this.getContractHolidays()) .then(() => this.getYearHolidays()); } get businessId() { return this._businessId; } set businessId(value) { this._businessId = value; if (value) { this.refresh() .then(() => this.repaint()) .then(() => this.getContractHolidays()) .then(() => this.getYearHolidays()); } } get date() { return this._date; } set date(value) { this._date = value; value.setHours(0, 0, 0, 0); this.months = new Array(12); for (let i = 0; i < this.months.length; i++) { const now = new Date(value.getTime()); now.setDate(1); now.setMonth(i); this.months[i] = now; } } get worker() { return this._worker; } set worker(value) { this._worker = value; if (value) { this.getIsSubordinate(); this.getActiveContract(); } } get payedHolidays() { return this._businessId; } buildYearFilter() { const now = new Date(); now.setFullYear(now.getFullYear() + 1); const maxYear = now.getFullYear(); const minRange = maxYear - 5; const years = []; for (let i = maxYear; i > minRange; i--) years.push({year: i}); this.yearFilter = years; } getIsSubordinate() { this.$http.get(`Workers/${this.worker.id}/isSubordinate`) .then(res => this.isSubordinate = res.data); } getActiveContract() { this.$http.get(`Workers/${this.worker.id}/activeContract`).then(res => { if (res.data) this.businessId = res.data.businessFk; }); } getContractHolidays() { this.getHolidays({ businessFk: this.businessId, year: this.year }, data => this.contractHolidays = data); } getYearHolidays() { this.getHolidays({ year: this.year }, data => this.yearHolidays = data); } getHolidays(params, cb) { this.$http.get(`Workers/${this.worker.id}/holidays`, {params}) .then(res => cb(res.data)); } onData(data) { this.events = {}; this.calendar = data.calendar; let addEvent = (day, newEvent) => { const timestamp = new Date(day).getTime(); const event = this.events[timestamp]; if (event) { const oldName = event.name; Object.assign(event, newEvent); event.name = `${oldName}, ${event.name}`; } else this.events[timestamp] = newEvent; }; if (data.holidays) { data.holidays.forEach(holiday => { const holidayDetail = holiday.detail && holiday.detail.name; const holidayType = holiday.type && holiday.type.name; const holidayName = holidayDetail || holidayType; addEvent(holiday.dated, { name: holidayName, className: 'festive' }); }); } if (data.absences) { data.absences.forEach(absence => { let type = absence.absenceType; addEvent(absence.dated, { name: type.name, color: type.rgb, type: type.code, absenceId: absence.id }); }); } } repaint() { let calendars = this.element.querySelectorAll('vn-calendar'); for (let calendar of calendars) calendar.$ctrl.repaint(); } formatDay(day, element) { let event = this.events[day.getTime()]; if (!event) return; let dayNumber = element.firstElementChild; dayNumber.title = event.name; dayNumber.style.backgroundColor = event.color; if (event.border) dayNumber.style.border = event.border; if (event.className) dayNumber.classList.add(event.className); } pick(absenceType) { if (!this.isSubordinate) return; if (absenceType == this.absenceType) absenceType = null; this.absenceType = absenceType; } onSelection($event, $days) { if (!this.absenceType) return this.vnApp.showMessage(this.$t('Choose an absence type from the right menu')); const day = $days[0]; const stamp = day.getTime(); const event = this.events[stamp]; const calendar = $event.target.closest('vn-calendar').$ctrl; if (event && event.absenceId) { if (event.type == this.absenceType.code) this.delete(calendar, day, event); else this.edit(calendar, event); } else this.create(calendar, day); } create(calendar, dated) { const absenceType = this.absenceType; const params = { dated: dated, absenceTypeId: absenceType.id, businessFk: this.businessId }; const path = `Workers/${this.$params.id}/createAbsence`; this.$http.post(path, params).then(res => { const newEvent = res.data; this.events[dated.getTime()] = { name: absenceType.name, color: absenceType.rgb, type: absenceType.code, absenceId: newEvent.id }; this.repaintCanceller(() => this.refresh() .then(calendar.repaint()) .then(() => this.repaint()) .then(() => this.getContractHolidays()) .then(() => this.getYearHolidays()) ); }); } edit(calendar, event) { const absenceType = this.absenceType; const params = { absenceId: event.absenceId, absenceTypeId: absenceType.id }; const path = `Workers/${this.$params.id}/updateAbsence`; this.$http.patch(path, params).then(() => { event.color = absenceType.rgb; event.name = absenceType.name; event.type = absenceType.code; this.repaintCanceller(() => this.refresh() .then(calendar.repaint()) .then(() => this.getContractHolidays()) .then(() => this.getYearHolidays()) ); }); } delete(calendar, day, event) { const params = {absenceId: event.absenceId}; const path = `Workers/${this.$params.id}/deleteAbsence`; this.$http.delete(path, {params}).then(() => { delete this.events[day.getTime()]; this.repaintCanceller(() => this.refresh() .then(calendar.repaint()) .then(() => this.repaint()) .then(() => this.getContractHolidays()) .then(() => this.getYearHolidays()) ); }); } repaintCanceller(cb) { if (this.canceller) { clearTimeout(this.canceller); this.canceller = null; } this.canceller = setTimeout( () => cb(), 500); } refresh() { const params = { workerFk: this.$params.id, businessFk: this.businessId, year: this.year }; return this.$http.get(`Calendars/absences`, {params}) .then(res => this.onData(res.data)); } } ngModule.vnComponent('vnWorkerCalendar', { template: require('./index.html'), controller: Controller, bindings: { worker: '<' } });