diff --git a/plugins/discourse-local-dates/assets/javascripts/initializers/discourse-local-dates.js b/plugins/discourse-local-dates/assets/javascripts/initializers/discourse-local-dates.js index 4eb5b8066ee..d360d643fdd 100644 --- a/plugins/discourse-local-dates/assets/javascripts/initializers/discourse-local-dates.js +++ b/plugins/discourse-local-dates/assets/javascripts/initializers/discourse-local-dates.js @@ -21,10 +21,22 @@ export function applyLocalDates(dates, siteSettings) { const currentUserTZ = moment.tz.guess(); - dates.forEach((element) => { + dates.forEach((element, index, arr) => { const opts = buildOptionsFromElement(element, siteSettings); + if ( + element.attributes["data-range"]?.value === "to" && + index !== 0 && + arr[index - 1].attributes["data-range"]?.value === "from" + ) { + const fromElement = arr[index - 1]; + if (_rangeIsSameLocalDay(fromElement, element)) { + opts.sameLocalDayAsFrom = true; + } + } + const localDateBuilder = new LocalDateBuilder(opts, currentUserTZ).build(); + element.innerText = ""; element.insertAdjacentHTML( "beforeend", @@ -45,6 +57,17 @@ export function applyLocalDates(dates, siteSettings) { }); } +function _rangeIsSameLocalDay(fromElement, toElement) { + const timezone = fromElement.attributes["data-timezone"].value; + const from = moment(_getDateFromElement(fromElement)).tz(timezone); + const to = moment(_getDateFromElement(toElement)).tz(timezone); + return from.isSame(to, "day"); +} + +function _getDateFromElement(element) { + return `${element.attributes["data-date"].value}T${element.attributes["data-time"].value}`; +} + function buildOptionsFromElement(element, siteSettings) { const opts = {}; const dataset = element.dataset; @@ -85,6 +108,7 @@ function buildOptionsFromMarkdownTag(element) { opts.displayedTimezone = element.attributes["data-displayed-timezone"]; opts.format = element.attributes["data-format"]; opts.countdown = element.attributes["data-countdown"]; + opts.range = element.attributes["data-range"]; return opts; } @@ -189,7 +213,11 @@ function initializeDiscourseLocalDates(api) { this.metadata.discourseLocalDateStartRangeOpts = null; return ""; } - if (this.element.attributes["data-range"] === "true") { + if ( + this.element.attributes["data-range"] === "true" || + this.element.attributes["data-range"] === "from" || + this.element.attributes["data-range"] === "to" + ) { this.metadata.discourseLocalDateStartRangeOpts = buildOptionsFromMarkdownTag(this.element); return ""; diff --git a/plugins/discourse-local-dates/assets/javascripts/lib/discourse-markdown/discourse-local-dates.js b/plugins/discourse-local-dates/assets/javascripts/lib/discourse-markdown/discourse-local-dates.js index 945ed5845a0..e85e26a15b1 100644 --- a/plugins/discourse-local-dates/assets/javascripts/lib/discourse-markdown/discourse-local-dates.js +++ b/plugins/discourse-local-dates/assets/javascripts/lib/discourse-markdown/discourse-local-dates.js @@ -47,7 +47,7 @@ function addSingleLocalDate(buffer, state, config) { ]); } if (config.range) { - token.attrs.push(["data-range", true]); + token.attrs.push(["data-range", config.range]); } if ( @@ -152,12 +152,12 @@ function addLocalRange(buffer, matches, state) { config.timezones = parsed.attrs.timezones; config.displayedTimezone = parsed.attrs.displayedTimezone; config.countdown = parsed.attrs.countdown; - config.range = parsed.attrs.from && parsed.attrs.to; if (parsed.attrs.from) { [date, time] = parsed.attrs.from.split("T"); config.date = date; config.time = time; + config.range = "from"; addSingleLocalDate(buffer, state, config); } if (config.range) { @@ -167,6 +167,7 @@ function addLocalRange(buffer, matches, state) { [date, time] = parsed.attrs.to.split("T"); config.date = date; config.time = time; + config.range = "to"; addSingleLocalDate(buffer, state, config); } } diff --git a/plugins/discourse-local-dates/assets/javascripts/lib/local-date-builder.js b/plugins/discourse-local-dates/assets/javascripts/lib/local-date-builder.js index 2196eabaab9..352ecd09b93 100644 --- a/plugins/discourse-local-dates/assets/javascripts/lib/local-date-builder.js +++ b/plugins/discourse-local-dates/assets/javascripts/lib/local-date-builder.js @@ -16,6 +16,7 @@ export default class LocalDateBuilder { this.time = params.time; this.date = params.date; this.recurring = params.recurring; + this.sameLocalDayAsFrom = params.sameLocalDayAsFrom; this.timezones = Array.from( new Set((params.timezones || []).filter(Boolean)) ); @@ -233,6 +234,10 @@ export default class LocalDateBuilder { localDate.add(1, "day").datetime.endOf("day") ); + if (this.sameLocalDayAsFrom) { + return this._timeOnlyFormat(localDate, displayedTimezone); + } + if (inCalendarRange && sameTimezone) { const date = localDate.datetimeWithZone(this.localTimezone); @@ -293,4 +298,8 @@ export default class LocalDateBuilder { .format(format); return `${formatted} (${this._zoneWithoutPrefix(displayedTimezone)})`; } + + _timeOnlyFormat(localTime, displayedTimezone) { + return this._formatWithZone(localTime, displayedTimezone, "LT"); + } } diff --git a/plugins/discourse-local-dates/spec/integration/local_dates_spec.rb b/plugins/discourse-local-dates/spec/integration/local_dates_spec.rb index 6d4425660e1..2889d41fb42 100644 --- a/plugins/discourse-local-dates/spec/integration/local_dates_spec.rb +++ b/plugins/discourse-local-dates/spec/integration/local_dates_spec.rb @@ -91,7 +91,8 @@ RSpec.describe "Local Dates" do cooked = Fabricate(:post, raw: raw).cooked expect(cooked).to include('data-date="2022-01-06') - expect(cooked).to include('data-range="true"') + expect(cooked).to include('data-range="from"') + expect(cooked).to include('data-range="to"') expect(cooked).not_to include('data-time=') end @@ -100,7 +101,8 @@ RSpec.describe "Local Dates" do cooked = Fabricate(:post, raw: raw).cooked expect(cooked).to include('data-date="2022-01-06') - expect(cooked).to include('data-range="true"') + expect(cooked).to include('data-range="to"') + expect(cooked).to include('data-range="from"') expect(cooked).to include('data-time="13:00"') expect(cooked).to include('data-timezone="Australia/Sydney"') end @@ -111,7 +113,7 @@ RSpec.describe "Local Dates" do expect(cooked).to include('data-date="2022-01-06') expect(cooked).to include('data-time="13:00"') - expect(cooked).not_to include('data-range=') + expect(cooked).not_to include('data-range="to"') end end end diff --git a/plugins/discourse-local-dates/test/javascripts/lib/local-date-builder-test.js b/plugins/discourse-local-dates/test/javascripts/lib/local-date-builder-test.js index 8f73b151520..5a640c476de 100644 --- a/plugins/discourse-local-dates/test/javascripts/lib/local-date-builder-test.js +++ b/plugins/discourse-local-dates/test/javascripts/lib/local-date-builder-test.js @@ -86,6 +86,20 @@ module("lib:local-date-builder", function () { ); }); + test("time", function (assert) { + assert.buildsCorrectDate( + { + "time": "12:22:00", + "date": "2022-10-07", + "timezone": "Asia/Singapore", + "localTimezone": "Asia/Singapore", + "sameLocalDayAsFrom": true + }, + { formatted: "12:22 PM (Singapore)" }, + "it displays the time only as the date is the same local day as 'from'" + ); + }); + test("option[format]", function (assert) { freezeTime({ date: "2020-03-11" }, () => { assert.buildsCorrectDate(