FEATURE: show local timezone (#735)

When set to true `showLocalTime` will display the event dates using the timezone of the event. It's useful for local events and you have people looking at this event from a different timezone.

![Screenshot 2025-06-02 at 21 51 20](https://github.com/user-attachments/assets/cce939a0-37b6-4ad7-8688-21b25d360090)
This commit is contained in:
Joffrey JAFFEUX 2025-06-02 22:52:27 +02:00 committed by GitHub
parent 426c855e75
commit ae015fd694
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 87 additions and 14 deletions

View File

@ -312,6 +312,7 @@ module DiscoursePostEvent
recurrence: event_params[:recurrence],
recurrence_until: parsed_recurrence_until,
timezone: event_params[:timezone],
show_local_time: event_params[:"show-local-time"] == "true",
status: Event.statuses[event_params[:status]&.to_sym] || event.status,
reminders: event_params[:reminders],
raw_invitees: event_params[:"allowed-groups"]&.split(","),
@ -416,7 +417,6 @@ end
# original_starts_at :datetime not null
# original_ends_at :datetime
# deleted_at :datetime
# recurrence_until :datetime
# raw_invitees :string is an Array
# name :string
# url :string(1000)
@ -428,4 +428,6 @@ end
# closed :boolean default(FALSE), not null
# chat_enabled :boolean default(FALSE), not null
# chat_channel_id :bigint
# recurrence_until :datetime
# show_local_time :boolean default(FALSE), not null
#

View File

@ -29,6 +29,7 @@ module DiscoursePostEvent
attributes :stats
attributes :status
attributes :timezone
attributes :show_local_time
attributes :url
attributes :watching_invitee
attributes :chat_enabled

View File

@ -36,23 +36,34 @@ export default class DiscoursePostEventDates extends Component {
get datesBBCode() {
const dates = [];
dates.push(
`[date=${this.startsAt.format("YYYY-MM-DD")} time=${this.startsAt.format(
"HH:mm"
)} format=${this.format} timezone=${this.timezone}]`
);
dates.push(this.buildDateBBCode(this.startsAt));
if (this.endsAt) {
dates.push(
`[date=${this.endsAt.format("YYYY-MM-DD")} time=${this.endsAt.format(
"HH:mm"
)} format=${this.format} timezone=${this.timezone}]`
);
dates.push(this.buildDateBBCode(this.endsAt));
}
return dates;
}
buildDateBBCode(date) {
const bbcode = {
date: date.format("YYYY-MM-DD"),
time: date.format("HH:mm"),
format: this.format,
timezone: this.timezone,
};
if (this.args.event.showLocalTime) {
bbcode.displayedTimezone = this.args.event.timezone;
}
const content = Object.entries(bbcode)
.map(([key, value]) => `${key}=${value}`)
.join(" ");
return `[${content}]`;
}
@action
async computeDates(element) {
if (this.siteSettings.discourse_local_dates_enabled) {

View File

@ -62,6 +62,21 @@
/>
</EventField>
<EventField
class="show-local-time"
@label="discourse_post_event.builder_modal.show_local_time.label"
>
<label class="checkbox-label">
<Input @type="checkbox" @checked={{@model.event.showLocalTime}} />
<span class="message">
{{i18n
"discourse_post_event.builder_modal.show_local_time.description"
timezone=@model.event.timezone
}}
</span>
</label>
</EventField>
<EventField @label="discourse_post_event.builder_modal.status.label">
<label class="radio-label">
<RadioButton

View File

@ -279,7 +279,6 @@ export default class PostEventBuilder extends Component {
this.event,
this.siteSettings
);
const newRaw = replaceRaw(eventParams, raw);
if (newRaw) {
const props = {

View File

@ -33,7 +33,10 @@ export function buildParams(startsAt, endsAt, event, siteSettings) {
params.recurrenceUntil = moment(event.recurrenceUntil)
.tz(eventTz)
.format("YYYY-MM-DD HH:mm");
moment(startsAt).tz(eventTz).format("YYYY-MM-DD HH:mm");
}
if (event.showLocalTime) {
params.showLocalTime = "true";
}
if (event.minimal) {

View File

@ -31,6 +31,7 @@ export default class DiscoursePostEventEvent {
@tracked rawInvitees;
@tracked url;
@tracked timezone;
@tracked showLocalTime;
@tracked status;
@tracked post;
@tracked minimal;
@ -64,6 +65,7 @@ export default class DiscoursePostEventEvent {
this.sampleInvitees = args.sample_invitees || [];
this.url = args.url;
this.timezone = args.timezone;
this.showLocalTime = args.show_local_time;
this.status = args.status;
this.creator = args.creator;
this.post = args.post;
@ -145,6 +147,7 @@ export default class DiscoursePostEventEvent {
this.endsAt = event.endsAt;
this.url = event.url;
this.timezone = event.timezone;
this.showLocalTime = event.showLocalTime;
this.status = event.status;
this.creator = event.creator;
this.isClosed = event.isClosed;

View File

@ -11,6 +11,7 @@ const EVENT_ATTRIBUTES = {
closed: { default: null },
status: { default: "public" },
timezone: { default: "UTC" },
showLocalTime: { default: null },
allowedGroups: { default: null },
recurrence: { default: null },
recurrenceUntil: { default: null },

View File

@ -171,7 +171,7 @@
flex-direction: column;
.description {
color: var(--primary-medium);
font-weight: normal;
}
}
}

View File

@ -432,6 +432,9 @@ en:
update: "Save"
attach: "Create event"
add_reminder: "Add reminder"
show_local_time:
label: "Show local time"
description: "Dates and times will be displayed using: %{timezone}. Use this for events at a location, so times reflect the timezone where the event takes place."
timezone:
label: Timezone
remove_timezone: No timezone (UTC)

View File

@ -0,0 +1,7 @@
# frozen_string_literal: true
class AddShowLocalTime < ActiveRecord::Migration[7.2]
def change
add_column :discourse_post_event_events, :show_local_time, :boolean, default: false, null: false
end
end

View File

@ -13,6 +13,7 @@ module DiscoursePostEvent
:recurrence,
:"recurrence-until",
:timezone,
:"show-local-time",
:minimal,
:closed,
:"chat-enabled",

View File

@ -40,6 +40,20 @@ describe DiscoursePostEvent::EventParser do
expect(events[0][:end]).to eq("bar")
end
it "parses showLocalTime" do
events =
parser.extract_events(build_post(user, '[event start="foo" showLocalTime="true"]\n[/event]'))
expect(events[0][:"show-local-time"]).to eq("true")
end
it "parses recurrenceUntil" do
events =
parser.extract_events(
build_post(user, '[event start="foo" recurrenceUntil="2025-06-21 23:59"]\n[/event]'),
)
expect(events[0][:"recurrence-until"]).to eq("2025-06-21 23:59")
end
it "works with escaped string" do
events =
parser.extract_events(

View File

@ -29,6 +29,19 @@ describe "Post event", type: :system do
expect(page).to have_css(".event-info .name", text: "<script>alert(1);</script>")
end
it "shows local timezone" do
post =
PostCreator.create(
admin,
title: "My test meetup event",
raw: "[event timezone='Japan' showLocalTime='true' start='2222-02-22 14:22']\n[/event]",
)
visit(post.topic.url)
expect(page).to have_css(".discourse-local-date", text: "Japan")
end
it "can create, close, and open an event" do
visit "/new-topic"
title = "My upcoming l33t event"