From dae52f7605723c2f88eccb873ed7592ee7ad0964 Mon Sep 17 00:00:00 2001 From: Cristen Jones Date: Mon, 17 Jun 2024 10:19:46 -0400 Subject: [PATCH] Logan Express icons and fixes --- assets/css/_stop-bubbles.scss | 5 ++++ lib/dotcom/trip_plan/itinerary_row.ex | 17 +++++++----- lib/dotcom/trip_plan/related_link.ex | 21 +++++++++++---- lib/dotcom_web/views/helpers.ex | 12 ++++++++- .../views/partial/svg_icon_with_circle.ex | 2 ++ lib/dotcom_web/views/trip_plan_view.ex | 3 ++- lib/routes/route.ex | 8 +++--- lib/trip_plan/itinerary.ex | 4 ++- lib/trip_plan/transfer.ex | 17 ++++++------ lib/trip_planner/fare_passes.ex | 9 +++++++ lib/trip_planner/parser.ex | 25 +++++++++++++----- .../static/icon-svg/icon-logan-express-BB.svg | 26 +++++++++++++++++++ .../static/icon-svg/icon-logan-express-BT.svg | 26 +++++++++++++++++++ .../static/icon-svg/icon-logan-express-FH.svg | 26 +++++++++++++++++++ .../static/icon-svg/icon-logan-express-PB.svg | 26 +++++++++++++++++++ .../static/icon-svg/icon-logan-express-WO.svg | 26 +++++++++++++++++++ 16 files changed, 220 insertions(+), 33 deletions(-) create mode 100644 priv/static/icon-svg/icon-logan-express-BB.svg create mode 100644 priv/static/icon-svg/icon-logan-express-BT.svg create mode 100644 priv/static/icon-svg/icon-logan-express-FH.svg create mode 100644 priv/static/icon-svg/icon-logan-express-PB.svg create mode 100644 priv/static/icon-svg/icon-logan-express-WO.svg diff --git a/assets/css/_stop-bubbles.scss b/assets/css/_stop-bubbles.scss index ee11442be6..7f76efb0d5 100644 --- a/assets/css/_stop-bubbles.scss +++ b/assets/css/_stop-bubbles.scss @@ -298,6 +298,11 @@ $location-line-width: $space-6; @include stop-bubble-mode-color('.green-line-e', $brand-green-line); @include stop-bubble-mode-color('.bus', $brand-bus); @include stop-bubble-mode-color('.logan-express', $brand-logan-express); +@include stop-bubble-mode-color('.logan-express-FH', #ff505d); +@include stop-bubble-mode-color('.logan-express-BB', #f16823); +@include stop-bubble-mode-color('.logan-express-BT', #0055a0); +@include stop-bubble-mode-color('.logan-express-WO', #00954c); +@include stop-bubble-mode-color('.logan-express-PB', #704c9f); @include stop-bubble-mode-color('.massport-shuttle', $brand-massport-shuttle); @include stop-bubble-mode-color('.silver-line', $brand-silver-line); @include stop-bubble-mode-color('.ferry', $brand-ferry); diff --git a/lib/dotcom/trip_plan/itinerary_row.ex b/lib/dotcom/trip_plan/itinerary_row.ex index 21a7c64c0d..2d50ea4c91 100644 --- a/lib/dotcom/trip_plan/itinerary_row.ex +++ b/lib/dotcom/trip_plan/itinerary_row.ex @@ -3,7 +3,6 @@ defmodule Dotcom.TripPlan.ItineraryRow do alias Routes.Route alias Dotcom.TripPlan.IntermediateStop - alias OpenTripPlannerClient.Schema alias TripPlan.{Leg, NamedPosition, PersonalDetail, TransitDetail} alias TripPlan.PersonalDetail.Step @@ -55,6 +54,10 @@ defmodule Dotcom.TripPlan.ItineraryRow do def route_type(%__MODULE__{route: %Route{type: type}}), do: type def route_type(_row), do: nil + def route_name(%__MODULE__{route: %Route{external_agency_name: agency, long_name: name}}) + when is_binary(agency) and is_binary(name), + do: name + def route_name(%__MODULE__{route: %Route{custom_route?: true, long_name: name}}), do: name def route_name(%__MODULE__{route: %Route{name: name}}), do: name def route_name(_row), do: nil @@ -64,9 +67,12 @@ defmodule Dotcom.TripPlan.ItineraryRow do """ @spec from_leg(Leg.t(), Leg.t() | nil) :: t def from_leg(leg, next_leg) do - trip = leg |> Leg.trip_id() |> parse_trip_id() transit? = Leg.transit?(leg) route = if(transit?, do: leg.mode.route) + + trip = + if(route && is_nil(route.external_agency_name), do: leg |> Leg.trip_id() |> parse_trip_id()) + stop = name_from_position(leg.from) %__MODULE__{ @@ -74,7 +80,7 @@ defmodule Dotcom.TripPlan.ItineraryRow do transit?: Leg.transit?(leg), route: route, trip: trip, - departure: leg_time(leg.start), + departure: leg.start, steps: get_steps(leg.mode, next_leg), additional_routes: get_additional_routes(route, trip, leg, stop), duration: leg.duration, @@ -82,9 +88,6 @@ defmodule Dotcom.TripPlan.ItineraryRow do } end - defp leg_time(%Schema.LegTime{estimated: nil, scheduled_time: time}), do: time - defp leg_time(%Schema.LegTime{estimated: %{time: time}}), do: time - @spec fetch_alerts(t, [Alerts.Alert.t()]) :: t def fetch_alerts(row, alerts) @@ -169,7 +172,7 @@ defmodule Dotcom.TripPlan.ItineraryRow do do: Enum.map(steps, &format_personal_to_personal_step/1) defp get_steps(%TransitDetail{intermediate_stops: stops}, _next_leg) do - for stop <- stops do + for stop <- stops, stop do %IntermediateStop{ description: stop.name, stop: stop diff --git a/lib/dotcom/trip_plan/related_link.ex b/lib/dotcom/trip_plan/related_link.ex index 7e056c2d20..fa95d134a3 100644 --- a/lib/dotcom/trip_plan/related_link.ex +++ b/lib/dotcom/trip_plan/related_link.ex @@ -69,6 +69,7 @@ defmodule Dotcom.TripPlan.RelatedLink do defp optional_icon(nil), do: [] defp optional_icon(icon_name) do + # IO.inspect(icon_name, label: "icon name") SvgIconWithCircle.svg_icon_with_circle(%SvgIconWithCircle{icon: icon_name, size: :small}) end @@ -81,14 +82,24 @@ defmodule Dotcom.TripPlan.RelatedLink do end end - defp route_link(%Route{custom_route?: true} = route, _, _) do + defp route_link( + %Route{external_agency_name: "Logan Express", name: name, long_name: long_name} = route, + _, + _ + ) do url = - if String.starts_with?(route.long_name, "Logan Express") do - "https://www.massport.com/logan-airport/getting-to-logan/logan-express" + if name == "BB" do + "https://www.massport.com/logan-airport/to-from-logan/transportation-options/logan-express/back-bay/" else - "https://massport.com/" + route_name = String.split(long_name, " ") |> List.first() + "https://www.massport.com/logan-airport/getting-to-logan/logan-express/#{route_name}" end + new("#{long_name} schedules", url, route) + end + + defp route_link(%Route{external_agency_name: "Massport"}, _, _) do + url = "https://massport.com/" new("Massport schedules", url, :massport_shuttle) end @@ -108,7 +119,7 @@ defmodule Dotcom.TripPlan.RelatedLink do end defp fare_links(itinerary) do - for %Leg{mode: %TransitDetail{route: %Route{custom_route?: false} = route}} = leg <- + for %Leg{mode: %TransitDetail{route: %Route{external_agency_name: nil} = route}} = leg <- itinerary.legs do fare_link(route, leg) end diff --git a/lib/dotcom_web/views/helpers.ex b/lib/dotcom_web/views/helpers.ex index beb9b67b20..419c0a5627 100644 --- a/lib/dotcom_web/views/helpers.ex +++ b/lib/dotcom_web/views/helpers.ex @@ -112,12 +112,18 @@ defmodule DotcomWeb.ViewHelpers do end # Massport shuttle routes - def line_icon(%Route{custom_route?: true, long_name: "Massport" <> _, name: name}, _) + def line_icon(%Route{external_agency_name: "Massport", name: name}, _) when is_binary(name) do route_number = String.slice(name, 0..1) svg("icon-massport-#{route_number}.svg") end + # Logan Express shuttle routes + def line_icon(%Route{external_agency_name: "Logan Express", name: name}, _) + when is_binary(name) do + svg("icon-logan-express-#{name}.svg") + end + def line_icon(%Route{} = route, size) do route |> Route.icon_atom() @@ -239,6 +245,10 @@ defmodule DotcomWeb.ViewHelpers do @spec route_to_class(Routes.Route.t()) :: String.t() def route_to_class(nil), do: "" + def route_to_class(%Routes.Route{external_agency_name: "Logan Express", name: name}) do + "logan-express-#{name}" + end + def route_to_class(route) do route |> Routes.Route.to_naive() diff --git a/lib/dotcom_web/views/partial/svg_icon_with_circle.ex b/lib/dotcom_web/views/partial/svg_icon_with_circle.ex index b32b2845d0..edd549a0a7 100644 --- a/lib/dotcom_web/views/partial/svg_icon_with_circle.ex +++ b/lib/dotcom_web/views/partial/svg_icon_with_circle.ex @@ -218,6 +218,8 @@ defmodule DotcomWeb.PartialView.SvgIconWithCircle do def title(%Routes.Route{id: "Green-" <> branch}), do: DotcomWeb.ViewHelpers.mode_name(:green_line) <> " #{branch}" + def title(%Routes.Route{external_agency_name: "Massport", long_name: name}), do: name + def title(%Routes.Route{external_agency_name: "Logan Express", long_name: name}), do: name def title(%Routes.Route{custom_route?: true, long_name: name}), do: name def title(%Routes.Route{type: type}), do: DotcomWeb.ViewHelpers.mode_name(type) def title(_icon), do: "" diff --git a/lib/dotcom_web/views/trip_plan_view.ex b/lib/dotcom_web/views/trip_plan_view.ex index a6228bb16e..d19d51f9e4 100644 --- a/lib/dotcom_web/views/trip_plan_view.ex +++ b/lib/dotcom_web/views/trip_plan_view.ex @@ -362,7 +362,7 @@ defmodule DotcomWeb.TripPlanView do svg_icon_with_circle(%SvgIconWithCircle{icon: :bus}) end - def icon_for_route(%Route{type: 3, custom_route?: false} = route) do + def icon_for_route(%Route{type: 3, external_agency_name: nil} = route) do DotcomWeb.ViewHelpers.bus_icon_pill(route) end @@ -370,6 +370,7 @@ defmodule DotcomWeb.TripPlanView do svg_icon_with_circle(%SvgIconWithCircle{icon: route}) end + @spec datetime_from_query(nil | Dotcom.TripPlan.Query.t()) :: any() def datetime_from_query(%Query{time: {:error, _}}), do: datetime_from_query(nil) def datetime_from_query(%Query{time: {_depart_or_arrive, dt}}), do: dt def datetime_from_query(nil), do: Util.now() |> Dotcom.TripPlan.DateTime.round_minute() diff --git a/lib/routes/route.ex b/lib/routes/route.ex index 3576983068..cbbbc4c7c5 100644 --- a/lib/routes/route.ex +++ b/lib/routes/route.ex @@ -67,8 +67,8 @@ defmodule Routes.Route do @silver_line_set MapSet.new(@silver_line) @spec type_atom(t | type_int | String.t()) :: route_type - def type_atom(%__MODULE__{id: "Massport" <> _}), do: :massport_shuttle - def type_atom(%__MODULE__{id: "Logan Express" <> _}), do: :logan_express + def type_atom(%__MODULE__{external_agency_name: "Massport"}), do: :massport_shuttle + def type_atom(%__MODULE__{external_agency_name: "Logan Express"}), do: :logan_express def type_atom(%__MODULE__{type: type}), do: type_atom(type) def type_atom(0), do: :subway def type_atom(1), do: :subway @@ -99,6 +99,8 @@ defmodule Routes.Route do def types_for_mode(:silver_line), do: [3] @spec icon_atom(t) :: gtfs_route_type | subway_lines_type + def icon_atom(%__MODULE__{external_agency_name: "Massport"}), do: :massport_shuttle + def icon_atom(%__MODULE__{external_agency_name: "Logan Express"}), do: :logan_express def icon_atom(%__MODULE__{id: "Red"}), do: :red_line def icon_atom(%__MODULE__{id: "Mattapan"}), do: :mattapan_line def icon_atom(%__MODULE__{id: "Orange"}), do: :orange_line @@ -108,8 +110,6 @@ defmodule Routes.Route do def icon_atom(%__MODULE__{id: "Green-C"}), do: :green_line_c def icon_atom(%__MODULE__{id: "Green-D"}), do: :green_line_d def icon_atom(%__MODULE__{id: "Green-E"}), do: :green_line_e - def icon_atom(%__MODULE__{id: "Massport" <> _}), do: :massport_shuttle - def icon_atom(%__MODULE__{id: "Logan Express" <> _}), do: :logan_express for silver_line_route <- @silver_line do def icon_atom(%__MODULE__{id: unquote(silver_line_route)}), do: unquote(:silver_line) diff --git a/lib/trip_plan/itinerary.ex b/lib/trip_plan/itinerary.ex index fc08470249..affe72d3e1 100644 --- a/lib/trip_plan/itinerary.ex +++ b/lib/trip_plan/itinerary.ex @@ -108,7 +108,9 @@ defmodule TripPlan.Itinerary do end defp leg_intermediate(%Leg{mode: %TransitDetail{intermediate_stops: stops}}) do - Enum.map(stops, & &1.id) + stops + |> Enum.reject(&is_nil/1) + |> Enum.map(& &1.id) end defp leg_intermediate(_) do diff --git a/lib/trip_plan/transfer.ex b/lib/trip_plan/transfer.ex index 78a4787949..27c2e8f69a 100644 --- a/lib/trip_plan/transfer.ex +++ b/lib/trip_plan/transfer.ex @@ -32,7 +32,8 @@ defmodule TripPlan.Transfer do mode: %TransitDetail{route: route_from} } | _ - ]) do + ]) + when not is_nil(to_stop) and not is_nil(from_stop) do same_station?(from_stop.id, to_stop.id) and subway?(route_to) and subway?(route_from) end @@ -56,13 +57,13 @@ defmodule TripPlan.Transfer do def maybe_transfer?([ first_leg = %Leg{ - mode: %TransitDetail{route: %Routes.Route{custom_route?: false} = first_route} + mode: %TransitDetail{route: %Routes.Route{external_agency_name: nil} = first_route} }, middle_leg = %Leg{ - mode: %TransitDetail{route: %Routes.Route{custom_route?: false} = middle_route} + mode: %TransitDetail{route: %Routes.Route{external_agency_name: nil} = middle_route} }, last_leg = %Leg{ - mode: %TransitDetail{route: %Routes.Route{custom_route?: false} = last_route} + mode: %TransitDetail{route: %Routes.Route{external_agency_name: nil} = last_route} } ]) do @multi_ride_transfers @@ -73,8 +74,8 @@ defmodule TripPlan.Transfer do end def maybe_transfer?([ - %Leg{mode: %TransitDetail{route: %Routes.Route{custom_route?: false} = from_route}}, - %Leg{mode: %TransitDetail{route: %Routes.Route{custom_route?: false} = to_route}} + %Leg{mode: %TransitDetail{route: %Routes.Route{external_agency_name: nil} = from_route}}, + %Leg{mode: %TransitDetail{route: %Routes.Route{external_agency_name: nil} = to_route}} ]) do if from_route === to_route and Enum.all?([from_route, to_route], &bus?/1) do @@ -101,8 +102,8 @@ defmodule TripPlan.Transfer do end def bus_to_subway_transfer?([ - %Leg{mode: %TransitDetail{route: from_route}}, - %Leg{mode: %TransitDetail{route: to_route}} + %Leg{mode: %TransitDetail{route: %Routes.Route{external_agency_name: nil} = from_route}}, + %Leg{mode: %TransitDetail{route: %Routes.Route{external_agency_name: nil} = to_route}} ]) do bus?(from_route) && subway?(to_route) end diff --git a/lib/trip_planner/fare_passes.ex b/lib/trip_planner/fare_passes.ex index 8049d783c0..2447f58f86 100644 --- a/lib/trip_planner/fare_passes.ex +++ b/lib/trip_planner/fare_passes.ex @@ -71,6 +71,9 @@ defmodule Dotcom.TripPlanner.FarePasses do %Leg{leg | mode: mode_with_fares} end + def leg_with_fares(%Leg{from: %NamedPosition{stop: nil}} = leg), do: leg + def leg_with_fares(%Leg{to: %NamedPosition{stop: nil}} = leg), do: leg + def leg_with_fares(%Leg{mode: %TransitDetail{route: route}} = leg) do trip = Schedules.Repo.trip(leg.mode.trip_id) origin_id = leg.from.stop.id @@ -139,6 +142,8 @@ defmodule Dotcom.TripPlanner.FarePasses do @spec highest_month_pass(Leg.t()) :: Fare.t() | nil defp highest_month_pass(%Leg{mode: %PersonalDetail{}}), do: nil + defp highest_month_pass(%Leg{from: %NamedPosition{stop: nil}}), do: nil + defp highest_month_pass(%Leg{to: %NamedPosition{stop: nil}}), do: nil defp highest_month_pass( %Leg{ @@ -156,6 +161,8 @@ defmodule Dotcom.TripPlanner.FarePasses do @spec lowest_month_pass(Leg.t()) :: Fare.t() | nil defp lowest_month_pass(%Leg{mode: %PersonalDetail{}}), do: nil + defp lowest_month_pass(%Leg{from: %NamedPosition{stop: nil}}), do: nil + defp lowest_month_pass(%Leg{to: %NamedPosition{stop: nil}}), do: nil defp lowest_month_pass( %Leg{ @@ -173,6 +180,8 @@ defmodule Dotcom.TripPlanner.FarePasses do @spec reduced_pass(Leg.t()) :: Fare.t() | nil defp reduced_pass(%Leg{mode: %PersonalDetail{}}), do: nil + defp reduced_pass(%Leg{from: %NamedPosition{stop: nil}}), do: nil + defp reduced_pass(%Leg{to: %NamedPosition{stop: nil}}), do: nil defp reduced_pass( %Leg{ diff --git a/lib/trip_planner/parser.ex b/lib/trip_planner/parser.ex index 5c62c15e59..b0ba334151 100644 --- a/lib/trip_planner/parser.ex +++ b/lib/trip_planner/parser.ex @@ -52,8 +52,8 @@ defmodule Dotcom.TripPlanner.Parser do %Leg{ from: place(leg.from), mode: mode(leg, agency_name), - start: leg.start, - stop: leg.end, + start: time(leg.start), + stop: time(leg.end), to: place(leg.to), polyline: leg.leg_geometry.points, distance: miles(leg.distance), @@ -61,6 +61,9 @@ defmodule Dotcom.TripPlanner.Parser do } end + defp time(%Schema.LegTime{estimated: nil, scheduled_time: time}), do: time + defp time(%Schema.LegTime{estimated: %{time: time}}), do: time + @spec place(Schema.Place.t()) :: NamedPosition.t() def place(%Schema.Place{ stop: stop, @@ -141,7 +144,7 @@ defmodule Dotcom.TripPlanner.Parser do name: short_name || id, long_name: route_name(agency_name, short_name, long_name), type: type, - color: color + color: route_color(agency_name, short_name, color) } end @@ -156,20 +159,30 @@ defmodule Dotcom.TripPlanner.Parser do if long_name, do: long_name, else: short_name end + defp route_color("Logan Express", "WO", _), do: "00954c" + defp route_color("Logan Express", "BB", _), do: "f16823" + defp route_color("Logan Express", "PB", _), do: "704c9f" + defp route_color(_, _, color), do: color + + # only create a %Stop{} if the GTFS ID is from MBTA + defp build_stop(stop, attributes \\ %{}) + defp build_stop( %Schema.Stop{ - gtfs_id: gtfs_id, + gtfs_id: "mbta-ma-us:" <> gtfs_id, name: name }, - attributes \\ %{} + attributes ) do %Stops.Stop{ - id: id_from_gtfs(gtfs_id), + id: gtfs_id, name: name } |> struct(attributes) end + defp build_stop(_, _), do: nil + defp id_from_gtfs(gtfs_id) do case String.split(gtfs_id, ":") do [_, id] -> id diff --git a/priv/static/icon-svg/icon-logan-express-BB.svg b/priv/static/icon-svg/icon-logan-express-BB.svg new file mode 100644 index 0000000000..10a33cced2 --- /dev/null +++ b/priv/static/icon-svg/icon-logan-express-BB.svg @@ -0,0 +1,26 @@ + + + + + + + + + + \ No newline at end of file diff --git a/priv/static/icon-svg/icon-logan-express-BT.svg b/priv/static/icon-svg/icon-logan-express-BT.svg new file mode 100644 index 0000000000..a77059106f --- /dev/null +++ b/priv/static/icon-svg/icon-logan-express-BT.svg @@ -0,0 +1,26 @@ + + + + + + + + + + \ No newline at end of file diff --git a/priv/static/icon-svg/icon-logan-express-FH.svg b/priv/static/icon-svg/icon-logan-express-FH.svg new file mode 100644 index 0000000000..a43c6dfa75 --- /dev/null +++ b/priv/static/icon-svg/icon-logan-express-FH.svg @@ -0,0 +1,26 @@ + + + + + + + + + + \ No newline at end of file diff --git a/priv/static/icon-svg/icon-logan-express-PB.svg b/priv/static/icon-svg/icon-logan-express-PB.svg new file mode 100644 index 0000000000..3460ae3846 --- /dev/null +++ b/priv/static/icon-svg/icon-logan-express-PB.svg @@ -0,0 +1,26 @@ + + + + + + + + + + \ No newline at end of file diff --git a/priv/static/icon-svg/icon-logan-express-WO.svg b/priv/static/icon-svg/icon-logan-express-WO.svg new file mode 100644 index 0000000000..cc66b82c7c --- /dev/null +++ b/priv/static/icon-svg/icon-logan-express-WO.svg @@ -0,0 +1,26 @@ + + + + + + + + + + \ No newline at end of file