Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions app/assets/stylesheets/events/new/index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,9 @@
max-width: 270px;
}

.timezone-select {
margin: 0 auto;
max-width: 350px;
}

.location-step .fieldsLayout--two { margin: 0 30px; }
20 changes: 11 additions & 9 deletions app/controllers/events_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,19 +29,21 @@ def show
end

def create
Time.use_zone(params[:event][:timezone] || current_nonprofit.timezone) do
params[:event][:start_datetime] = Chronic.parse(params[:event][:start_datetime]) if params[:event][:start_datetime].present?
params[:event][:end_datetime] = Chronic.parse(params[:event][:end_datetime]) if params[:event][:end_datetime].present?
end
event = current_nonprofit.events.create(params[:event])

render_json do
Time.use_zone(current_nonprofit.timezone || "UTC") do
params[:event][:start_datetime] = Chronic.parse(params[:event][:start_datetime]) if params[:event][:start_datetime].present?
params[:event][:end_datetime] = Chronic.parse(params[:event][:end_datetime]) if params[:event][:end_datetime].present?
end
flash[:notice] = "Your draft event has been created! Well done."
ev = current_nonprofit.events.create(params[:event])
{url: "/events/#{ev.slug}", event: ev}
flash[:notice] = "Your draft event has been created! Well done." if event.persisted?

{ url: "/events/#{event.slug}", event: }
end
end

def update
Time.use_zone(current_nonprofit.timezone || "UTC") do
Time.use_zone(current_event.timezone) do
params[:event][:start_datetime] = Chronic.parse(params[:event][:start_datetime]) if params[:event][:start_datetime].present?
params[:event][:end_datetime] = Chronic.parse(params[:event][:end_datetime]) if params[:event][:end_datetime].present?
end
Expand Down Expand Up @@ -75,6 +77,6 @@ def stats
end

def name_and_id
@events = current_nonprofit.events.not_deleted.order("events.name ASC")
@events = current_nonprofit.events.not_deleted.order("events.name ASC").select(:name, :id)
end
end
4 changes: 4 additions & 0 deletions app/legacy_lib/format/date.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,9 @@ def self.time(datetime, timezone = nil)
datetime = datetime.in_time_zone(timezone) if timezone
datetime.strftime("%l:%M%P")
end

def self.timezone(timezone)
Time.now.in_time_zone(timezone).strftime('%Z')
end
end
end
3 changes: 2 additions & 1 deletion app/legacy_lib/query_event_metrics.rb
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ def self.for_listings(id_type, id, params)
"events.start_datetime",
"events.end_datetime",
"events.organizer_email",
"events.in_person_or_virtual"
"events.in_person_or_virtual",
"events.timezone"
]

exp = QueryEventMetrics.expression(selects)
Expand Down
9 changes: 8 additions & 1 deletion app/models/event.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ class Event < ApplicationRecord
:organizer_email, # string
:receipt_message, # text
:nonprofit,
:in_person_or_virtual
:in_person_or_virtual,
:timezone # string (timezone): event time zone if different from nonprofit timezone

enum :in_person_or_virtual, %w[in_person virtual].index_by(&:itself), validate: true

Expand Down Expand Up @@ -87,6 +88,8 @@ class Event < ApplicationRecord
end
self.published = false if published.nil?
self.total_raised ||= 0
self.timezone = nonprofit_timezone || "UTC"

self
end

Expand Down Expand Up @@ -123,4 +126,8 @@ def fee_coverage_option
def get_tickets_button_label
misc_event_info&.custom_get_tickets_button_label || "Get Tickets"
end

def timezone_with_fallback
timezone.presence || nonprofit_timezone
end
end
2 changes: 1 addition & 1 deletion app/views/events/_date_time.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<header>Date &amp; Time</header>
<div class='pastelBox-body'>
<h5 class='strong u-marginBottom--0'>
<%= Format::Date.full_range(@event.start_datetime, @event.end_datetime, @event.nonprofit_timezone) %>
<%= Format::Date.full_range(@event.start_datetime, @event.end_datetime, @event.timezone_with_fallback) %> <%= Format::Date.timezone(@event.timezone_with_fallback) %>
</h5>

<% if Time.now > @event.end_datetime %>
Expand Down
10 changes: 9 additions & 1 deletion app/views/events/_edit_form.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,12 @@

<hr>

<section class='layout--four'>
<section class='layout--four u-padding--8'>
<fieldset>
<label>Organizer Contact Email</label>
<input type='text' name='event[organizer_email]' value='<%= @event.organizer_email || @organizer['email'] %>'>
</fieldset>

<fieldset>
<label>Start Date & Time</label>
<div pikaday-timepicker='MM/DD/YYYY hh:mm a'>
Expand All @@ -37,6 +38,13 @@
<a class='button edit u-inlineBlock'>Set</a>
</div>
</fieldset>

<fieldset class="timezone-select">
<label>Timezone</label>
<div>
<%= select(:event, :timezone, time_zone_options_with_iana(@event.timezone), include_blank: 'Select Timezone') %>
</div>
</fieldset>
</section>

<hr>
Expand Down
7 changes: 4 additions & 3 deletions app/views/events/_listing.html.erb
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
<%- # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -%>
<% css = 'fundraiser--active' if css.nil? %>
<section class='events <%= css %>'>
<section class='<%= class_names('events', 'fundraiser--active' => css.nil? ) %>'>
<div class='event-date'>
<p> <%= Format::Date.full_range(event.start_datetime, event.end_datetime, event.nonprofit_timezone) %> </p>
<p>
<%= Format::Date.full_range(event.start_datetime, event.end_datetime, event.timezone_with_fallback) %> <%= Format::Date.timezone(event.timezone_with_fallback) %>
</p>
</div>
<a href='<%= event.url %>'>
<article class='event-text'>
Expand Down
39 changes: 23 additions & 16 deletions app/views/events/_new_modal.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -44,32 +44,39 @@
<div class='wizard-step dates-step' style='display: block;'>
<!--= wizard.set_step 'new_event_wiz' 'Dates' -->

<form parsley-validate class='dates-fields u-centered'>
<form parsley-validate class='u-centered'>
<!--= on 'submit' (def 'new_event' form_object) (wizard.advance 'new_event_wiz') -->

<fieldset class='group'>
<label class='u-floatL'>Start Date & Time</label>
<div pikaday-timepicker='MM/DD/YYYY hh:mm a'>
<input class='u-width--200 u-bold u-inlineBlock' apply-pikaday-time='MM/DD/YYYY hh:mm a' type='text' name='event[start_datetime]' required parsley-trigger='change' placeholder='MM/DD/YYYY HH:MM'>
<a class='button edit u-inlineBlock'>Set</a>
</div>
</fieldset>
<div class="dates-fields">
<fieldset class='group'>
<label class='u-floatL'>Start Date & Time</label>
<div pikaday-timepicker='MM/DD/YYYY hh:mm a'>
<input class='u-width--200 u-bold u-inlineBlock' apply-pikaday-time='MM/DD/YYYY hh:mm a' type='text' name='event[start_datetime]' required parsley-trigger='change' placeholder='MM/DD/YYYY HH:MM'>
<a class='button edit u-inlineBlock'>Set</a>
</div>
</fieldset>

<fieldset class='group u-marginBottom--15 u-relative'>
<label class='u-floatL'>End Date & Time:</label>
<div pikaday-timepicker='MM/DD/YYYY hh:mm a'>
<input class='u-width--200 u-bold u-inlineBlock' type='text' name='event[end_datetime]' required parsley-trigger='change' placeholder='MM/DD/YYYY HH:MM'>
<a class='button edit u-inlineBlock'>Set</a>
</div>
<fieldset class='group'>
<label class='u-floatL'>End Date & Time:</label>
<div pikaday-timepicker='MM/DD/YYYY hh:mm a'>
<input class='u-width--200 u-bold u-inlineBlock' type='text' name='event[end_datetime]' required parsley-trigger='change' placeholder='MM/DD/YYYY HH:MM'>
<a class='button edit u-inlineBlock'>Set</a>
</div>
</fieldset>
</div>

<fieldset class='group timezone-select u-marginBottom--15 u-relative'>
<label>Timezone</label>
<div>
<%= select(:event, :timezone, time_zone_options_with_iana(@nonprofit.timezone), include_blank: 'Select Timezone', class: 'u-bold') %>
</div>
</fieldset>

<%= render 'components/forms/submit_button', button_text: 'Next', scope: 'new_event_wiz', branded: true %>

</form>
</div><!-- .dates-step -->



<div class='wizard-step location-step'>
<!--= wizard.set_step 'new_event_wiz' 'Location' -->

Expand Down
8 changes: 4 additions & 4 deletions client/js/events/listing-item/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ const h = require('snabbdom/h')
const moment = require('moment-timezone')
const {commaJoin} = require('./common');

const dateTime = (startTime, endTime) => {
const tz = ENV.nonprofitTimezone || 'America/Los_Angeles'
const dateTime = (startTime, endTime, timeZone) => {
const tz = timeZone || ENV.nonprofitTimezone || 'America/Los_Angeles'
startTime = moment(startTime).tz(tz)
endTime = moment(endTime).tz(tz)
const sameDate = startTime.format("YYYY-MM-DD") === endTime.format("YYYY-MM-DD")
Expand All @@ -14,7 +14,7 @@ const dateTime = (startTime, endTime) => {
const endTimeFormatted = sameDate ? endTime.format("h:mma") : endTime.format(format)

return [
h('strong', startTime.format(format) + ' - ' + endTimeFormatted)
h('strong', startTime.format(format) + ' - ' + endTimeFormatted + ' ' + moment.tz(tz).zoneAbbr())
, h('span.u-color--grey', ended)
]
}
Expand Down Expand Up @@ -67,7 +67,7 @@ module.exports = e => {
return h('div.u-paddingTop--10.u-marginBottom--20', [
h('h5.u-paddingX--20', e.name)
, h('table.table--striped.u-margin--0', [
row('fa-clock-o', dateTime(e.start_datetime, e.end_datetime))
row('fa-clock-o', dateTime(e.start_datetime, e.end_datetime, e.timezone))
, row('fa-map-marker', location)
, row('fa-users', attendeesMetrics)
, row('fa-dollar', moneyMetrics)
Expand Down
7 changes: 7 additions & 0 deletions db/migrate/20250910231648_add_timezone_to_events.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
class AddTimezoneToEvents < ActiveRecord::Migration[7.1]
def change
change_table :events do |t|
t.string :timezone
end
end
end
3 changes: 2 additions & 1 deletion db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema[7.1].define(version: 2025_08_26_154514) do
ActiveRecord::Schema[7.1].define(version: 2025_09_10_231648) do
# These are extensions that must be enabled in order to support this database
enable_extension "pg_stat_statements"
enable_extension "plpgsql"
Expand Down Expand Up @@ -383,6 +383,7 @@
t.datetime "start_datetime", precision: nil
t.datetime "end_datetime", precision: nil
t.string "in_person_or_virtual", default: "in_person", comment: "whether or not this is a virtual event"
t.string "timezone"
t.index ["in_person_or_virtual"], name: "index_events_on_in_person_or_virtual"
t.index ["nonprofit_id", "deleted", "published", "end_datetime"], name: "events_nonprofit_id_not_deleted_and_published_endtime"
t.index ["nonprofit_id", "deleted", "published"], name: "index_events_on_nonprofit_id_and_deleted_and_published"
Expand Down
10 changes: 6 additions & 4 deletions spec/lib/insert/insert_duplicate_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,8 @@ def set_event_start_time(start_time, end_time)
{
id: result.id,
start_datetime: DateTime.new(2020, 5, 12),
end_datetime: DateTime.new(2020, 5, 12, 4)
end_datetime: DateTime.new(2020, 5, 12, 4),
timezone: "UTC"
}
).with_indifferent_access)
validate_tls(result)
Expand All @@ -301,9 +302,9 @@ def set_event_start_time(start_time, end_time)
expect(result.attributes.with_indifferent_access).to eq(common_result_attributes.merge(
{
id: result.id,

start_datetime: Time.utc(2020, 5, 12),
end_datetime: Time.utc(2020, 5, 12, 4)
end_datetime: Time.utc(2020, 5, 12, 4),
timezone: "UTC"

}
).with_indifferent_access)
Expand All @@ -323,7 +324,8 @@ def set_event_start_time(start_time, end_time)
{
id: result.id,
start_datetime: event.start_datetime.to_time,
end_datetime: event.end_datetime.to_time
end_datetime: event.end_datetime.to_time,
timezone: "UTC"
}
).with_indifferent_access)
validate_tls(result)
Expand Down
15 changes: 15 additions & 0 deletions spec/models/event_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
require "rails_helper"

RSpec.describe Event, type: :model do
it { is_expected.to belong_to(:nonprofit) }
it { is_expected.to have_many(:ticketholders).through(:tickets).source(:supporter) }
it { is_expected.to define_enum_for(:in_person_or_virtual).with_values(%w[in_person virtual].index_by(&:itself)).backed_by_column_of_type(:string).validating }
it { is_expected.to delegate_method(:timezone).to(:nonprofit).with_prefix.allow_nil }
Expand All @@ -18,4 +19,18 @@
it { is_expected.to_not validate_presence_of(:state_code) }
end
end

describe "#timezone_with_fallback" do
let(:nonprofit) { create(:nonprofit_base, timezone: 'America/Los_Angeles') }
let(:event) { create(:event_base, nonprofit:, timezone: 'America/Central') }
let(:event_without_timezone) { create(:event_base, nonprofit:) }

it "returns the event timezone with priority" do
expect(event.timezone_with_fallback).to eq('America/Central')
end

it "returns the nonprofit timezone if event timezone is not set" do
expect(event_without_timezone.timezone_with_fallback).to eq(nonprofit.timezone)
end
end
end
Loading
Loading