diff --git a/app/models/communication/website/agenda/event.rb b/app/models/communication/website/agenda/event.rb index a482b9fc91be146ed84a46c8c6ca1297c01dc95c..30977fc2b6791e20cb6f142406f2f7fbbd5bf189 100644 --- a/app/models/communication/website/agenda/event.rb +++ b/app/models/communication/website/agenda/event.rb @@ -46,11 +46,13 @@ class Communication::Website::Agenda::Event < ApplicationRecord include Sanitizable include WithAccessibility include WithBlobs + include WithCal include WithDuplication include WithFeaturedImage include WithMenuItemTarget include WithPermalink include WithSlug + include WithTime include WithTranslations include WithTree include WithUniversity @@ -74,49 +76,6 @@ class Communication::Website::Agenda::Event < ApplicationRecord scope :for_category, -> (category_id) { joins(:categories).where(communication_website_categories: { id: category_id }).distinct } - scope :future, -> { where('from_day > :today', today: Date.today).ordered_asc } - scope :future_or_current, -> { where('from_day >= :today', today: Date.today).ordered_asc } - scope :current, -> { where('(from_day <= :today AND to_day IS NULL) OR (from_day <= :today AND to_day >= :today)', today: Date.today).ordered_asc } - scope :archive, -> { where('to_day < :today', today: Date.today).ordered_desc } - scope :past, -> { archive } - - validates_presence_of :from_day, :title - validate :to_day_after_from_day, :to_hour_after_from_hour_on_same_day - - STATUS_FUTURE = 'future' - STATUS_CURRENT = 'current' - STATUS_ARCHIVE = 'archive' - - def status - if future? - STATUS_FUTURE - elsif current? - STATUS_CURRENT - else - STATUS_ARCHIVE - end - end - - def future? - from_day > Date.today - end - - def current? - to_day.present? ? (Date.today >= from_day && Date.today <= to_day) - : from_day <= Date.today # Les événements sans date de fin restent actifs - end - - def archive? - to_day.present? ? to_day < Date.today - : false # Les événements sans date de fin restent actifs - end - - # Un événement demain aura une distance de 1, comme un événement hier - # On utilise cette info pour classer les événements à venir dans un sens et les archives dans l'autre - def distance_in_days - (Date.today - from_day).to_i.abs - end - def git_path(website) return unless website.id == communication_website_id && published path = "#{git_path_content_prefix(website)}events/" @@ -148,69 +107,16 @@ class Communication::Website::Agenda::Event < ApplicationRecord "#{Static.remove_trailing_slash website.url}#{Static.clean_path current_permalink_in_website(website).path}" end - def cal - @cal ||= AddToCalendar::URLs.new( - start_datetime: from_time, - end_datetime: to_time, - timezone: 'Europe/Paris', - title: "#{title} #{subtitle}", - url: url, - description: summary, - all_day: (from_hour.nil? && to_hour.nil?) - ) - end - def to_s "#{title}" end protected - def from_time - from_hour.nil? ? from_day.to_time - : date_and_time(from_day, from_hour) - end - - def to_time - if to_day.nil? && to_hour.nil? - # Pas de fin - nil - elsif to_day.nil? && to_hour.present? - # Heure de fin sans jour de fin, donc on se base sur le jour de début - date_and_time(from_day, to_hour) - elsif to_day.present? && to_hour.nil? - # Jour de fin seul - to_day.to_time - elsif to_day.present? && to_hour.nil? - # Jour et heure de fin - date_and_time(to_day, to_hour) - end - end - - def date_and_time(date, time) - # FIXME la timezone est Europe/Paris pour tout - Time.new date.year, - date.month, - date.day, - time.hour, - time.min, - time.sec, - Time.zone - end - def check_accessibility accessibility_merge_array blocks end - def to_day_after_from_day - errors.add(:to_day, :too_soon) if to_day.present? && to_day < from_day - end - - def to_hour_after_from_hour_on_same_day - return if from_day != to_day - errors.add(:to_hour, :too_soon) if to_hour.present? && from_hour.present? && to_hour < from_hour - end - def explicit_blob_ids super.concat [featured_image&.blob_id] end diff --git a/app/models/communication/website/agenda/event/with_cal.rb b/app/models/communication/website/agenda/event/with_cal.rb new file mode 100644 index 0000000000000000000000000000000000000000..450d395dc9dff051fc23e4991683a06d99bd52cc --- /dev/null +++ b/app/models/communication/website/agenda/event/with_cal.rb @@ -0,0 +1,58 @@ +module Communication::Website::Agenda::Event::WithCal + extend ActiveSupport::Concern + + def cal + @cal ||= AddToCalendar::URLs.new( + start_datetime: cal_from_time, + end_datetime: cal_to_time, + timezone: timezone.name, + all_day: cal_all_day, + title: "#{title} #{subtitle}", + url: url, + description: summary + ) + end + + protected + + def cal_from_time + from_hour.nil? ? from_day.to_time + : date_and_time(from_day, from_hour) + end + + def cal_to_time + to_day.nil? ? cal_to_time_with_no_end_day + : cal_to_time_with_end_day + end + + def cal_all_day + from_hour.nil? && to_hour.nil? + end + + # Ce cas n'est plus possible depuis la résolution #1386 + def cal_to_time_with_no_end_day + to_hour.nil? ? nil # Pas de fin + : date_and_time(from_day, to_hour) # Heure de fin sans jour de fin, donc on se base sur le jour de début + end + + def cal_to_time_with_end_day + to_hour.nil? ? to_day.to_time + 1.hour # Jour de fin seul, on ajoute 1 heure pour éviter les événements sans durée + : date_and_time(to_day, to_hour) # Jour et heure de fin + end + + def timezone + # FIXME la timezone est Europe/Paris pour tout + Time.zone + end + + def date_and_time(date, time) + Time.new date.year, + date.month, + date.day, + time.hour, + time.min, + time.sec, + timezone + end + +end diff --git a/app/models/communication/website/agenda/event/with_time.rb b/app/models/communication/website/agenda/event/with_time.rb new file mode 100644 index 0000000000000000000000000000000000000000..5d0c09866ff82ce642c2b378c42d7090cb179d09 --- /dev/null +++ b/app/models/communication/website/agenda/event/with_time.rb @@ -0,0 +1,69 @@ +module Communication::Website::Agenda::Event::WithTime + extend ActiveSupport::Concern + + included do + STATUS_FUTURE = 'future' + STATUS_CURRENT = 'current' + STATUS_ARCHIVE = 'archive' + + scope :future, -> { where('from_day > :today', today: Date.today).ordered_asc } + scope :future_or_current, -> { where('from_day >= :today', today: Date.today).ordered_asc } + scope :current, -> { where('(from_day <= :today AND to_day IS NULL) OR (from_day <= :today AND to_day >= :today)', today: Date.today).ordered_asc } + scope :archive, -> { where('to_day < :today', today: Date.today).ordered_desc } + scope :past, -> { archive } + + before_validation :set_to_day + + validates_presence_of :from_day, :title + validate :to_day_after_from_day, :to_hour_after_from_hour_on_same_day + end + + def status + if future? + STATUS_FUTURE + elsif current? + STATUS_CURRENT + else + STATUS_ARCHIVE + end + end + + def future? + from_day > Date.today + end + + def current? + to_day.present? ? (Date.today >= from_day && Date.today <= to_day) + : from_day <= Date.today # Les événements sans date de fin restent actifs + end + + def archive? + to_day.present? ? to_day < Date.today + : false # Les événements sans date de fin restent actifs + end + + def same_day? + from_day == to_day + end + + # Un événement demain aura une distance de 1, comme un événement hier + # On utilise cette info pour classer les événements à venir dans un sens et les archives dans l'autre + def distance_in_days + (Date.today - from_day).to_i.abs + end + + protected + + def set_to_day + self.to_day = self.from_day if self.to_day.nil? + end + + def to_day_after_from_day + errors.add(:to_day, :too_soon) if to_day.present? && to_day < from_day + end + + def to_hour_after_from_hour_on_same_day + return if from_day != to_day + errors.add(:to_hour, :too_soon) if to_hour.present? && from_hour.present? && to_hour < from_hour + end +end diff --git a/app/views/admin/communication/websites/agenda/events/_dates.html.erb b/app/views/admin/communication/websites/agenda/events/_dates.html.erb index 870e21eb40e032eafeab9b7a85979a0a9a48814c..5df299ee030a068ece7e25fbfa992e47793dac7e 100644 --- a/app/views/admin/communication/websites/agenda/events/_dates.html.erb +++ b/app/views/admin/communication/websites/agenda/events/_dates.html.erb @@ -1,9 +1,23 @@ -<i class="fas fa-play-circle"></i> -<%= l(event.from_day) %> -<%= l(event.from_hour, format: :time_only) if event.from_hour %> -<% if event.to_day %> - <br> - <i class="fas fa-stop-circle"></i> - <%= l(event.to_day) %> - <%= l(event.to_hour, format: :time_only) if event.to_hour %> +<% +detailed = local_assigns.dig(:detailed) +day_format = detailed ? :full + : :default +%> +<% if event.same_day? %> + <%= l(event.from_day, format: day_format).upcase_first %> + <% if event.from_hour %> + <br> + <%= l(event.from_hour, format: :time_only) %> + <% if event.to_hour %> + - <%= l(event.to_hour, format: :time_only) %> + <% end %> + <% end %> +<% else %> + <%= l(event.from_day, format: day_format).upcase_first %> + <%= l(event.from_hour, format: :time_only) if event.from_hour %> + <% if event.to_day %> + <br> + <%= l(event.to_day, format: day_format).upcase_first %> + <%= l(event.to_hour, format: :time_only) if event.to_hour %> + <% end %> <% end %> \ No newline at end of file diff --git a/app/views/admin/communication/websites/agenda/events/_dates_static.html.erb b/app/views/admin/communication/websites/agenda/events/_dates_static.html.erb index 04fa585b16fbbd66b4389714347884a51282561b..703d8eb353d11ae8b7f5e76b76a251ee4f6c9b8a 100644 --- a/app/views/admin/communication/websites/agenda/events/_dates_static.html.erb +++ b/app/views/admin/communication/websites/agenda/events/_dates_static.html.erb @@ -26,8 +26,8 @@ indentation = ' ' * depth <%= indentation %> hour: <%= event.to_hour.strftime "%H:%M" %> <% end %> <%= indentation %> add_to_calendar: -<%= indentation %> google: "<%= event.cal.google_url %>" -<%= indentation %> yahoo: "<%= event.cal.yahoo_url %>" -<%= indentation %> office: "<%= event.cal.office365_url %>" -<%= indentation %> outlook: "<%= event.cal.outlook_com_url %>" -<%= indentation %> ical: "<%= event.cal.ical_url %>" +<%= indentation %> google: "<%= event.cal.google_url.html_safe %>" +<%= indentation %> yahoo: "<%= event.cal.yahoo_url.html_safe %>" +<%= indentation %> office: "<%= event.cal.office365_url.html_safe %>" +<%= indentation %> outlook: "<%= event.cal.outlook_com_url.html_safe %>" +<%= indentation %> ical: "<%= event.cal.ical_url.html_safe %>" diff --git a/app/views/admin/communication/websites/agenda/events/show.html.erb b/app/views/admin/communication/websites/agenda/events/show.html.erb index 013f849125f8efd89558773c7efdf81c565f779b..41591946ed92224b27de1c888615352b50f2b1ae 100644 --- a/app/views/admin/communication/websites/agenda/events/show.html.erb +++ b/app/views/admin/communication/websites/agenda/events/show.html.erb @@ -8,7 +8,7 @@ <% if @event.subtitle.present? %> <p class="mt-n3 text-muted"><%= @event.subtitle %></p> <% end %> - <p><%= render 'admin/communication/websites/agenda/events/dates', event: @event %></p> + <p><%= render 'admin/communication/websites/agenda/events/dates', event: @event, detailed: true %></p> <% end %> </div> <div class="offset-lg-1 col-lg-4"> diff --git a/config/locales/en.yml b/config/locales/en.yml index 596d868698d538ffea00db0c2e36e9ed9b363271..6e2adf9f08597daeb482cfe73fda7ed6f7ad76c0 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -165,6 +165,7 @@ en: date: formats: birthday: "%B %d" + full: "%A %-d %B %Y" delete: Delete default_images_hint: "5 MB max, %{formats}" devise: diff --git a/config/locales/fr.yml b/config/locales/fr.yml index 73b518db256be60ac53ec9e30eee64d421a19704..9ec5a600cd89079b8e189db31e92810e784272f5 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -165,6 +165,7 @@ fr: date: formats: birthday: "%d %B" + full: "%A %-d %B %Y" default_images_hint: "5 Mo max, %{formats}" delete: Supprimer devise: