From a2f4c13b616f64bccac69fc085cfc6b660524900 Mon Sep 17 00:00:00 2001 From: bohung Date: Wed, 13 Jul 2022 12:05:33 +0800 Subject: [PATCH] Add calendar setting. Change translations. Fix known bug. --- app/assets/javascripts/calendar.js | 268 ++++++++---- app/assets/javascripts/calendar_frontend.js | 391 +++++++++++------- app/assets/javascripts/calendar_moment.min.js | 2 + .../javascripts/fullcalendar_moment.min.js | 6 + app/controllers/admin/calendars_controller.rb | 9 + app/controllers/calendars_controller.rb | 10 +- app/models/calendar_setting.rb | 81 ++++ .../admin/calendars/calendar_setting.html.erb | 79 ++++ app/views/admin/calendars/index.html.erb | 19 +- .../calendars/_calendar_variable.html.erb | 16 + app/views/calendars/index.html.erb | 3 +- calendar.gemspec | 25 +- config/locales/en.yml | 22 + config/locales/zh_tw.yml | 22 + config/routes.rb | 10 +- lib/calendar/engine.rb | 5 + modules/calendar/index.html.erb | 9 +- 17 files changed, 704 insertions(+), 273 deletions(-) create mode 100644 app/assets/javascripts/calendar_moment.min.js create mode 100644 app/assets/javascripts/fullcalendar_moment.min.js create mode 100644 app/models/calendar_setting.rb create mode 100644 app/views/admin/calendars/calendar_setting.html.erb create mode 100644 app/views/calendars/_calendar_variable.html.erb diff --git a/app/assets/javascripts/calendar.js b/app/assets/javascripts/calendar.js index 9ffdd24..abb4b36 100644 --- a/app/assets/javascripts/calendar.js +++ b/app/assets/javascripts/calendar.js @@ -1,4 +1,53 @@ window.auto_close_popup = false; +if(window.calendar_variable == undefined){ + window.calendar_variable = {}; + window.calendar_variable.is_chinese = ( I18n && I18n.locale.indexOf('zh') != -1 ); + window.calendar_variable.date_type = 0; +}else{ + if(window.calendar_variable.date_type == 1){ + window.calendar_variable.is_chinese = false; + }else{ + window.calendar_variable.is_chinese = ( I18n && I18n.locale.indexOf('zh') != -1 ); + } +} +if(!(window.calendar_variable.dayNames)){ + if(window.calendar_variable.is_chinese){ + window.calendar_variable.dayNames = ['週日', '週一', '週二', '週三','週四', '週五', '週六']; + window.calendar_variable.dayNamesShort = ['日', '一', '二', '三','四', '五', '六']; + }else{ + window.calendar_variable.dayNames = ['Sunday', 'Monday', 'Tuesday', 'Wednesday','Thursday', 'Friday', 'Saturday']; + window.calendar_variable.dayNamesShort = ['Sun', 'Mon', 'Tue', 'Wed','Thu', 'Fri', 'Sat']; + } +} +if(window.calendar_variable.is_chinese){ + window.calendar_variable.months = []; + for(var i=0;i<12;i++){ + window.calendar_variable.months.push((i+1)+"月"); + } +}else{ + window.calendar_variable.months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']; +} +if(window.calendar_variable.date_type == 2){ + window.calendar_variable.datetime_format = calendar_variable.is_chinese ? 'yy/MM/dd b h:m' : 'dd/MM/yy h:m b'; + window.calendar_variable.month_year_format = calendar_variable.is_chinese ? 'yy/MM' : 'MM/yy'; + window.calendar_variable.date_format = calendar_variable.is_chinese ? 'yy/MM/dd' : 'dd/MM/yy'; + window.calendar_variable.date_format_with_short_month = calendar_variable.is_chinese ? 'yy/MM/dd' : 'dd/MM/yy'; + window.calendar_variable.date_format_with_week = calendar_variable.is_chinese ? 'yy/MM/dd (W)' : 'W, MM/dd/yy'; + window.calendar_variable.short_date = (calendar_variable.is_chinese ? "MM/dd (W)" : "W, dd/MM"); + window.calendar_variable.short_date_time = (calendar_variable.is_chinese ? "MM/dd (W) b h:m" : "W, dd/MM h:m b"); +}else{ + window.calendar_variable.datetime_format = calendar_variable.is_chinese ? 'y MMM d b h:m' : 'd MMM, y h:m b'; + window.calendar_variable.month_year_format = calendar_variable.is_chinese ? 'y MMM' : 'MMM y'; + window.calendar_variable.date_format = calendar_variable.is_chinese ? 'y MMM d' : 'd MMM, y'; + window.calendar_variable.date_format_with_short_month = calendar_variable.is_chinese ? 'y M d' : 'd M, y'; + window.calendar_variable.date_format_with_week = calendar_variable.is_chinese ? 'y MMM d (W)' : 'W, MMM d, y'; + window.calendar_variable.short_date = (calendar_variable.is_chinese ? "MMM d (W)" : "W, d MMM"); + window.calendar_variable.short_date_time = (calendar_variable.is_chinese ? "MMM d (W) b h:m" : "W, d MMM h:m b"); +} +window.calendar_variable.short_date_numeric = (calendar_variable.is_chinese ? "MM/dd (w)" : "w MM/dd"); +window.time_format = (calendar_variable.is_chinese ? "b h:m" : "h:m b"); +window.calendar_variable.std_date_format = 'y-MM-d'; +window.calendar_variable.short_day = (calendar_variable.is_chinese ? "d (W)" : "W d"); $.fn.fullCalendar = function(args){ var self = this[0] if(!self.calendar_args) @@ -60,41 +109,40 @@ FullCalendar.Calendar.prototype.isAnOverlapEvent = function(eventStartDay, event } return false; } -window.is_chinese = ( I18n && I18n.locale.indexOf('zh') != -1 ); -window.datetime_format = is_chinese ? 'y M d h:m b' : 'd M, y h:m b'; -window.date_format = is_chinese ? 'y M d' : 'd M, y'; -window.datetime_format = window.date_format; -window.time_format = "h:m b"; -window.std_date_format = 'y-MM-d'; -window.short_day = (is_chinese ? "d (w)" : "w d"); -window.short_date = (is_chinese ? "M d (w)" : "w d, M"); -window.short_date_time = (is_chinese ? "M d (w) h:m b" : "w d, M h:m b"); -window.getDateString = function(date, format,is_chinese) { - var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; - var week_days = ['Sun','Mon','Tue','Wed','Thu','Fri','Sat']; - if(is_chinese){ - months = []; - for(var i=0;i<12;i++){ - months.push((i+1)+"月"); - } - week_days = ["週日","週一","週二","週三","週四","週五","週六"] - } + +window.getDateString = function(date, format, is_chinese) { + var months = calendar_variable.months; + var week_days = calendar_variable.dayNames; var getPaddedComp = function(comp) { return ((parseInt(comp) < 10) ? ('0' + comp) : comp) }, formattedDate = format, + y = date.getFullYear(), + m = date.getMonth(), + d = date.getDate(), + H = date.getHours(), + M = date.getMinutes(), + s = date.getSeconds(), + S = date.getMilliseconds(), + month_name = months[m], + am_trans = (calendar_variable.is_chinese ? '上午' : 'AM'), + pm_trans = (calendar_variable.is_chinese ? '下午' : 'PM'), o = { - "y+": date.getFullYear() + (is_chinese ? "年" : ""), // year - "MM+": getPaddedComp(date.getMonth() + 1), //raw month - "M+": months[date.getMonth()], //month - "d+": (is_chinese ? (date.getDate() + "日") : getPaddedComp(date.getDate())), //day - "w+": week_days[date.getDay()], //weekday - "h+": getPaddedComp((date.getHours() > 12) ? date.getHours() % 12 : date.getHours()), //hour - "H+": getPaddedComp(date.getHours()), //hour - "m+": getPaddedComp(date.getMinutes()), //minute - "s+": getPaddedComp(date.getSeconds()), //second - "S+": getPaddedComp(date.getMilliseconds()), //millisecond, - "b+": (date.getHours() >= 12) ? 'PM' : 'AM' + "yy+": y, //raw year + "y+": y + (calendar_variable.is_chinese ? "年" : ""), // year + "MMM+": month_name, //month + "MM+": getPaddedComp(m + 1), //raw month + "M+": month_name.substring(0,3), //month + "dd+": getPaddedComp(d), //raw day + "d+": (calendar_variable.is_chinese ? (d + "日") : getPaddedComp(d)), //day + "W+": week_days[date.getDay()], //weekday + "w+": (calendar_variable.is_chinese ? week_days[date.getDay()].substr(-1, 1) : week_days[date.getDay()].substr(0, 3)), //weekday + "h+": getPaddedComp((H > 12) ? H % 12 : H), //hour + "H+": getPaddedComp(H), //hour + "m+": getPaddedComp(M), //minute + "s+": getPaddedComp(s), //second + "S+": getPaddedComp(S), //millisecond, + "b+": (H >= 12) ? pm_trans : am_trans }; for (var k in o) { @@ -288,7 +336,7 @@ var Calendar = function(dom){ }); }, // events: 'https://fullcalendar.io/demo-events.json', - headerToolbar: false, + headerToolbar: false, fixedWeekCount: false, initialView: dview, loading: function(bool) { @@ -306,12 +354,35 @@ var Calendar = function(dom){ originalEvent = eventClickInfo.jsEvent, view = eventClickInfo.view, el = $(eventClickInfo.el); - c.event_create_space.html("").hide(); - c.dialog.dismiss(); - c.dialog.inflate(calEvent); - c.dialog.show({"x": originalEvent.clientX,"y": originalEvent.clientY}); + if(el.hasClass("reserve_btn")){ + window.calEvent = calEvent; + var start_time = calEvent.event.start; + var date_str = window.getDateString(start_time,std_date_format); + c.dialog.hide(); + var allow_times = calEvent.event._def.extendedProps.allow_times; + window.pick_hire_date(date_str,allow_times); + }else{ + c.event_create_space.html("").hide(); + c.dialog.dismiss(); + c.dialog.inflate(calEvent); + c.dialog.show({"x": originalEvent.clientX,"y": originalEvent.clientY}); + } }, - select : function(selectionInfo){ + dateClick: function(ev) { + var calendar = this; + var calendar_dom = $(this.el); + if(c.calendar_dom.hasClass("active_picker")){ + var date = ev.date, + date_str = getDateString(date,date_time_str_format), + day_element = ev.dayEl, + jsEvent = ev.jsEvent; + var time_str = date_str.split(" ")[1]; + var date_str = date_str.split(" ")[0]; + calendar_dom.trigger("init_time",[time_str]); + calendar_dom.trigger("select_time",[date_str]); + } + }, + select : function(selectionInfo){ var jsEvent = selectionInfo.jsEvent, view = selectionInfo.view; var start = selectionInfo.start, @@ -338,10 +409,37 @@ var Calendar = function(dom){ }) }, views: { - dayGridMonth: { - dayMaxEvents: false - } - } + timeGridDay: { + titleFormat: function(date_info){ + var date = date_info.date.marker; + return getDateString(date, calendar_variable.date_format_with_week); + }, + dayHeaderFormat: function(date_info){ + return window.calendar_variable.dayNames[date_info.date.marker.getDay()]; + } + }, + timeGridWeek: { + titleFormat: function(date_info){ + var start = date_info.start.marker, + end = date_info.end.marker; + return getDateString(start, calendar_variable.date_format) + ' ~ ' + getDateString(end, calendar_variable.date_format); + }, + dayHeaderFormat: function(date_info){ + return getDateString(date_info.date.marker, calendar_variable.short_date_numeric); + } + }, + dayGridMonth: { + dayMaxEvents: false, + titleFormat: function(date_info){ + var date = date_info.date.marker; + return getDateString(date, calendar_variable.month_year_format); + }, + dayHeaderFormat: function(date_info){ + return window.calendar_variable.dayNamesShort[date_info.date.marker.getDay()]; + } + } + }, + firstDay: (window.calendar_variable.sunday_first == true ? 0 : 1) }); c.create_event_btn.click(function(){ $.ajax({ @@ -356,14 +454,17 @@ var Calendar = function(dom){ c.nextBtn.click(function(){ c.dialog.dismiss(); c.calendar_dom.calendar.next(); + c.title.text(c.calendar_dom.calendar.currentData.viewTitle); }); c.prevBtn.click(function(){ c.dialog.dismiss(); c.calendar_dom.calendar.prev(); + c.title.text(c.calendar_dom.calendar.currentData.viewTitle); }); c.todayBtn.click(function(){ c.dialog.dismiss(); c.calendar_dom.calendar.today(); + c.title.text(c.calendar_dom.calendar.currentData.viewTitle); }); c.modeBtns.click(function(){ c.dialog.dismiss(); @@ -404,13 +505,8 @@ var Calendar = function(dom){ c.calendar_dom.calendar.refetchEvents(); loadeventsonviewchange = false; } - if(c.calendar_dom.calendar.currentData){ - var viewTitle = c.calendar_dom.calendar.currentData.viewTitle; - if(view == "timeGridDay" && $('.fc-col-header-cell-cushion ').text() != "") - viewTitle = $('.fc-col-header-cell-cushion ').text() + ', ' + viewTitle; - $('#current_title').html(viewTitle); - } - c.calendar_dom.calendar.render(); //Rerender to fix layout + c.title.text(c.calendar_dom.calendar.currentData.viewTitle); + // c.calendar_dom.calendar.rerenderEvents(); //Rerender to fix layout }; if(c.currentView == "agenda"){toggleViews("agenda");loadeventsonviewchange = true;} }; @@ -464,11 +560,8 @@ var EventDialog = function(calendar,event){ _event.allDay = _event.event.allDay; _event._start = _event.event.start; _event._end = (_event.event.end ? _event.event.end : _event.event.start); - // var start_date = getDateString(_event._start,date_format); - // var end_date = getDateString(_event._end,date_format); - if(_event._end - _event._start > 86400 * 1000){ - _event.allDay = true; - } + // var start_date = getDateString(_event._start,calendar_variable.date_format); + // var end_date = getDateString(_event._end,calendar_variable.date_format); _event.title = _event.event.title; var extendedProps = _event.event.extendedProps; Object.keys(extendedProps).forEach(function(k){ @@ -481,15 +574,15 @@ var EventDialog = function(calendar,event){ end_time = "", time_string = null; if(_event.allDay) { - start_time = getDateString(_event._start,datetime_format, is_chinese); + start_time = getDateString(_event._start,calendar_variable.date_format_with_short_month); if(_event._end) - end_time = getDateString(_event._end,datetime_format, is_chinese); + end_time = getDateString(_event._end,calendar_variable.date_format_with_short_month); time_string = (_event._start === _event._end || !_event._end ? "

" + start_time + "

" : "" + start_time + "
" + end_time + ""); } else { - start_time = getDateString(_event._start,date_format, is_chinese); - end_time = getDateString(_event._end,date_format, is_chinese); - var stime = getDateString(_event._start,time_format, is_chinese), - etime = getDateString(_event._end,time_format, is_chinese), + start_time = getDateString(_event._start,calendar_variable.date_format_with_short_month); + end_time = getDateString(_event._end,calendar_variable.date_format_with_short_month); + var stime = getDateString(_event._start,time_format), + etime = getDateString(_event._end,time_format), same = (start_time == end_time); if( same ){ time_string = "

" + @@ -507,7 +600,7 @@ var EventDialog = function(calendar,event){ template = '