FEATURE: refactoring and better handling of special cases (#6666)

FEATURE: refactoring and better handling of special cases (#6666)

From b0d08b5a8cc7fe66f69a7cd18816fe11ad6c7e3a Mon Sep 17 00:00:00 2001
From: Joffrey JAFFEUX <j.jaffeux@gmail.com>
Date: Mon, 26 Nov 2018 14:20:32 +0100
Subject: [PATCH] FEATURE: refactoring and better handling of special cases
 (#6666)


diff --git a/plugins/discourse-local-dates/assets/javascripts/discourse-local-dates.js b/plugins/discourse-local-dates/assets/javascripts/discourse-local-dates.js
deleted file mode 100644
index e39b843..0000000
--- a/plugins/discourse-local-dates/assets/javascripts/discourse-local-dates.js
+++ /dev/null
@@ -1,141 +0,0 @@
-(function($) {
-  $.fn.applyLocalDates = function(repeat) {
-    function _formatTimezone(timezone) {
-      return timezone.replace("_", " ").split("/");
-    }
-
-    function processElement($element, options) {
-      repeat = repeat || true;
-
-      if (this.timeout) {
-        clearTimeout(this.timeout);
-      }
-
-      var relativeTime;
-
-      var dateAndTime = options.date;
-      if (options.time) {
-        dateAndTime = dateAndTime + " " + options.time;
-      }
-
-      if (options.timezone) {
-        relativeTime = moment.tz(dateAndTime, options.timezone).utc();
-      } else {
-        relativeTime = moment.utc(dateAndTime);
-      }
-
-      if (relativeTime < moment().utc()) {
-        if (options.recurring) {
-          var parts = options.recurring.split(".");
-          var count = parseInt(parts[0], 10);
-          var type = parts[1];
-          var diff = moment().diff(relativeTime, type);
-          var add = Math.ceil(diff + count);
-
-          relativeTime = relativeTime.add(add, type);
-        } else {
-          $element.addClass("past");
-        }
-      }
-
-      var previews = options.timezones.split("|").map(function(timezone) {
-        var dateTime = relativeTime.tz(timezone).format(options.format);
-
-        var timezoneParts = _formatTimezone(timezone);
-
-        if (dateTime.match(/TZ/)) {
-          return dateTime.replace("TZ", timezoneParts.join(": "));
-        } else {
-          var output = timezoneParts[0];
-          if (timezoneParts[1]) {
-            output += " (" + timezoneParts[1] + ")";
-          }
-          output += " " + dateTime;
-          return output;
-        }
-      });
-
-      var relativeTime = relativeTime.tz(options.displayedZone);
-
-      var d = function(key) {
-        var translated = I18n.t("discourse_local_dates.relative_dates." + key, {
-          time: "LT"
-        });
-
-        if (options.time) {
-          return translated
-            .split("LT")
-            .map(function(w) {
-              return "[" + w + "]";
-            })
-            .join("LT");
-        } else {
-          return "[" + translated.replace(" LT", "") + "]";
-        }
-      };
-
-      var relativeFormat = {
-        sameDay: d("today"),
-        nextDay: d("tomorrow"),
-        lastDay: d("yesterday"),
-        sameElse: "L"
-      };
-
-      if (
-        options.calendar &&
-        relativeTime.isBetween(
-          moment().subtract(1, "day"),
-          moment().add(2, "day")
-        )
-      ) {
-        relativeTime = relativeTime.calendar(null, relativeFormat);
-      } else {
-        relativeTime = relativeTime.format(options.format);
-      }
-
-      var html = "<span>";
-      html += "<i class='fa fa-globe d-icon d-icon-globe'></i>";
-      html += "<span class='relative-time'></span>";
-      html += "</span>";
-
-      var joinedPreviews = previews.join("\n");
-
-      var displayedTime = relativeTime.replace(
-        "TZ",
-        _formatTimezone(options.displayedZone).join(": ")
-      );
-
-      $element
-        .html(html)
-        .attr("title", joinedPreviews)
-        .attr("data-tooltip", joinedPreviews)
-        .addClass("cooked-date")
-        .find(".relative-time")
-        .text(displayedTime);
-
-      if (repeat) {
-        this.timeout = setTimeout(function() {
-          processElement($element, options);
-        }, 10000);
-      }
-    }
-
-    return this.each(function() {
-      var $this = $(this);
-
-      var options = {};
-      options.time = $this.attr("data-time");
-      options.format =
-        $this.attr("data-format") || (options.time ? "LLL" : "LL");
-      options.date = $this.attr("data-date");
-      options.recurring = $this.attr("data-recurring");
-      options.timezones = $this.attr("data-timezones") || "Etc/UTC";
-      options.timezone = $this.attr("data-timezone");
-      options.calendar = ($this.attr("data-calendar") || "on") === "on";
-      options.displayedZone =
-        $this.attr("data-displayed-zone") || moment.tz.guess();
-
-      processElement($this, options);
-    });
-  };
-})(jQuery);
diff --git a/plugins/discourse-local-dates/assets/javascripts/discourse-local-dates.js.no-module.es6 b/plugins/discourse-local-dates/assets/javascripts/discourse-local-dates.js.no-module.es6
new file mode 100644
index 0000000..176a41a
--- /dev/null
+++ b/plugins/discourse-local-dates/assets/javascripts/discourse-local-dates.js.no-module.es6
@@ -0,0 +1,283 @@
+(function($) {
+  $.fn.applyLocalDates = function(repeat) {
+    const processElement = ($element, options = {}) => {
+      if (this.timeout) clearTimeout(this.timeout);
+
+      repeat = repeat || true;
+      const utc = moment().utc();
+      const dateTime = options.time
+        ? `${options.date} ${options.time}`
+        : options.date;
+      let utcDateTime;
+
+      let displayedTimezone;
+      if (options.time) {
+        displayedTimezone = options.displayedTimezone || moment.tz.guess();
+      } else {
+        displayedTimezone =
+          options.displayedTimezone || options.timezone || moment.tz.guess();
+      }
+
+      // if timezone given we convert date and time from given zone to Etc/UTC
+      if (options.timezone) {
+        utcDateTime = _applyZoneToDateTime(dateTime, options.timezone);
+      } else {
+        utcDateTime = moment.utc(dateTime);
+      }
+
+      if (utcDateTime < utc) {
+        // if event is in the past we want to bump it no next occurrence when
+        // recurring is set
+        if (options.recurring) {
+          utcDateTime = _applyRecurrence(utcDateTime, options.recurring);
+        } else {
+          $element.addClass("past");
+        }
+      }
+
+      // once we have the correct UTC date we want
+      // we adjust it to watching user timezone
+      const adjustedDateTime = utcDateTime.tz(displayedTimezone);
+
+      const previews = _generatePreviews(
+        adjustedDateTime.clone(),
+        displayedTimezone,
+        options
+      );
+      const textPreview = _generateTextPreview(previews);
+      const htmlPreview = _generateHtmlPreview(previews);
+
+      const formatedDateTime = _applyFormatting(
+        adjustedDateTime,
+        displayedTimezone,
+        options
+      );
+
+      const $dateTemplate = `
+        <span>
+          <i class="fa fa-globe d-icon d-icon-globe"></i>
+          <span class="relative-time"></span>
+        </span>
+      `;
+
+      $element
+        .html($dateTemplate)
+        .attr("title", textPreview)
+        .attr("data-html-tooltip", `<div class="previews">${htmlPreview}</div>`)
+        .addClass("cooked-date")
+        .find(".relative-time")
+        .text(formatedDateTime);
+
+      if (repeat) {
+        this.timeout = setTimeout(
+          () => processElement($element, options),
+          10000
+        );
+      }
+    };
+
+    const _formatTimezone = timezone =>
+      timezone
+        .replace("_", " ")
+        .replace("Etc/", "")
+        .split("/");
+
+    const _applyZoneToDateTime = (dateTime, timezone) => {
+      return moment.tz(dateTime, timezone).utc();
+    };
+
+    const _calendarFormats = time => {
+      const _translate = key => {
+        const translated = I18n.t(
+          `discourse_local_dates.relative_dates.${key}`,
+          {
+            time: "LT"
+          }
+        );
+
+        if (time) {
+          return translated
+            .split("LT")
+ 

GitHub

@jjaffeux this is incompatible with FA5. But I guess we can’t import the helpers from icon-library here.

Only option I see here is to insert the icon’s SVG markup directly.

That commit number though :smiling_imp:

2 Likes

Oh yeah good call thanks, wish we had a better solution here…

2 Likes

Now that FA5 is merged we need to follow this up.

1 Like

Already done in the FA5 merge: discourse/discourse-local-dates.js.no-module.es6 at 1da265db11b0894f9712ec3fa40f4bb5ed155ec4 · discourse/discourse · GitHub

3 Likes