FIX: add timezone to regional holidays

approved
#1

FIX: add timezone to regional holidays

FIX: schedule the CheckNextRegionalHolidays more often (every 10 minutes) FEATURE: new timezone field in user profile

diff --git a/assets/javascripts/connectors/user-custom-preferences/user-timezone.js.es6 b/assets/javascripts/connectors/user-custom-preferences/user-timezone.js.es6
new file mode 100644
index 0000000..59ea850
--- /dev/null
+++ b/assets/javascripts/connectors/user-custom-preferences/user-timezone.js.es6
@@ -0,0 +1,27 @@
+export default {
+  setupComponent(args, component) {
+    const { currentUser } = component;
+    const user = args.model;
+
+    let instructions;
+
+    // only show the instructions when browsing your own profile
+    if (currentUser && currentUser.id === user.id) {
+      instructions = I18n.t("discourse_calendar.timezone.instructions", { timezone: moment.tz.guess() });
+    }
+
+    component.setProperties({
+      instructions,
+      allTimezones: moment.tz.names(),
+      userTimezone: user.custom_fields.timezone,
+    });
+
+    component.addObserver("userTimezone", () => {
+      user.set("custom_fields.timezone", component.get("userTimezone"));
+    });
+  },
+
+  shouldRender(args, component) {
+    return component.siteSettings.calendar_enabled;
+  }
+}
diff --git a/assets/javascripts/templates/connectors/user-custom-preferences/user-timezone.hbs b/assets/javascripts/templates/connectors/user-custom-preferences/user-timezone.hbs
new file mode 100644
index 0000000..d7ab7a9
--- /dev/null
+++ b/assets/javascripts/templates/connectors/user-custom-preferences/user-timezone.hbs
@@ -0,0 +1,11 @@
+<div class="control-group">
+  <label class="control-label">{{i18n 'discourse_calendar.timezone.title'}}</label>
+  <div class="controls">
+    {{combo-box content=allTimezones value=userTimezone class="user-timezone"}}
+  </div>
+  {{#if instructions}}
+    <div class="instructions">
+      {{instructions}}
+    </div>
+  {{/if}}
+</div>
diff --git a/assets/stylesheets/common/discourse-calendar.scss b/assets/stylesheets/common/discourse-calendar.scss
index cb9214c..090d7c1 100644
--- a/assets/stylesheets/common/discourse-calendar.scss
+++ b/assets/stylesheets/common/discourse-calendar.scss
@@ -87,3 +87,7 @@
 a.holiday {
   cursor: default;
 }
+
+.combo-box.user-timezone {
+  min-width: 15em;
+}
diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml
new file mode 100644
index 0000000..9cab764
--- /dev/null
+++ b/config/locales/client.en.yml
@@ -0,0 +1,6 @@
+en:
+  js:
+    discourse_calendar:
+      timezone:
+        title: "Timezone"
+        instructions: "Your current timezone is %{timezone}."
diff --git a/jobs/scheduled/check_next_regional_holidays.rb b/jobs/scheduled/check_next_regional_holidays.rb
index 4181730..86975a4 100644
--- a/jobs/scheduled/check_next_regional_holidays.rb
+++ b/jobs/scheduled/check_next_regional_holidays.rb
@@ -1,6 +1,6 @@
 module Jobs
   class ::DiscourseCalendar::CheckNextRegionalHolidays < Jobs::Scheduled
-    every 1.hour
+    every 10.minutes
 
     def execute(args)
       return unless SiteSetting.calendar_enabled
@@ -17,6 +17,13 @@ module Jobs
         users_in_region[region] << user_id
       end
 
+      user_timezones = {}
+
+      UserCustomField.where(name: ::DiscourseCalendar::TIMEZONE_CUSTOM_FIELD).pluck(:user_id, :value).each do |user_id, timezone|
+        next unless tz = (TZInfo::Timezone.get(timezone) rescue nil)
+        user_timezones[user_id] = tz
+      end
+
       usernames = User.where(id: user_ids).pluck(:id, :username_lower).to_h
 
       old_regional_holidays = op.custom_fields[::DiscourseCalendar::CALENDAR_HOLIDAYS_CUSTOM_FIELD] || []
@@ -31,12 +38,13 @@ module Jobs
         end
 
         users_in_region[region].each do |user_id|
-          new_regional_holidays << [
-            region,
-            next_holiday[:name],
-            next_holiday[:date].to_s,
-            usernames[user_id]
-          ]
+          date = if tz = user_timezones[user_id]
+            next_holiday[:date].in_time_zone(tz).iso8601
+          else
+            next_holiday[:date].to_s
+          end
+
+          new_regional_holidays << [region, next_holiday[:name], date, usernames[user_id]]
         end
       end
 
diff --git a/plugin.rb b/plugin.rb
index 3cffd83..485ada0 100644
--- a/plugin.rb
+++ b/plugin.rb
@@ -44,6 +44,8 @@ after_initialize do
 
     REGION_CUSTOM_FIELD ||= "holidays-region"
 
+    TIMEZONE_CUSTOM_FIELD ||= "timezone"
+
     def self.users_on_holiday
       PluginStore.get(PLUGIN_NAME, USERS_ON_HOLIDAY_KEY)
     end
@@ -66,6 +68,9 @@ after_initialize do
   register_post_custom_field_type(DiscourseCalendar::CALENDAR_CUSTOM_FIELD, :string)
 
   whitelist_staff_user_custom_field(DiscourseCalendar::HOLIDAY_CUSTOM_FIELD)
+  whitelist_staff_user_custom_field(DiscourseCalendar::TIMEZONE_CUSTOM_FIELD)
+
+  register_editable_user_custom_field(DiscourseCalendar::TIMEZONE_CUSTOM_FIELD)
 
   class DiscourseCalendar::Calendar
     class << self
@@ -91,7 +96,6 @@ after_initialize do
     class << self
       def count(post)
         cooked = PrettyText.cook(post.raw, topic_id: post.topic_id, user_id: post.user_id)
-
         Nokogiri::HTML(cooked).css('span.discourse-local-date').count
       end
     end

GitHub sha: 3b9c7b69

1 Like
Approved #3