chore: upgrade calendar component to latest

feature parity for,
- toolbar actions
- show/hide weekend
- navigate through calendar and click events
This commit is contained in:
Rutwik Hiwalkar 2024-05-07 19:46:18 +05:30
parent c7c3eee6d5
commit 3d29f90dbd

View file

@ -1,6 +1,12 @@
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
// MIT License. See license.txt
import { Calendar as FullCalendar } from "@fullcalendar/core";
import dayGridPlugin from "@fullcalendar/daygrid";
import listPlugin from "@fullcalendar/list";
import timeGridPlugin from "@fullcalendar/timegrid";
import interactionPlugin from "@fullcalendar/interaction";
frappe.provide("frappe.views.calendar");
frappe.provide("frappe.views.calendars");
@ -99,18 +105,6 @@ frappe.views.CalendarView = class CalendarView extends frappe.views.ListView {
}
});
}
get required_libs() {
let assets = [
"assets/frappe/js/lib/fullcalendar/fullcalendar.min.css",
"assets/frappe/js/lib/fullcalendar/fullcalendar.min.js",
];
let user_language = frappe.boot.lang;
if (user_language && user_language !== "en") {
assets.push("assets/frappe/js/lib/fullcalendar/locale-all.js");
}
return assets;
}
};
frappe.views.Calendar = class Calendar {
@ -133,10 +127,10 @@ frappe.views.Calendar = class Calendar {
}
get_default_options() {
return new Promise((resolve) => {
let defaultView = localStorage.getItem("cal_defaultView");
let initialView = localStorage.getItem("cal_initialView");
let weekends = localStorage.getItem("cal_weekends");
let defaults = {
defaultView: defaultView ? defaultView : "month",
initialView: initialView ? initialView : "dayGridMonth",
weekends: weekends ? weekends : true,
};
resolve(defaults);
@ -162,13 +156,13 @@ frappe.views.Calendar = class Calendar {
});
$(this.parent).on("show", function () {
me.$cal.fullCalendar("refetchEvents");
me.$cal.fullCalendar.refetchEvents();
});
}
make() {
this.$wrapper = this.parent;
this.$cal = $("<div>").appendTo(this.$wrapper);
this.$cal = $("<div id='fc-calendar-wrapper'>").appendTo(this.$wrapper);
this.footnote_area = frappe.utils.set_footnote(
this.footnote_area,
this.$wrapper,
@ -176,7 +170,9 @@ frappe.views.Calendar = class Calendar {
);
this.footnote_area.css({ "border-top": "0px" });
this.$cal.fullCalendar(this.cal_options);
this.fullCalendar = new FullCalendar(this.$cal[0], this.cal_options);
this.fullCalendar.render();
this.set_css();
}
setup_view_mode_button(defaults) {
@ -194,37 +190,42 @@ frappe.views.Calendar = class Calendar {
const me = this;
let btn_group = me.$wrapper.find(".fc-button-group");
btn_group.on("click", ".btn", function () {
let value = $(this).hasClass("fc-agendaWeek-button")
? "agendaWeek"
: $(this).hasClass("fc-agendaDay-button")
? "agendaDay"
: "month";
me.set_localStorage_option("cal_defaultView", value);
let value = $(this).hasClass("fc-dayGridWeek-button")
? "dayGridWeek"
: $(this).hasClass("fc-dayGridDay-button")
? "dayGridDay"
: "dayGridMonth";
me.set_localStorage_option("cal_initialView", value);
});
me.$wrapper.on("click", ".btn-weekend", function () {
me.cal_options.weekends = !me.cal_options.weekends;
me.$cal.fullCalendar("option", "weekends", me.cal_options.weekends);
//me.fullCalendar("option", "weekends", );
me.fullCalendar.setOption("weekends", me.cal_options.weekends);
me.set_localStorage_option("cal_weekends", me.cal_options.weekends);
me.set_css();
me.setup_view_mode_button(me.cal_options);
});
}
set_css() {
// flatify buttons
this.$wrapper
.find("button.fc-state-default")
.removeClass("fc-state-default")
.find("button.fc-button")
.removeClass("fc-button")
.removeClass("fc-button-primary")
.addClass("btn btn-default");
this.$wrapper
.find(".fc-month-button, .fc-agendaWeek-button, .fc-agendaDay-button")
.find(".fc-dayGridMonth-button, .fc-dayGridWeek-button, .fc-dayGridDay-button")
.wrapAll('<div class="btn-group" />');
// add icons
this.$wrapper
.find(".fc-prev-button span")
.attr("class", "")
.html(frappe.utils.icon("left"));
this.$wrapper.find(".fc-prev-button").css("margin-right", 5 + "px");
this.$wrapper
.find(".fc-next-button span")
.attr("class", "")
@ -235,7 +236,7 @@ frappe.views.Calendar = class Calendar {
this.$wrapper.find(".fc-day-number").wrap('<div class="fc-day"></div>');
var btn_group = this.$wrapper.find(".fc-button-group");
btn_group.find(".fc-state-active").addClass("active");
btn_group.find(".fc-button-active").addClass("active");
btn_group.find(".btn").on("click", function () {
btn_group.find(".btn").removeClass("active");
@ -244,93 +245,95 @@ frappe.views.Calendar = class Calendar {
}
get_system_datetime(date) {
date._offset = moment(date).tz(frappe.sys_defaults.time_zone)._offset;
return frappe.datetime.convert_to_system_tz(moment(date).locale("en"));
return frappe.datetime.convert_to_system_tz(new Date(date));
}
setup_options(defaults) {
var me = this;
defaults.meridiem = "false";
this.cal_options = {
plugins: [dayGridPlugin, listPlugin, timeGridPlugin, interactionPlugin],
initialView: defaults.initialView || "dayGridMonth",
locale: frappe.boot.lang,
header: {
left: "prev, title, next",
right: "today, month, agendaWeek, agendaDay",
headerToolbar: {
left: "prev,next",
center: "title",
right: "today,dayGridMonth,dayGridWeek,dayGridDay",
},
editable: true,
droppable: true,
selectable: true,
selectHelper: true,
selectMirror: true,
forceEventDuration: true,
displayEventTime: true,
defaultView: defaults.defaultView,
displayEventTime: false,
weekends: defaults.weekends,
nowIndicator: true,
themeSystem: null,
buttonText: {
today: __("Today"),
month: __("Month"),
week: __("Week"),
day: __("Day"),
},
events: function (start, end, timezone, callback) {
events: function (info, successCallback, failureCallback) {
return frappe.call({
method: me.get_events_method || "frappe.desk.calendar.get_events",
type: "GET",
args: me.get_args(start, end),
args: me.get_args(info.startStr, info.endStr),
callback: function (r) {
var events = r.message || [];
events = me.prepare_events(events);
callback(events);
successCallback(events);
},
});
},
displayEventEnd: true,
eventRender: function (event, element) {
element.attr("title", event.tooltip);
},
eventClick: function (event) {
eventClick: function (info) {
// edit event description or delete
var doctype = event.doctype || me.doctype;
var doctype = info.doctype || me.doctype;
if (frappe.model.can_read(doctype)) {
frappe.set_route("Form", doctype, event.name);
frappe.set_route("Form", doctype, info.event.id);
}
},
eventDrop: function (event, delta, revertFunc) {
me.update_event(event, revertFunc);
eventDrop: function (info) {
me.update_event(info.event, info.revert);
},
eventResize: function (event, delta, revertFunc) {
me.update_event(event, revertFunc);
eventResize: function (info) {
me.update_event(info.event, info.revert);
},
select: function (startDate, endDate, jsEvent, view) {
if (view.name === "month" && endDate - startDate === 86400000) {
select: function (info) {
if (info.view.type === "dayGridMonth" && info.end - info.start === 86400000) {
// detect single day click in month view
return;
}
var event = frappe.model.get_new_doc(me.doctype);
event[me.field_map.start] = me.get_system_datetime(startDate);
event[me.field_map.start] = me.get_system_datetime(info.startStr);
if (me.field_map.end) event[me.field_map.end] = me.get_system_datetime(endDate);
if (me.field_map.end)
event[me.field_map.end] = me.get_system_datetime(info.endStr);
if (me.field_map.allDay) {
var all_day = startDate._ambigTime && endDate._ambigTime ? 1 : 0;
var all_day = info.start._ambigTime && info.end._ambigTime ? 1 : 0;
event[me.field_map.allDay] = all_day;
if (all_day)
event[me.field_map.end] = me.get_system_datetime(
moment(endDate).subtract(1, "s")
moment(info.endStr).subtract(1, "s")
);
}
frappe.set_route("Form", me.doctype, event.name);
},
dayClick: function (date, jsEvent, view) {
if (view.name === "month") {
const $date_cell = $("td[data-date=" + date.format("YYYY-MM-DD") + "]");
dateClick: function (info) {
if (info.view.type === "dayGridMonth") {
const $date_cell = $(
"td[data-date=" + info.date.toISOString().slice(0, 10) + "]"
);
if ($date_cell.hasClass("date-clicked")) {
me.$cal.fullCalendar("changeView", "agendaDay");
me.$cal.fullCalendar("gotoDate", date);
me.fullCalendar.changeView("timeGridDay", info.date);
me.$wrapper.find(".date-clicked").removeClass("date-clicked");
// update "active view" btn
@ -361,7 +364,7 @@ frappe.views.Calendar = class Calendar {
return args;
}
refresh() {
this.$cal.fullCalendar("refetchEvents");
this.fullCalendar.refetchEvents();
}
prepare_events(events) {
var me = this;