diff --git a/plugins/discourse-local-dates/assets/javascripts/initializers/discourse-local-dates.js.es6 b/plugins/discourse-local-dates/assets/javascripts/initializers/discourse-local-dates.js.es6
index 30c1b5c5103..50d543c971e 100644
--- a/plugins/discourse-local-dates/assets/javascripts/initializers/discourse-local-dates.js.es6
+++ b/plugins/discourse-local-dates/assets/javascripts/initializers/discourse-local-dates.js.es6
@@ -39,6 +39,11 @@ export function applyLocalDates(dates, siteSettings) {
function buildOptionsFromElement(element, siteSettings) {
const opts = {};
const dataset = element.dataset;
+
+ if (_rangeElements(element).length === 2) {
+ opts.duration = _calculateDuration(element);
+ }
+
opts.time = dataset.time;
opts.date = dataset.date;
opts.recurring = dataset.recurring;
@@ -57,6 +62,12 @@ function buildOptionsFromElement(element, siteSettings) {
return opts;
}
+function _rangeElements(element) {
+ return Array.from(element.parentElement.children).filter(
+ (span) => span.dataset.date
+ );
+}
+
function initializeDiscourseLocalDates(api) {
const siteSettings = api.container.lookup("site-settings:main");
@@ -114,7 +125,7 @@ function buildHtmlPreview(element, siteSettings) {
const dateTimeNode = document.createElement("span");
dateTimeNode.classList.add("date-time");
- dateTimeNode.innerText = preview.formated;
+ dateTimeNode.innerHTML = preview.formated;
previewNode.appendChild(dateTimeNode);
return previewNode;
@@ -127,6 +138,20 @@ function buildHtmlPreview(element, siteSettings) {
return previewsNode.outerHTML;
}
+function _calculateDuration(element) {
+ const [startDataset, endDataset] = _rangeElements(element).map(
+ (dateElement) => dateElement.dataset
+ );
+ const startDateTime = moment(
+ `${startDataset.date} ${startDataset.time || ""}`
+ );
+ const endDateTime = moment(`${endDataset.date} ${endDataset.time || ""}`);
+ const duration = endDateTime.diff(startDateTime, "minutes");
+
+ // negative duration is used when we calculate difference for end date from range
+ return element.dataset === startDataset ? duration : -duration;
+}
+
export default {
name: "discourse-local-dates",
@@ -138,9 +163,13 @@ export default {
const siteSettings = owner.lookup("site-settings:main");
if (event?.target?.classList?.contains("discourse-local-date")) {
- showPopover(event, {
- htmlContent: buildHtmlPreview(event.target, siteSettings),
- });
+ if ($(document.getElementById("d-popover"))[0]) {
+ hidePopover(event);
+ } else {
+ showPopover(event, {
+ htmlContent: buildHtmlPreview(event.target, siteSettings),
+ });
+ }
}
},
@@ -155,7 +184,6 @@ export default {
router.on("routeWillChange", hidePopover);
window.addEventListener("click", this.showDatePopover);
- window.addEventListener("mouseover", this.showDatePopover);
window.addEventListener("mouseout", this.hideDatePopover);
const siteSettings = container.lookup("site-settings:main");
@@ -174,7 +202,6 @@ export default {
teardown() {
window.removeEventListener("click", this.showDatePopover);
- window.removeEventListener("mouseover", this.showDatePopover);
window.removeEventListener("mouseout", this.hideDatePopover);
},
};
diff --git a/plugins/discourse-local-dates/assets/javascripts/lib/local-date-builder.js.es6 b/plugins/discourse-local-dates/assets/javascripts/lib/local-date-builder.js.es6
index 915d87ccf64..d2661343786 100644
--- a/plugins/discourse-local-dates/assets/javascripts/lib/local-date-builder.js.es6
+++ b/plugins/discourse-local-dates/assets/javascripts/lib/local-date-builder.js.es6
@@ -1,9 +1,15 @@
import DateWithZoneHelper from "./date-with-zone-helper";
import I18n from "I18n";
+import { renderIcon } from "discourse-common/lib/icon-library";
-const TIME_FORMAT = "LLL";
+const DATETIME_FORMAT = "LLL";
const DATE_FORMAT = "LL";
+const FULL_DATETIME_FORMAT = "LLLL";
+const TIME_FORMAT = "h:mm A";
+const DAY_OF_THE_WEEK_FORMAT = "dddd";
const RANGE_SEPARATOR = "→";
+const TIME_ICON = "clock";
+const SHORT_FORMAT_DAYS_PERIOD = 1;
export default class LocalDateBuilder {
constructor(params = {}, localTimezone) {
@@ -17,8 +23,9 @@ export default class LocalDateBuilder {
this.calendar =
typeof params.calendar === "undefined" ? true : params.calendar;
this.displayedTimezone = params.displayedTimezone;
- this.format = params.format || (this.time ? TIME_FORMAT : DATE_FORMAT);
+ this.format = params.format || (this.time ? DATETIME_FORMAT : DATE_FORMAT);
this.countdown = params.countdown;
+ this.duration = params.duration;
this.localTimezone = localTimezone;
}
@@ -95,7 +102,8 @@ export default class LocalDateBuilder {
localDate.timezone,
this.localTimezone
),
- this.time
+ this.time,
+ this.duration
),
});
@@ -126,7 +134,8 @@ export default class LocalDateBuilder {
localDate.timezone,
timezone
),
- this.time
+ this.time,
+ this.duration
),
});
});
@@ -148,19 +157,56 @@ export default class LocalDateBuilder {
);
}
- _createDateTimeRange(startRange, time) {
+ _createDateTimeRange(startRange, time, duration) {
+ const [startDate, endDate] = this._calculateDatesForRange(
+ startRange,
+ time,
+ duration
+ );
+ let formatElements = [
+ startDate.format(`${DAY_OF_THE_WEEK_FORMAT}, ${DATE_FORMAT}`),
+ this._optionalTimeIcon(startDate, endDate),
+ startDate.format(TIME_FORMAT),
+ ];
+ if (endDate) {
+ formatElements = formatElements.concat([
+ RANGE_SEPARATOR,
+ endDate.format(this._endDateFormat(startDate, endDate)),
+ ]);
+ }
+ return formatElements.filter(Boolean).join(" ");
+ }
+
+ _shortFormat(startDate, endDate) {
+ return (
+ endDate.datetime.diff(startDate.datetime, "days") <
+ SHORT_FORMAT_DAYS_PERIOD
+ );
+ }
+
+ _optionalTimeIcon(startDate, endDate) {
+ if (!endDate || this._shortFormat(startDate, endDate)) {
+ return `
${renderIcon("string", TIME_ICON)}`;
+ }
+ }
+
+ _endDateFormat(startDate, endDate) {
+ return this._shortFormat(startDate, endDate)
+ ? TIME_FORMAT
+ : FULL_DATETIME_FORMAT;
+ }
+
+ _calculateDatesForRange(date, time, duration) {
// if a time has been given we do not attempt to automatically create a range
// instead we show only one date with a format showing the time
- if (time) {
- return startRange.format(TIME_FORMAT);
- } else {
- const endRange = startRange.add(24, "hours");
- return [
- startRange.format("LLLL"),
- RANGE_SEPARATOR,
- endRange.format("LLLL"),
- ].join(" ");
+ if (time && !duration) {
+ return [date];
}
+ const dates = [
+ date,
+ duration ? date.add(duration, "minutes") : date.add(24, "hours"),
+ ];
+ return duration < 0 ? dates.reverse() : dates;
}
_applyFormatting(localDate, displayedTimezone) {
diff --git a/plugins/discourse-local-dates/test/javascripts/lib/local-date-builder-test.js.es6 b/plugins/discourse-local-dates/test/javascripts/lib/local-date-builder-test.js.es6
index 9764dac4719..f01c289d1dd 100644
--- a/plugins/discourse-local-dates/test/javascripts/lib/local-date-builder-test.js.es6
+++ b/plugins/discourse-local-dates/test/javascripts/lib/local-date-builder-test.js.es6
@@ -446,6 +446,38 @@ test("previews", function (assert) {
);
});
+ freezeTime({ date: "2020-03-22", timezone: PARIS }, () => {
+ assert.buildsCorrectDate(
+ { duration: 90, timezone: PARIS, timezones: [PARIS] },
+ {
+ previews: [
+ {
+ current: true,
+ formated:
+ 'Sunday, March 22, 2020
12:00 AM → 1:30 AM',
+ timezone: "Paris",
+ },
+ ],
+ }
+ );
+ });
+
+ freezeTime({ date: "2020-03-22", timezone: PARIS }, () => {
+ assert.buildsCorrectDate(
+ { duration: 1440, timezone: PARIS, timezones: [PARIS] },
+ {
+ previews: [
+ {
+ current: true,
+ formated:
+ "Sunday, March 22, 2020 12:00 AM → Monday, March 23, 2020 12:00 AM",
+ timezone: "Paris",
+ },
+ ],
+ }
+ );
+ });
+
freezeTime({ date: "2020-03-22", timezone: PARIS }, () => {
assert.buildsCorrectDate(
{ time: "11:34", timezone: PARIS, timezones: [PARIS] },
@@ -453,7 +485,8 @@ test("previews", function (assert) {
previews: [
{
current: true,
- formated: "March 22, 2020 11:34 AM",
+ formated:
+ 'Sunday, March 22, 2020
11:34 AM',
timezone: "Paris",
},
],
@@ -508,19 +541,23 @@ test("previews", function (assert) {
previews: [
{
current: true,
- formated: "April 7, 2020 2:54 PM",
+ formated:
+ 'Tuesday, April 7, 2020
2:54 PM',
timezone: "Paris",
},
{
- formated: "April 7, 2020 1:54 PM",
+ formated:
+ 'Tuesday, April 7, 2020
1:54 PM',
timezone: "London",
},
{
- formated: "April 7, 2020 1:54 PM",
+ formated:
+ 'Tuesday, April 7, 2020
1:54 PM',
timezone: "Lagos",
},
{
- formated: "April 7, 2020 10:54 PM",
+ formated:
+ 'Tuesday, April 7, 2020
10:54 PM',
timezone: "Sydney",
},
],
@@ -539,11 +576,13 @@ test("previews", function (assert) {
previews: [
{
current: true,
- formated: "May 13, 2020 11:00 AM",
+ formated:
+ 'Wednesday, May 13, 2020
11:00 AM',
timezone: "Los Angeles",
},
{
- formated: "May 13, 2020 6:00 PM",
+ formated:
+ 'Wednesday, May 13, 2020
6:00 PM',
timezone: "UTC",
},
],