From 876434e6a5ff7eb3b9b5860487cda5797584e08c Mon Sep 17 00:00:00 2001 From: bohung Date: Mon, 25 Jul 2022 22:37:02 +0800 Subject: [PATCH] Add weekdays setting feature. Fix bug. --- app/assets/javascripts/calendar.js | 16 ++++-- app/assets/javascripts/calendar_frontend.js | 16 ++++-- app/assets/javascripts/calendar_widget.js | 9 ++-- app/assets/javascripts/calendar_widget2.js | 5 +- app/assets/javascripts/category_type.js | 9 ++-- app/controllers/admin/calendars_controller.rb | 4 +- app/controllers/calendars_controller.rb | 12 ++--- app/models/event.rb | 45 +++++++++++++--- app/views/admin/calendar_types/_form.html.erb | 2 +- app/views/admin/calendar_types/index.html.erb | 2 +- app/views/admin/calendar_types/new.html.erb | 2 +- app/views/admin/calendars/_form.html.erb | 51 +++++++++++++++++-- config/locales/en.yml | 11 ++++ config/locales/zh_tw.yml | 11 ++++ config/routes.rb | 9 +++- 15 files changed, 163 insertions(+), 41 deletions(-) diff --git a/app/assets/javascripts/calendar.js b/app/assets/javascripts/calendar.js index 9fcda58..3f8b96b 100644 --- a/app/assets/javascripts/calendar.js +++ b/app/assets/javascripts/calendar.js @@ -19,6 +19,14 @@ if(!(window.calendar_variable.dayNames)){ window.calendar_variable.dayNamesShort = ['Sun', 'Mon', 'Tue', 'Wed','Thu', 'Fri', 'Sat']; } } +if(Array.prototype.rotate == undefined){ + Array.prototype.rotate = function(n) { + n = n % this.length; + while (this.length && n < 0) n += this.length; + this.push.apply(this, this.splice(0, n)); + return this; + } +} if(window.calendar_variable.is_chinese){ window.calendar_variable.months = []; for(var i=0;i<12;i++){ @@ -729,7 +737,7 @@ var AgendaView = function(calendar){ '' + '' + '' + - calendar_variable.dayNamesShort.map(function(title){ + calendar_variable.dayNamesShort.slice(0).rotate(calendar_variable.sunday_first ? 0 : 1).map(function(title){ return ''; }).join('') + '' + @@ -1066,9 +1074,10 @@ var AgendaView = function(calendar){ var row = $(""); switch (position){ case "first": + var offset = firstDay.getDay() - (window.calendar_variable.sunday_first ? 0 : 1); for(var i = 0;i < 7;i++){ var td = $(""); - if(i >= firstDay.getDay()){ + if(i >= offset){ td.text(last_inserted_date); td.attr("data-date-node",last_inserted_date+"-"+firstDay.getMonth()+"-"+firstDay.getFullYear()); last_inserted_date++; @@ -1086,9 +1095,10 @@ var AgendaView = function(calendar){ } break; case "last": + var offset = lastDay.getDay() - (window.calendar_variable.sunday_first ? 0 : 1); for(var i = 0;i < 7;i++){ var td = $(""); - if(i <= lastDay.getDay()){ + if(i <= offset){ td.text(last_inserted_date); td.attr("data-date-node",last_inserted_date+"-"+firstDay.getMonth()+"-"+firstDay.getFullYear()); last_inserted_date++; diff --git a/app/assets/javascripts/calendar_frontend.js b/app/assets/javascripts/calendar_frontend.js index 2794564..3978fca 100644 --- a/app/assets/javascripts/calendar_frontend.js +++ b/app/assets/javascripts/calendar_frontend.js @@ -19,6 +19,14 @@ if(!(window.calendar_variable.dayNames)){ window.calendar_variable.dayNamesShort = ['Sun', 'Mon', 'Tue', 'Wed','Thu', 'Fri', 'Sat']; } } +if(Array.prototype.rotate == undefined){ + Array.prototype.rotate = function(n) { + n = n % this.length; + while (this.length && n < 0) n += this.length; + this.push.apply(this, this.splice(0, n)); + return this; + } +} if(window.calendar_variable.is_chinese){ window.calendar_variable.months = []; for(var i=0;i<12;i++){ @@ -560,7 +568,7 @@ var AgendaView = function(calendar){ '
'+title+'
' + '' + '' + - calendar_variable.dayNamesShort.map(function(title){ + calendar_variable.dayNamesShort.slice(0).rotate(calendar_variable.sunday_first ? 0 : 1).map(function(title){ return ''; }).join('') + '' + @@ -898,9 +906,10 @@ var AgendaView = function(calendar){ var row = $(""); switch (position){ case "first": + var offset = firstDay.getDay() - (window.calendar_variable.sunday_first ? 0 : 1); for(var i = 0;i < 7;i++){ var td = $(""); - if(i >= firstDay.getDay()){ + if(i >= offset){ td.text(last_inserted_date); td.attr("data-date-node",last_inserted_date+"-"+firstDay.getMonth()+"-"+firstDay.getFullYear()); last_inserted_date++; @@ -918,9 +927,10 @@ var AgendaView = function(calendar){ } break; case "last": + var offset = lastDay.getDay() - (window.calendar_variable.sunday_first ? 0 : 1); for(var i = 0;i < 7;i++){ var td = $(""); - if(i <= lastDay.getDay()){ + if(i <= offset){ td.text(last_inserted_date); td.attr("data-date-node",last_inserted_date+"-"+firstDay.getMonth()+"-"+firstDay.getFullYear()); last_inserted_date++; diff --git a/app/assets/javascripts/calendar_widget.js b/app/assets/javascripts/calendar_widget.js index 8ace494..9fc74c5 100644 --- a/app/assets/javascripts/calendar_widget.js +++ b/app/assets/javascripts/calendar_widget.js @@ -326,23 +326,24 @@ var CalendarModuleMonth1 = function(date,dom,subpart,url,index_flag){ var row = $(""); switch (position){ case "first": - var first_line_first_day = new Date(year,month,firstDay.getDate()-firstDay.getDay()) + var offset = firstDay.getDay() - (window.calendar_variable.sunday_first ? 0 : 1); + var first_line_first_day = new Date(year,month,firstDay.getDate() - offset) var first_line_first_date = first_line_first_day.getDate() var first_line_first_month = first_line_first_day.getMonth() var first_line_first_year = first_line_first_day.getFullYear() first_target_day = new Date(first_line_first_year,first_line_first_month,first_line_first_date) for(var i = 0;i < 7;i++){ var td = $(""); - if(i >= firstDay.getDay()){ + if(i >= offset){ if(today != 0 && last_inserted_date == today){ td.addClass("w-calendar-today"); } td.find('div').html(last_inserted_date<10 ? " "+last_inserted_date+" " : last_inserted_date); td.attr("data-date-node",last_inserted_date+"-"+firstDay.getMonth()+"-"+firstDay.getFullYear()); last_inserted_date++; - }else{ + }else{first_line_first_date td.find('div').text(first_line_first_date+i) - td.attr("data-date-node",(first_line_first_date+i)+"-"+first_line_first_month+"-"+first_line_first_year); + td.attr("data-date-node",(+i)+"-"+first_line_first_month+"-"+first_line_first_year); td.addClass("w-calendar-other-month") } row.append(td); diff --git a/app/assets/javascripts/calendar_widget2.js b/app/assets/javascripts/calendar_widget2.js index a53a16b..b25ebba 100644 --- a/app/assets/javascripts/calendar_widget2.js +++ b/app/assets/javascripts/calendar_widget2.js @@ -466,14 +466,15 @@ var CalendarModuleMonth2 = function(date,dom,subpart,url,index_flag){ var row = $(""); switch (position){ case "first": - var first_line_first_day = new Date(year,month,firstDay.getDate()-firstDay.getDay()) + var offset = firstDay.getDay() - (window.calendar_variable.sunday_first ? 0 : 1); + var first_line_first_day = new Date(year,month,firstDay.getDate() - offset) var first_line_first_date = first_line_first_day.getDate() var first_line_first_month = first_line_first_day.getMonth() var first_line_first_year = first_line_first_day.getFullYear() first_target_day = new Date(first_line_first_year,first_line_first_month,first_line_first_date) for(var i = 0;i < 7;i++){ var td = $(""); - if(i >= firstDay.getDay()){ + if(i >= offset){ if(today != 0 && last_inserted_date == today){ td.addClass("w-calendar-today"); } diff --git a/app/assets/javascripts/category_type.js b/app/assets/javascripts/category_type.js index 98d1b8d..63023e0 100644 --- a/app/assets/javascripts/category_type.js +++ b/app/assets/javascripts/category_type.js @@ -5,21 +5,20 @@ $(function() { $.pageslide.loadComplete(function(pageslide, item) { $('.filter-item').removeClass("active"); item.closest('li').addClass('active'); + $('.color-picker').miniColors("destroy"); + setForm(item.data('form')); if(item.data('id') == 'new') { - resetForm(); pageslide.find('form').attr('method', 'post'); $("#update_patch").remove(); } else { - $('.color-picker').miniColors("destroy"); - setForm(item.data('form')); pageslide.find('form').attr("action",item.data("href")); if($("#update_patch").length == 0){ pageslide.find("form").append(""); } pageslide.find('input[type="checkbox"]').prop( 'checked', item.data('disable') ); - $('.color-picker').miniColors(); - $('.miniColors-trigger').addClass('btn'); } + $('.color-picker').miniColors(); + $('.miniColors-trigger').addClass('btn'); }); }) \ No newline at end of file diff --git a/app/controllers/admin/calendars_controller.rb b/app/controllers/admin/calendars_controller.rb index f2b91ee..1ba9bbd 100644 --- a/app/controllers/admin/calendars_controller.rb +++ b/app/controllers/admin/calendars_controller.rb @@ -49,8 +49,8 @@ class Admin::CalendarsController < OrbitAdminController end def agenda - agenda_start = Time.at(params[:unix_start].to_i).to_s - agenda_end = Time.at(params[:unix_end].to_i).to_s + agenda_start = Time.at(params[:unix_start].to_i).utc + agenda_end = Time.at(params[:unix_end].to_i).utc @events = Event.agenda_events(agenda_start,agenda_end) # re = Event.recurring_event(Time.at(params[:unix_start].to_i), Time.at(params[:unix_end].to_i)) # @events = @events.inject(re, :<<) diff --git a/app/controllers/calendars_controller.rb b/app/controllers/calendars_controller.rb index 705869a..e71d380 100644 --- a/app/controllers/calendars_controller.rb +++ b/app/controllers/calendars_controller.rb @@ -10,7 +10,7 @@ class CalendarsController < ApplicationController { "modes_info" => @calendar_setting.get_modes_info.map.with_index{|(trans, mode),i| {trans: trans, mode: mode, active_class: (i == 2 ? 'active' : '')}}, - "week_title" => @calendar_setting.week_title.map{|t| {'week_title'=> t}}, + "week_title" => @calendar_setting.week_title.map{|t| {'week_title'=> t}}.rotate(@calendar_setting.sunday_first ? 0 : 1), "extras" => { "page_id" => OrbitHelper.params[:page_id], 'widget_title' => page.name, @@ -43,7 +43,7 @@ class CalendarsController < ApplicationController { "modes_info" => @calendar_setting.get_modes_info.map.with_index{|(trans, mode),i| {trans: trans, mode: mode, active_class: (i == 2 ? 'active' : '')}}, - "week_title" => @calendar_setting.week_title.map{|t| {'week_title'=> t}}, + "week_title" => @calendar_setting.week_title.map{|t| {'week_title'=> t}}.rotate(@calendar_setting.sunday_first ? 0 : 1), "extras" => { "subpart-id" => part.id.to_s, "more_url" => OrbitHelper.widget_more_url, @@ -94,8 +94,8 @@ class CalendarsController < ApplicationController calendar_types = [] end if params[:unix_start].present? && params[:unix_end].present? - agenda_start = Time.at(params[:unix_start].to_i).utc.to_s - agenda_end = Time.at(params[:unix_end].to_i).utc.to_s + agenda_start = Time.at(params[:unix_start].to_i).utc + agenda_end = Time.at(params[:unix_end].to_i).utc event = Event.where("title_translations.#{locale}".to_sym.ne=>"") events = event.with_categories(calendar_types).agenda_events(agenda_start,agenda_end) end @@ -115,8 +115,8 @@ class CalendarsController < ApplicationController calendar_types = [] end if params[:unix_start].present? && params[:unix_end].present? - agenda_start = Time.at(params[:unix_start].to_i).utc.to_s - agenda_end = Time.at(params[:unix_end].to_i).utc.to_s + agenda_start = Time.at(params[:unix_start].to_i).utc + agenda_end = Time.at(params[:unix_end].to_i).utc event = Event.where("title_translations.#{locale}".to_sym.ne=>"") events = event.with_categories(calendar_types).agenda_events(agenda_start,agenda_end) end diff --git a/app/models/event.rb b/app/models/event.rb index 10756a2..ecc1581 100644 --- a/app/models/event.rb +++ b/app/models/event.rb @@ -9,24 +9,26 @@ class Event field :title field :note - field :title_translations,type: Hash,default: {} - field :note_translations,type: Hash,default: {} + field :title_translations,type: Hash, default: {} + field :note_translations,type: Hash, default: {} field :start, type: DateTime field :end, type: DateTime - field :all_day, type: Boolean,default: false - field :recurring, type: Boolean,default: false + field :all_day, type: Boolean, default: false + field :recurring, type: Boolean, default: false field :frequency field :period + field :weekdays, type: Array, default: [] field :recurring_end_date, type: DateTime field :create_user_id field :update_user_id field :module_key field :model_cat field :model_page_id - field :model_tags,type: Array,default: [] + field :model_tags, type: Array, default: [] + field :is_weekdays, type: Boolean, default: false belongs_to :calendar_type field :url - field :url_translations,type: Hash,default: {} + field :url_translations, type: Hash, default: {} def get_module_url page = !self.model_page_id.blank? ? Page.find(self.model_page_id): Page.where(:module => self.module_key).where(:categories.in => Array(self.model_cat)+[[]],:tags.in=>Array(self.model_tags)+[[]]).first page.nil? ? '' : (page.url+'/'+eval(self.model_class).where(:id=>self.model_id).first.to_calendar_param) @@ -64,6 +66,11 @@ class Event self['title'] = self.title self['note'] = self.note self['url'] = self.url + if self.is_weekdays + self.weekdays = (1..5).to_a #平日 + else + self.weekdays = self.weekdays.map{|s| s.to_i}.sort + end end ######################################## validates_presence_of :title, :message => "Please fill the title of the Event", :if => lambda { self['title_translations'].blank? } @@ -158,6 +165,7 @@ class Event is_year = false days = 1 interval = nil + weekdays = nil if re.period == 'Daily' period_str = 'day' interval = 1.day @@ -165,6 +173,8 @@ class Event period_str = 'week' days = 7 interval = 1.week + weekdays = re.weekdays + weekdays = nil if weekdays.blank? elsif re.period == 'Monthly' period_str = 'month' is_month = true @@ -195,12 +205,31 @@ class Event add_interval += (freq - rest) end add_interval = add_interval.send(period_str) + need_check_start = false + if weekdays + add_interval -= @start_date.wday.day + need_check_start = true + end + start_date = [start_date, @start_date].max @start_date += add_interval @end_date += add_interval new_end_date = has_recurring_end_date ? [re.recurring_end_date,end_date].min : end_date while @start_date <= new_end_date do - if @start_date >= start_date && @start_date != org_start - @recurring << data.merge({:start => @start_date.to_json.gsub('"',''), :end => @end_date.to_json.gsub('"','')}) + if weekdays + weekdays.each do |w| + new_start = (@start_date + w.day) + if need_check_start && new_start < start_date + next + end + if new_start != org_start + @recurring << data.merge({:start => new_start.to_json.gsub('"',''), :end => (@end_date + w.day).to_json.gsub('"','')}) + end + end + need_check_start = false + else + if @start_date != org_start + @recurring << data.merge({:start => @start_date.to_json.gsub('"',''), :end => @end_date.to_json.gsub('"','')}) + end end @start_date += interval @end_date += interval diff --git a/app/views/admin/calendar_types/_form.html.erb b/app/views/admin/calendar_types/_form.html.erb index df75bce..00ac204 100644 --- a/app/views/admin/calendar_types/_form.html.erb +++ b/app/views/admin/calendar_types/_form.html.erb @@ -1,6 +1,6 @@ <%= label_tag("color", t("calendar.color")) %>
- <%= f.text_field :color, id: "color", :class => "color-picker miniColors input-small", :size => "7", :maxlength => "7", :autocomplete=>"off",:value=>"9100FF" %> + <%= text_field_tag "#{f.object_name}[color]", f.object.color || "#9100FF", id: "color", :class => "color-picker miniColors input-small", :size => "7", :maxlength => "7", :autocomplete=>"off",:value=>"#9100FF" %>
<%= f.fields_for :title_translations do |f| %> <% @site_valid_locales.each do |locale| %> diff --git a/app/views/admin/calendar_types/index.html.erb b/app/views/admin/calendar_types/index.html.erb index a81ae4a..cdf9d48 100644 --- a/app/views/admin/calendar_types/index.html.erb +++ b/app/views/admin/calendar_types/index.html.erb @@ -18,7 +18,7 @@
diff --git a/app/views/admin/calendar_types/new.html.erb b/app/views/admin/calendar_types/new.html.erb index afca95f..c4f29f9 100644 --- a/app/views/admin/calendar_types/new.html.erb +++ b/app/views/admin/calendar_types/new.html.erb @@ -6,7 +6,7 @@
<%= label_tag("color", t("calendar.color")) %> - <%= f.text_field :color, :class => "color-picker miniColors span5", :size => "7", :maxlength => "7", :autocomplete=>"off",:value=>"9100FF" %> + <%= text_field_tag "#{f.object_name}[color]", "#9100FF", :id=>"color", :class=>"color-picker miniColors span5", :size=>"7", :maxlength=>"7", :autocomplete=>"off" %>
diff --git a/app/views/admin/calendars/_form.html.erb b/app/views/admin/calendars/_form.html.erb index b9f8f47..74d97aa 100644 --- a/app/views/admin/calendars/_form.html.erb +++ b/app/views/admin/calendars/_form.html.erb @@ -124,7 +124,7 @@
-<% data_format = @event.all_day ? 'yyyy/MM/dd' : 'yyyy/MM/dd hh:mm' %> +<% data_format = @all_day ? 'yyyy/MM/dd' : 'yyyy/MM/dd hh:mm' %>
<%= f.label t("start_date"), :class=>"control-label" %> <%#= f.datetime_select :start %> @@ -161,9 +161,9 @@
>
- <%=f.label :period, t("calendar.repeats"),:class=>"control-label" %> + <%=f.label :period, t("calendar.repeats"),:class=>"control-label", :for => "event_period" %>
- <%=f.select :period, Event::REPEATS.map{|v| [t("calendar.#{v.downcase}"),v]},{},:class=>"span5" %> + <%=f.select :period, Event::REPEATS.map{|v| [t("calendar.#{v.downcase}"),v]},{},:class=>"span5",:id => "event_period" %>
@@ -172,6 +172,31 @@ <%=f.select :frequency, (1..30).to_a,{},:class=>"span2" %>
+
+ <%=f.label :is_weekdays, t("calendar.type") ,:class=>"control-label", :for => "event_is_weekdays" %> +
+ <%=f.select :is_weekdays, options_for_select(['custom', 'weekdays'].map.with_index{|v, i| [t("calendar.#{v}"), i.to_s]}, f.object.is_weekdays ? '1' : '0'),{},:class=>"span5",:id=>"event_is_weekdays" %> +
+ <% + weekdays = f.object.weekdays + if f.object.new_record? && f.object.start + weekdays = [f.object.start.wday] + end + tmp_html = [] + %> + <% (0...7).each do |i| %> + <% tmp = f.check_box_tag "#{f.object_name}[weekdays][]", i, weekdays.include?(i), {:class=>"weekdays-checkbox"} + tmp += t("calendar.short_day.#{i}") + tmp_html << tmp + %> + <% end %> + <% unless (CalendarSetting.first.sunday_first rescue false) + tmp_html.rotate!(1) + end %> + <%= tmp_html.join("\n").html_safe %> +
+
+
<%= f.label t("calendar.recurring_end_date"), :class=>"control-label" %>
@@ -294,5 +319,25 @@ $(this).html(($('
').append(e.originalEvent.clipboardData.getData('text/plain')).text())); e.preventDefault(); }); + $("#event_is_weekdays").change(function(){ + if($(this).val() == "0"){ + $("#Weekly_custom_panel").removeClass('hide'); + }else{ + $("#Weekly_custom_panel").addClass('hide'); + } + }) + $("#event_period").change(function(){ + if($(this).val() == "Weekly"){ + $("#Weekly_panel").removeClass('hide'); + }else{ + $("#Weekly_panel").addClass('hide'); + } + }) + $("#event_start").change(function(){ + var _this = $(this); + var date = $.ui_datepicker.parseDate(_this.data('datepicker').settings.dateFormat, _this.val()); + $(".weekdays-checkbox").prop("checked", false); + $(".weekdays-checkbox").eq(date.getDay()).prop("checked", true); + }) }) \ No newline at end of file diff --git a/config/locales/en.yml b/config/locales/en.yml index 0eef5c1..3869fbb 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -1,5 +1,8 @@ en: calendar: + type: Type + custom: Custom + weekdays: Weekdays recurring_end_date: "Recurring End Date" "12_hour_clock": "12 hour clock" "24_hour_clock": "24 hour clock" @@ -17,6 +20,14 @@ en: month: "Month" agenda: "Agenda" day_of_the_week: "Day of the week" + short_day: + "0": "Sun" + "1": "Mon" + "2": "Tue" + "3": "Wed" + "4": "Thu" + "5": "Fri" + "6": "Sat" day: "0": "Sunday" "1": "Monday" diff --git a/config/locales/zh_tw.yml b/config/locales/zh_tw.yml index 22eea0a..d971e62 100644 --- a/config/locales/zh_tw.yml +++ b/config/locales/zh_tw.yml @@ -1,5 +1,8 @@ zh_tw: calendar: + type: 類型 + custom: 自訂 + weekdays: 平日 recurring_end_date: "週期結束時間" "12_hour_clock": "12小時制" "24_hour_clock": "24小時制" @@ -17,6 +20,14 @@ zh_tw: month: "月曆" agenda: "日程" day_of_the_week: "星期幾" + short_day: + "0": "日" + "1": "一" + "2": "二" + "3": "三" + "4": "四" + "5": "五" + "6": "六" day: "0": "週日" "1": "週一" diff --git a/config/routes.rb b/config/routes.rb index e0afd84..4ff5484 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -5,7 +5,7 @@ Rails.application.routes.draw do Thread.new do s = Site.first update_flag = s.respond_to?(:tmp_flags) - need_update = !update_flag || !(s.tmp_flags.include?('cf1')) + need_update = !update_flag || !(s.tmp_flags.include?('cf2')) calendar_setting = CalendarSetting.first calendar_setting = CalendarSetting.create if calendar_setting.nil? if need_update @@ -21,9 +21,14 @@ Rails.application.routes.draw do e.url_translations = locales.map{|l| [l.to_s, e[:url].to_s]}.to_h e.save end + Event.where(:period=>'Weekly',:weekdays=>nil).each do |e| + wday = e.start.wday rescue nil + e.weekdays = [wday] + e.save + end if update_flag s = Site.first - s.tmp_flags << 'cf1' + s.tmp_flags << 'cf2' s.save end puts "Calendar fix!"
'+title+'