From 7d8cda9858d28921591960952cc8ed9a97045ffa Mon Sep 17 00:00:00 2001 From: Natalie Tay Date: Fri, 7 Oct 2022 09:39:41 +0800 Subject: [PATCH] FEATURE: Omit showing day when 'to' day is same as 'from' day (#18500) Essentially, Saturday at 2:50 PM -> Saturday at 4:38 PM becomes Saturday at 2:50 PM -> 4:38 PM (Singapore) Also, the displayed dates are shortened when the standalone date is within two days. So despite the 'from' and 'to' date being the same day, it may show 'Saturday' for 'from', and the specific date for the 'to'. This corrects the behaviour. (so if the current date and time is Thursday 5PM, the 'from' date below is within 2 days, but the 'to' date is not) Saturday at 2:50 PM -> 8 October 2022 at 9:38 PM becomes Saturday at 2:50 PM -> 9:38 PM --- .../initializers/discourse-local-dates.js | 32 +++++++++++++++++-- .../discourse-local-dates.js | 5 +-- .../javascripts/lib/local-date-builder.js | 9 ++++++ .../spec/integration/local_dates_spec.rb | 8 +++-- .../lib/local-date-builder-test.js | 14 ++++++++ 5 files changed, 61 insertions(+), 7 deletions(-) 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(