From f15b57781a3b859e2fa7d9a5f6925729109bbc9a Mon Sep 17 00:00:00 2001 From: Josh Larson Date: Thu, 9 Jan 2025 11:47:55 -0500 Subject: [PATCH 1/5] feat: Add module that retrieves system-status relevant alerts --- lib/dotcom/system_status.ex | 23 +++ lib/dotcom/system_status/alerts.ex | 29 ++++ lib/dotcom_web/live/admin.ex | 5 + lib/dotcom_web/live/system_status.ex | 35 +++++ lib/dotcom_web/router.ex | 9 ++ test/dotcom/system_status/alerts_test.exs | 177 ++++++++++++++++++++++ 6 files changed, 278 insertions(+) create mode 100644 lib/dotcom/system_status.ex create mode 100644 lib/dotcom/system_status/alerts.ex create mode 100644 lib/dotcom_web/live/system_status.ex create mode 100644 test/dotcom/system_status/alerts_test.exs diff --git a/lib/dotcom/system_status.ex b/lib/dotcom/system_status.ex new file mode 100644 index 0000000000..d1e5122655 --- /dev/null +++ b/lib/dotcom/system_status.ex @@ -0,0 +1,23 @@ +defmodule Dotcom.SystemStatus do + alias Dotcom.SystemStatus + + def subway_alerts_for_today() do + subway_alerts_for_today(Timex.now()) + end + + def subway_alerts_for_today(now) do + [ + "Red", + "Orange", + "Blue", + "Green-B", + "Green-C", + "Green-D", + "Green-E", + "Mattapan" + ] + |> Alerts.Repo.by_route_ids(now) + |> SystemStatus.Alerts.for_today(now) + |> SystemStatus.Alerts.filter_relevant() + end +end diff --git a/lib/dotcom/system_status/alerts.ex b/lib/dotcom/system_status/alerts.ex new file mode 100644 index 0000000000..394632f2af --- /dev/null +++ b/lib/dotcom/system_status/alerts.ex @@ -0,0 +1,29 @@ +defmodule Dotcom.SystemStatus.Alerts do + @relevant_effects [:delay, :shuttle, :suspension, :station_closure] + + defp has_started?(active_period_start, now) do + now |> Timex.end_of_day() |> Timex.after?(active_period_start) + end + + defp has_not_ended?(nil, _now) do + true + end + + defp has_not_ended?(active_period_end, now) do + now |> Timex.before?(active_period_end) + end + + def active_today?(alert, now) do + Enum.any?(alert.active_period, fn {active_period_start, active_period_end} -> + has_started?(active_period_start, now) && has_not_ended?(active_period_end, now) + end) + end + + def for_today(alerts, now) do + Enum.filter(alerts, &active_today?(&1, now)) + end + + def filter_relevant(alerts) do + alerts |> Enum.filter(fn %{effect: effect} -> effect in @relevant_effects end) + end +end diff --git a/lib/dotcom_web/live/admin.ex b/lib/dotcom_web/live/admin.ex index 572b4a0c8a..b14b290b56 100644 --- a/lib/dotcom_web/live/admin.ex +++ b/lib/dotcom_web/live/admin.ex @@ -16,6 +16,11 @@ defmodule DotcomWeb.Live.Admin do url: Helpers.live_path(socket, DotcomWeb.Live.TripPlanner), title: "Trip Planner Preview", description: "WIP on the trip planner rewrite." + }, + %{ + url: Helpers.live_path(socket, DotcomWeb.Live.SystemStatus), + title: "System Status Widget Preview", + description: "WIP on the system status widget." } ] )} diff --git a/lib/dotcom_web/live/system_status.ex b/lib/dotcom_web/live/system_status.ex new file mode 100644 index 0000000000..8e7457ca9e --- /dev/null +++ b/lib/dotcom_web/live/system_status.ex @@ -0,0 +1,35 @@ +defmodule DotcomWeb.Live.SystemStatus do + @moduledoc """ + A temporary LiveView for showing off the system status widget until we + put it into the homepage (and elsewhere). + """ + + alias Dotcom.SystemStatus + use DotcomWeb, :live_view + + def render(assigns) do + assigns = + assigns + |> assign(:alerts, SystemStatus.subway_alerts_for_today()) + + ~H""" +
+ <.alert :for={alert <- @alerts} alert={alert} /> +
+ """ + end + + defp alert(assigns) do + ~H""" +
+ + {@alert.severity} {@alert.effect}: {@alert.header} + +
+ Raw alert +
{inspect(@alert, pretty: true)}
+
+
+ """ + end +end diff --git a/lib/dotcom_web/router.ex b/lib/dotcom_web/router.ex index f693dccf6e..1fadd9a87b 100644 --- a/lib/dotcom_web/router.ex +++ b/lib/dotcom_web/router.ex @@ -274,6 +274,15 @@ defmodule DotcomWeb.Router do end end + scope "/preview", DotcomWeb do + import Phoenix.LiveView.Router + pipe_through([:browser, :browser_live, :basic_auth_readonly]) + + live_session :system_status, layout: {DotcomWeb.LayoutView, :preview} do + live "/system-status", Live.SystemStatus + end + end + scope "/api", DotcomWeb do pipe_through([:secure, :browser]) diff --git a/test/dotcom/system_status/alerts_test.exs b/test/dotcom/system_status/alerts_test.exs new file mode 100644 index 0000000000..11ac92090d --- /dev/null +++ b/test/dotcom/system_status/alerts_test.exs @@ -0,0 +1,177 @@ +defmodule Dotcom.SystemStatus.AlertsTest do + use ExUnit.Case, async: true + + import Test.Support.Factories.Alerts.Alert + + alias Dotcom.SystemStatus.Alerts + + defp local_datetime(naive) do + DateTime.from_naive!(naive, "America/New_York") + end + + describe "active_today?/2" do + test "returns true if the alert is currently active" do + assert Alerts.active_today?( + build(:alert, + active_period: [ + { + local_datetime(~N[2025-01-09 12:00:00]), + local_datetime(~N[2025-01-09 20:00:00]) + } + ] + ), + local_datetime(~N[2025-01-09 13:00:00]) + ) + end + + test "returns false if the alert starts after end-of-service" do + refute Alerts.active_today?( + build(:alert, + active_period: [ + { + local_datetime(~N[2025-01-10 12:00:00]), + local_datetime(~N[2025-01-10 20:00:00]) + } + ] + ), + local_datetime(~N[2025-01-09 13:00:00]) + ) + end + + test "returns true if the alert starts later, but before end-of-service" do + assert Alerts.active_today?( + build(:alert, + active_period: [ + { + local_datetime(~N[2025-01-09 20:00:00]), + local_datetime(~N[2025-01-10 20:00:00]) + } + ] + ), + local_datetime(~N[2025-01-09 13:00:00]) + ) + end + + test "returns false if the alert has already ended" do + refute Alerts.active_today?( + build(:alert, + active_period: [ + { + local_datetime(~N[2025-01-09 10:00:00]), + local_datetime(~N[2025-01-09 12:00:00]) + } + ] + ), + local_datetime(~N[2025-01-09 13:00:00]) + ) + end + + test "returns true if the alert has no end time" do + alert = + build(:alert, + active_period: [ + { + local_datetime(~N[2025-01-09 10:00:00]), + nil + } + ] + ) + + assert Alerts.active_today?( + alert, + local_datetime(~N[2025-01-09 13:00:00]) + ) + end + + test "returns false if the alert has no end time but hasn't started yet" do + refute Alerts.active_today?( + build(:alert, + active_period: [ + { + local_datetime(~N[2025-01-10 10:00:00]), + nil + } + ] + ), + local_datetime(~N[2025-01-09 13:00:00]) + ) + end + + test "returns true if a later part of the alert's active period is active" do + assert Alerts.active_today?( + build(:alert, + active_period: [ + { + local_datetime(~N[2025-01-08 10:00:00]), + local_datetime(~N[2025-01-08 12:00:00]) + }, + { + local_datetime(~N[2025-01-09 10:00:00]), + local_datetime(~N[2025-01-09 12:00:00]) + } + ] + ), + local_datetime(~N[2025-01-09 11:00:00]) + ) + end + end + + describe "for_today/2" do + test "includes alerts that are active today" do + alert1 = + build(:alert, + active_period: [ + { + local_datetime(~N[2025-01-09 12:00:00]), + local_datetime(~N[2025-01-09 20:00:00]) + } + ] + ) + + alert2 = + build(:alert, + active_period: [ + { + local_datetime(~N[2025-01-10 12:00:00]), + local_datetime(~N[2025-01-10 20:00:00]) + } + ] + ) + + assert Alerts.for_today( + [alert1, alert2], + local_datetime(~N[2025-01-09 13:00:00]) + ) == [alert1] + end + end + + describe "filter_relevant/1" do + test "includes an alert if its effect is :delay" do + alert = build(:alert, effect: :delay) + assert Alerts.filter_relevant([alert]) == [alert] + end + + test "includes an alert if its effect is :shuttle" do + alert = build(:alert, effect: :shuttle) + assert Alerts.filter_relevant([alert]) == [alert] + end + + test "includes an alert if its effect is :suspension" do + alert = build(:alert, effect: :suspension) + assert Alerts.filter_relevant([alert]) == [alert] + end + + test "includes an alert if its effect is :station_closure" do + alert = build(:alert, effect: :station_closure) + assert Alerts.filter_relevant([alert]) == [alert] + end + + test "does not include alerts with other effects" do + assert Alerts.filter_relevant([ + build(:alert, effect: :policy_change), + build(:alert, effect: :extra_service), + build(:alert, effect: :stop_closure) + ]) == [] + end + end +end From cfd69f44db5addab31d51715948ea6c0b87b5d6e Mon Sep 17 00:00:00 2001 From: Josh Larson Date: Tue, 14 Jan 2025 13:36:06 -0500 Subject: [PATCH 2/5] cleanup: Add docs and doctests --- lib/dotcom/system_status.ex | 11 +++- lib/dotcom/system_status/alerts.ex | 74 +++++++++++++++++++++++ test/dotcom/system_status/alerts_test.exs | 1 + 3 files changed, 85 insertions(+), 1 deletion(-) diff --git a/lib/dotcom/system_status.ex b/lib/dotcom/system_status.ex index d1e5122655..40b80c65df 100644 --- a/lib/dotcom/system_status.ex +++ b/lib/dotcom/system_status.ex @@ -1,11 +1,20 @@ defmodule Dotcom.SystemStatus do + @moduledoc """ + Parent module for the system status feature + """ + alias Dotcom.SystemStatus + @doc """ + Returns a list of alerts that satisfy the following criteria: + - They are for one of the subway or trolley lines (including Mattapan), and + - They are either currently active, or will be later today + """ def subway_alerts_for_today() do subway_alerts_for_today(Timex.now()) end - def subway_alerts_for_today(now) do + defp subway_alerts_for_today(now) do [ "Red", "Orange", diff --git a/lib/dotcom/system_status/alerts.ex b/lib/dotcom/system_status/alerts.ex index 394632f2af..6e8762dac6 100644 --- a/lib/dotcom/system_status/alerts.ex +++ b/lib/dotcom/system_status/alerts.ex @@ -1,4 +1,9 @@ defmodule Dotcom.SystemStatus.Alerts do + @moduledoc """ + A utility module intended to filter alerts for the system status feature, + relying on some specific criteria that are specific enough that they don't + belong in the main `Alerts` module. + """ @relevant_effects [:delay, :shuttle, :suspension, :station_closure] defp has_started?(active_period_start, now) do @@ -13,16 +18,85 @@ defmodule Dotcom.SystemStatus.Alerts do now |> Timex.before?(active_period_end) end + @doc """ + Checks to see whether an alert is active at some point later today, possibly including + `now`. + + Returns `true` if + - The alert is currently active + - The alert will become active later in the day + + ## Example (Currently Active) + iex> now = Timex.to_datetime(~N[2025-01-05 14:00:00], "America/New_York") + iex> one_hour_ago = Timex.to_datetime(~N[2025-01-05 13:00:00], "America/New_York") + iex> one_hour_from_now = Timex.to_datetime(~N[2025-01-05 15:00:00], "America/New_York") + iex> Dotcom.SystemStatus.Alerts.active_today?( + ...> %Alerts.Alert{active_period: [{one_hour_ago, one_hour_from_now}]}, + ...> now + ...> ) + true + + ## Example (Active Later Today) + iex> now = Timex.to_datetime(~N[2025-01-05 14:00:00], "America/New_York") + iex> one_hour_from_now = Timex.to_datetime(~N[2025-01-05 15:00:00], "America/New_York") + iex> one_day_from_now = Timex.to_datetime(~N[2025-01-06 14:00:00], "America/New_York") + iex> Dotcom.SystemStatus.Alerts.active_today?( + ...> %Alerts.Alert{active_period: [{one_hour_from_now, one_day_from_now}]}, + ...> now + ...> ) + true + + Returns `false` if the alert is not currently active, and either + - Was only active in the past (even if earlier today) + - Will next become active after the end of the day today + + ## Example (Expired) + iex> now = Timex.to_datetime(~N[2025-01-05 14:00:00], "America/New_York") + iex> two_hours_ago = Timex.to_datetime(~N[2025-01-05 12:00:00], "America/New_York") + iex> one_hour_ago = Timex.to_datetime(~N[2025-01-05 13:00:00], "America/New_York") + iex> Dotcom.SystemStatus.Alerts.active_today?( + ...> %Alerts.Alert{active_period: [{two_hours_ago, one_hour_ago}]}, + ...> now + ...> ) + false + + ## Example (Not Active Until Tomorrow) + iex> now = Timex.to_datetime(~N[2025-01-05 14:00:00], "America/New_York") + iex> one_day_from_now = Timex.to_datetime(~N[2025-01-06 14:00:00], "America/New_York") + iex> two_days_from_now = Timex.to_datetime(~N[2025-01-07 14:00:00], "America/New_York") + iex> Dotcom.SystemStatus.Alerts.active_today?( + ...> %Alerts.Alert{active_period: [{one_day_from_now, two_days_from_now}]}, + ...> now + ...> ) + false + """ def active_today?(alert, now) do Enum.any?(alert.active_period, fn {active_period_start, active_period_end} -> has_started?(active_period_start, now) && has_not_ended?(active_period_end, now) end) end + @doc """ + Given a list of alerts, filters only the ones that are active today, as defined in `&active_today?/2`. + See that function for details + """ def for_today(alerts, now) do Enum.filter(alerts, &active_today?(&1, now)) end + @doc """ + Given a list of alerts, returns only the alerts whose effects are one of + `[:delay, :shuttle, :suspension, :station_closure]`. + + ## Examples + iex> alerts = [ + ...> %Alerts.Alert{id: "include_this", effect: :delay}, + ...> %Alerts.Alert{id: "exclude_this", effect: :escalator_closure} + ...> ] + iex> Dotcom.SystemStatus.Alerts.filter_relevant(alerts) |> Enum.map(& &1.id) + ["include_this"] + } + """ def filter_relevant(alerts) do alerts |> Enum.filter(fn %{effect: effect} -> effect in @relevant_effects end) end diff --git a/test/dotcom/system_status/alerts_test.exs b/test/dotcom/system_status/alerts_test.exs index 11ac92090d..25a784eaa3 100644 --- a/test/dotcom/system_status/alerts_test.exs +++ b/test/dotcom/system_status/alerts_test.exs @@ -1,5 +1,6 @@ defmodule Dotcom.SystemStatus.AlertsTest do use ExUnit.Case, async: true + doctest Dotcom.SystemStatus.Alerts import Test.Support.Factories.Alerts.Alert From 0743c02a90b1a8f4016b6a2a2234b439bb1bfe74 Mon Sep 17 00:00:00 2001 From: Josh Larson Date: Wed, 15 Jan 2025 16:01:30 -0500 Subject: [PATCH 3/5] refactor: Rename various functions from "today" to "date", or equivalent --- lib/dotcom/system_status.ex | 8 ++++---- lib/dotcom/system_status/alerts.ex | 16 ++++++++-------- test/dotcom/system_status/alerts_test.exs | 20 ++++++++++---------- 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/lib/dotcom/system_status.ex b/lib/dotcom/system_status.ex index 40b80c65df..492e0548d4 100644 --- a/lib/dotcom/system_status.ex +++ b/lib/dotcom/system_status.ex @@ -11,10 +11,10 @@ defmodule Dotcom.SystemStatus do - They are either currently active, or will be later today """ def subway_alerts_for_today() do - subway_alerts_for_today(Timex.now()) + subway_alerts_for_day(Timex.now()) end - defp subway_alerts_for_today(now) do + defp subway_alerts_for_day(datetime) do [ "Red", "Orange", @@ -25,8 +25,8 @@ defmodule Dotcom.SystemStatus do "Green-E", "Mattapan" ] - |> Alerts.Repo.by_route_ids(now) - |> SystemStatus.Alerts.for_today(now) + |> Alerts.Repo.by_route_ids(datetime) + |> SystemStatus.Alerts.for_day(datetime) |> SystemStatus.Alerts.filter_relevant() end end diff --git a/lib/dotcom/system_status/alerts.ex b/lib/dotcom/system_status/alerts.ex index 6e8762dac6..4ac1cf6d79 100644 --- a/lib/dotcom/system_status/alerts.ex +++ b/lib/dotcom/system_status/alerts.ex @@ -30,7 +30,7 @@ defmodule Dotcom.SystemStatus.Alerts do iex> now = Timex.to_datetime(~N[2025-01-05 14:00:00], "America/New_York") iex> one_hour_ago = Timex.to_datetime(~N[2025-01-05 13:00:00], "America/New_York") iex> one_hour_from_now = Timex.to_datetime(~N[2025-01-05 15:00:00], "America/New_York") - iex> Dotcom.SystemStatus.Alerts.active_today?( + iex> Dotcom.SystemStatus.Alerts.active_on_day?( ...> %Alerts.Alert{active_period: [{one_hour_ago, one_hour_from_now}]}, ...> now ...> ) @@ -40,7 +40,7 @@ defmodule Dotcom.SystemStatus.Alerts do iex> now = Timex.to_datetime(~N[2025-01-05 14:00:00], "America/New_York") iex> one_hour_from_now = Timex.to_datetime(~N[2025-01-05 15:00:00], "America/New_York") iex> one_day_from_now = Timex.to_datetime(~N[2025-01-06 14:00:00], "America/New_York") - iex> Dotcom.SystemStatus.Alerts.active_today?( + iex> Dotcom.SystemStatus.Alerts.active_on_day?( ...> %Alerts.Alert{active_period: [{one_hour_from_now, one_day_from_now}]}, ...> now ...> ) @@ -54,7 +54,7 @@ defmodule Dotcom.SystemStatus.Alerts do iex> now = Timex.to_datetime(~N[2025-01-05 14:00:00], "America/New_York") iex> two_hours_ago = Timex.to_datetime(~N[2025-01-05 12:00:00], "America/New_York") iex> one_hour_ago = Timex.to_datetime(~N[2025-01-05 13:00:00], "America/New_York") - iex> Dotcom.SystemStatus.Alerts.active_today?( + iex> Dotcom.SystemStatus.Alerts.active_on_day?( ...> %Alerts.Alert{active_period: [{two_hours_ago, one_hour_ago}]}, ...> now ...> ) @@ -64,24 +64,24 @@ defmodule Dotcom.SystemStatus.Alerts do iex> now = Timex.to_datetime(~N[2025-01-05 14:00:00], "America/New_York") iex> one_day_from_now = Timex.to_datetime(~N[2025-01-06 14:00:00], "America/New_York") iex> two_days_from_now = Timex.to_datetime(~N[2025-01-07 14:00:00], "America/New_York") - iex> Dotcom.SystemStatus.Alerts.active_today?( + iex> Dotcom.SystemStatus.Alerts.active_on_day?( ...> %Alerts.Alert{active_period: [{one_day_from_now, two_days_from_now}]}, ...> now ...> ) false """ - def active_today?(alert, now) do + def active_on_day?(alert, now) do Enum.any?(alert.active_period, fn {active_period_start, active_period_end} -> has_started?(active_period_start, now) && has_not_ended?(active_period_end, now) end) end @doc """ - Given a list of alerts, filters only the ones that are active today, as defined in `&active_today?/2`. + Given a list of alerts, filters only the ones that are active today, as defined in `&active_on_day?/2`. See that function for details """ - def for_today(alerts, now) do - Enum.filter(alerts, &active_today?(&1, now)) + def for_day(alerts, now) do + Enum.filter(alerts, &active_on_day?(&1, now)) end @doc """ diff --git a/test/dotcom/system_status/alerts_test.exs b/test/dotcom/system_status/alerts_test.exs index 25a784eaa3..4b8570eae4 100644 --- a/test/dotcom/system_status/alerts_test.exs +++ b/test/dotcom/system_status/alerts_test.exs @@ -10,9 +10,9 @@ defmodule Dotcom.SystemStatus.AlertsTest do DateTime.from_naive!(naive, "America/New_York") end - describe "active_today?/2" do + describe "active_on_day?/2" do test "returns true if the alert is currently active" do - assert Alerts.active_today?( + assert Alerts.active_on_day?( build(:alert, active_period: [ { @@ -26,7 +26,7 @@ defmodule Dotcom.SystemStatus.AlertsTest do end test "returns false if the alert starts after end-of-service" do - refute Alerts.active_today?( + refute Alerts.active_on_day?( build(:alert, active_period: [ { @@ -40,7 +40,7 @@ defmodule Dotcom.SystemStatus.AlertsTest do end test "returns true if the alert starts later, but before end-of-service" do - assert Alerts.active_today?( + assert Alerts.active_on_day?( build(:alert, active_period: [ { @@ -54,7 +54,7 @@ defmodule Dotcom.SystemStatus.AlertsTest do end test "returns false if the alert has already ended" do - refute Alerts.active_today?( + refute Alerts.active_on_day?( build(:alert, active_period: [ { @@ -78,14 +78,14 @@ defmodule Dotcom.SystemStatus.AlertsTest do ] ) - assert Alerts.active_today?( + assert Alerts.active_on_day?( alert, local_datetime(~N[2025-01-09 13:00:00]) ) end test "returns false if the alert has no end time but hasn't started yet" do - refute Alerts.active_today?( + refute Alerts.active_on_day?( build(:alert, active_period: [ { @@ -99,7 +99,7 @@ defmodule Dotcom.SystemStatus.AlertsTest do end test "returns true if a later part of the alert's active period is active" do - assert Alerts.active_today?( + assert Alerts.active_on_day?( build(:alert, active_period: [ { @@ -117,7 +117,7 @@ defmodule Dotcom.SystemStatus.AlertsTest do end end - describe "for_today/2" do + describe "for_day/2" do test "includes alerts that are active today" do alert1 = build(:alert, @@ -139,7 +139,7 @@ defmodule Dotcom.SystemStatus.AlertsTest do ] ) - assert Alerts.for_today( + assert Alerts.for_day( [alert1, alert2], local_datetime(~N[2025-01-09 13:00:00]) ) == [alert1] From e3a428152c98e54e8dcb30ddfed80140acfa6f2d Mon Sep 17 00:00:00 2001 From: Josh Larson Date: Wed, 15 Jan 2025 16:02:08 -0500 Subject: [PATCH 4/5] Move private functions to the bottom of the file --- lib/dotcom/system_status/alerts.ex | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/lib/dotcom/system_status/alerts.ex b/lib/dotcom/system_status/alerts.ex index 4ac1cf6d79..2910180400 100644 --- a/lib/dotcom/system_status/alerts.ex +++ b/lib/dotcom/system_status/alerts.ex @@ -6,18 +6,6 @@ defmodule Dotcom.SystemStatus.Alerts do """ @relevant_effects [:delay, :shuttle, :suspension, :station_closure] - defp has_started?(active_period_start, now) do - now |> Timex.end_of_day() |> Timex.after?(active_period_start) - end - - defp has_not_ended?(nil, _now) do - true - end - - defp has_not_ended?(active_period_end, now) do - now |> Timex.before?(active_period_end) - end - @doc """ Checks to see whether an alert is active at some point later today, possibly including `now`. @@ -100,4 +88,16 @@ defmodule Dotcom.SystemStatus.Alerts do def filter_relevant(alerts) do alerts |> Enum.filter(fn %{effect: effect} -> effect in @relevant_effects end) end + + defp has_started?(active_period_start, now) do + now |> Timex.end_of_day() |> Timex.after?(active_period_start) + end + + defp has_not_ended?(nil, _now) do + true + end + + defp has_not_ended?(active_period_end, now) do + now |> Timex.before?(active_period_end) + end end From 2f0f0ec3bb88ec1ad83a72a5ecfe8e70159a22c0 Mon Sep 17 00:00:00 2001 From: Josh Larson Date: Wed, 15 Jan 2025 16:58:50 -0500 Subject: [PATCH 5/5] Rename some more variables away from `now` and add explanatory comments --- lib/dotcom/system_status/alerts.ex | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/lib/dotcom/system_status/alerts.ex b/lib/dotcom/system_status/alerts.ex index 2910180400..d92b87e483 100644 --- a/lib/dotcom/system_status/alerts.ex +++ b/lib/dotcom/system_status/alerts.ex @@ -58,9 +58,10 @@ defmodule Dotcom.SystemStatus.Alerts do ...> ) false """ - def active_on_day?(alert, now) do + def active_on_day?(alert, datetime) do Enum.any?(alert.active_period, fn {active_period_start, active_period_end} -> - has_started?(active_period_start, now) && has_not_ended?(active_period_end, now) + starts_before_end_of_day?(active_period_start, datetime) && + has_not_ended?(active_period_end, datetime) end) end @@ -68,8 +69,8 @@ defmodule Dotcom.SystemStatus.Alerts do Given a list of alerts, filters only the ones that are active today, as defined in `&active_on_day?/2`. See that function for details """ - def for_day(alerts, now) do - Enum.filter(alerts, &active_on_day?(&1, now)) + def for_day(alerts, datetime) do + Enum.filter(alerts, &active_on_day?(&1, datetime)) end @doc """ @@ -89,15 +90,17 @@ defmodule Dotcom.SystemStatus.Alerts do alerts |> Enum.filter(fn %{effect: effect} -> effect in @relevant_effects end) end - defp has_started?(active_period_start, now) do - now |> Timex.end_of_day() |> Timex.after?(active_period_start) + # Returns true if the alert (as signified by the active_period_start provided) + # starts before the end of datetime's day. + defp starts_before_end_of_day?(active_period_start, datetime) do + datetime |> Timex.end_of_day() |> Timex.after?(active_period_start) end - defp has_not_ended?(nil, _now) do - true - end + # Returns true if the alert (as signified by the active_period_end provided) + # ends before the given datetime. If active_period_end is nil, then the alert + # is indefinite, which means that it definitionally has not ended. + defp has_not_ended?(nil, _datetime), do: true - defp has_not_ended?(active_period_end, now) do - now |> Timex.before?(active_period_end) - end + defp has_not_ended?(active_period_end, datetime), + do: datetime |> Timex.before?(active_period_end) end