You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
203 lines
6.8 KiB
203 lines
6.8 KiB
/** @odoo-module **/
|
|
import { patch } from "@web/core/utils/patch";
|
|
import { Component, useState , useRef, useEffect } from "@odoo/owl";
|
|
import { animations } from "@website/js/content/snippets.animation";
|
|
const { DateTime } = luxon;
|
|
import publicWidget from "@web/legacy/js/public/public_widget";
|
|
import { renderToFragment } from "@web/core/utils/render";
|
|
import { useService } from "@web/core/utils/hooks";
|
|
import { jsonrpc } from "@web/core/network/rpc_service";
|
|
import { DateTimePicker } from "@web/core/datetime/datetime_picker";
|
|
|
|
|
|
const DATE_FORMAT = "yyyy-MM-dd";
|
|
const DATETIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
|
|
|
|
publicWidget.registry.CustomCalendar = publicWidget.Widget.extend({
|
|
selector: '.s_event_calendar_list',
|
|
|
|
setup() {
|
|
const rpc = useService("rpc");
|
|
},
|
|
|
|
init: function () {
|
|
const referenceMoment = DateTime.local().setLocale("en");
|
|
this.selected_date = null
|
|
|
|
this.datepickerOptions = {
|
|
inline: true,
|
|
minDate: referenceMoment.minus({ years: 100 }),
|
|
maxDate: referenceMoment.plus({ years: 100 }),
|
|
icons: {
|
|
previous: "fa fa-chevron-left",
|
|
next: "fa fa-chevron-right",
|
|
},
|
|
format: DATE_FORMAT,
|
|
useCurrent: false,
|
|
locale: referenceMoment.loc.locale,
|
|
};
|
|
|
|
return this._super.apply(this, arguments);
|
|
},
|
|
|
|
start: function (editableMode) {
|
|
this._super.apply(this, arguments);
|
|
|
|
if (editableMode) {
|
|
return;
|
|
}
|
|
this.selectedDates = {
|
|
min: null,
|
|
max: null,
|
|
matches: [],
|
|
};
|
|
|
|
this.defaultAmount = Number(this.$(".js_amount").html()) || 4;
|
|
// Get initial events to render the list
|
|
this.loadEvents(null, this.defaultAmount)
|
|
.then($.proxy(this, "renderList"));
|
|
// Preload dates and render the calendar
|
|
const referenceMoment = DateTime.local().setLocale("en");
|
|
this.preloadDates(referenceMoment)
|
|
.then($.proxy(this, "renderCalendar"));
|
|
},
|
|
|
|
preloadDates: function (when) {
|
|
const referenceMoment = DateTime.local().setLocale("en");
|
|
const margin = { months: 4 };
|
|
|
|
// Don't preload if we have up to 4 months of margin
|
|
if (
|
|
this.selectedDates.min && this.selectedDates.max &&
|
|
this.selectedDates.min <= when - margin &&
|
|
this.selectedDates.max >= when + margin
|
|
) {
|
|
return $.Deferred().resolve();
|
|
}
|
|
// Default values
|
|
margin.months += 2;
|
|
const start = referenceMoment.minus(margin);
|
|
const end = referenceMoment.plus(margin);
|
|
// If we already preloaded, preload 6 more months
|
|
if (this.selectedDates.min) {
|
|
start.subtract(6, "months");
|
|
}
|
|
if (this.selectedDates.max) {
|
|
end.add(6, "months");
|
|
}
|
|
// Do the preloading
|
|
return this.loadDates(start, end);
|
|
},
|
|
|
|
loadDates: function (start, end) {
|
|
const startdate = start.toISO();
|
|
|
|
return jsonrpc(
|
|
"/web_events_calendar_view/days_with_events",
|
|
{
|
|
start: start.toISO(),
|
|
end: end.toISO(),
|
|
}
|
|
).then($.proxy(this, "updateDatesCache", start, end));
|
|
},
|
|
|
|
updateDatesCache: function (start, end, dates) {
|
|
if (!this.selectedDates.min || this.selectedDates.min > start) {
|
|
this.selectedDates.min = start;
|
|
}
|
|
if (!this.selectedDates.max || this.selectedDates.max < end) {
|
|
this.selectedDates.max = end;
|
|
}
|
|
this.selectedDates.matches = [...new Set([...this.selectedDates.matches, ...dates])];
|
|
|
|
},
|
|
|
|
renderCalendar: function () {
|
|
const enabledDates = this.selectedDates.matches.map((ndate) => {
|
|
return new Date(ndate); // Convert string date to JavaScript Date object
|
|
});
|
|
this._load_fullcalendar();
|
|
},
|
|
|
|
_load_fullcalendar: function () {
|
|
// Dynamically load FullCalendar CSS
|
|
var link = document.createElement('link');
|
|
link.rel = 'stylesheet';
|
|
link.type = 'text/css';
|
|
link.href = 'https://cdn.jsdelivr.net/npm/fullcalendar@5.10.0/main.min.css';
|
|
document.head.appendChild(link);
|
|
|
|
// Dynamically load FullCalendar JS
|
|
var script = document.createElement('script');
|
|
script.type = 'text/javascript';
|
|
script.src = 'https://cdn.jsdelivr.net/npm/fullcalendar@5.10.0/main.min.js';
|
|
script.onload = this._initialize_calendar.bind(this); // Initialize the calendar once the script is loaded
|
|
document.body.appendChild(script);
|
|
},
|
|
|
|
async _initialize_calendar() {
|
|
var calendarElement = document.querySelector('.s_event_calendar')
|
|
if (!calendarElement) {
|
|
return;
|
|
}
|
|
|
|
var events = await jsonrpc(
|
|
"/web_events_calendar_view/events",
|
|
{}
|
|
);
|
|
|
|
// Initialize FullCalendar
|
|
new FullCalendar.Calendar(calendarElement, {
|
|
initialView: 'dayGridMonth',
|
|
events: events,
|
|
|
|
// This will trigger when a date is clicked
|
|
dateClick: (info) => {
|
|
this.handleDateClick(info); // 'this' now refers to the CalendarHandler instance
|
|
}
|
|
}).render();
|
|
},
|
|
|
|
// Handle date click event
|
|
handleDateClick(info) {
|
|
let clickedDate = info.dateStr; // Date in 'YYYY-MM-DD' format
|
|
this.selected_date = clickedDate;
|
|
|
|
let previousSelectedDate = document.querySelector('.fc-selected');
|
|
if (previousSelectedDate) {
|
|
previousSelectedDate.classList.remove('fc-selected');
|
|
previousSelectedDate.style.backgroundColor = ''; // Reset background color
|
|
}
|
|
|
|
// Add background color to the clicked date
|
|
let clickedDateElement = info.dayEl; // Get the actual DOM element of the clicked day
|
|
clickedDateElement.classList.add('fc-selected');
|
|
clickedDateElement.style.backgroundColor = '#1b918b';
|
|
|
|
// Get the default amount
|
|
this.defaultAmount = Number(document.querySelector(".js_amount").innerHTML) || 4;
|
|
|
|
// Call loadEvents and then render the list
|
|
this.loadEvents(this.selected_date, this.defaultAmount)
|
|
.then(this.renderList);
|
|
},
|
|
|
|
renderList: function (events) {
|
|
document.querySelector('.s_event_list').innerHTML = '';
|
|
|
|
document.querySelector('.s_event_list').append(renderToFragment(
|
|
'web_events_calendar_view.list',
|
|
{
|
|
events: events
|
|
}
|
|
));
|
|
},
|
|
|
|
loadEvents: function (day, limit) {
|
|
return jsonrpc(
|
|
"/web_events_calendar_view/events_for_day",
|
|
{day: day, limit: limit}
|
|
);
|
|
},
|
|
|
|
});
|
|
|