diff --git a/assets/css/dashboard/error-toast.scss b/assets/css/dashboard/error-toast.scss deleted file mode 100644 index 64469febf..000000000 --- a/assets/css/dashboard/error-toast.scss +++ /dev/null @@ -1,38 +0,0 @@ -.error-alert-container { - display: flex; - justify-content: center; - align-items: center; - position: fixed; - left: 50%; - transform: translateX(-50%); - bottom: 40px; - - .error-alert { - width: 400px; - background-color: $alert-yellow; - font-size: 16px; - display: flex; - align-items: center; - - .btn-close { - &:hover { - background-color: transparent; - } - } - - &__icon { - height: 24px; - width: 24px; - opacity: 60%; - flex-shrink: 0; - } - - &__text { - padding-left: 8px; - - ul { - margin-bottom: 0; - } - } - } -} diff --git a/assets/css/dashboard/toast.scss b/assets/css/dashboard/toast.scss new file mode 100644 index 000000000..06cb2ce2d --- /dev/null +++ b/assets/css/dashboard/toast.scss @@ -0,0 +1,52 @@ +.toast-container { + margin-bottom: 40px; + + .toast { + font-size: 16px; + display: flex; + align-items: center; + + .btn-close { + &:hover { + background-color: transparent; + } + } + + &--warning { + background-color: $alert-yellow; + } + + &--info { + background-color: $accessibility-blue; + color: white; + } + + &__icon { + height: 24px; + width: 24px; + opacity: 60%; + flex-shrink: 0; + } + + &__text { + padding-left: 8px; + + ul { + margin-bottom: 0; + } + } + } + + .toast-header { + .btn-close { + margin-right: 4px; + + &:hover { + background-color: transparent; + } + } + + border: none; + border-radius: 4px; + } +} diff --git a/assets/css/screen-detail.scss b/assets/css/screen-detail.scss index ac45145ad..95f141231 100644 --- a/assets/css/screen-detail.scss +++ b/assets/css/screen-detail.scss @@ -1,6 +1,8 @@ .screen-detail__inline-layout { display: flex; justify-content: space-between; + flex-wrap: wrap; + gap: 4px; } .screen-detail__container { diff --git a/assets/css/screen-simulation.scss b/assets/css/screen-simulation.scss index e5ece02b4..77c379e68 100644 --- a/assets/css/screen-simulation.scss +++ b/assets/css/screen-simulation.scss @@ -45,7 +45,8 @@ width: 100%; &--busway_v2, - &--bus_shelter_v2 { + &--bus_shelter_v2, + &--elevator_v2 { height: 379px; } diff --git a/assets/css/screenplay.scss b/assets/css/screenplay.scss index 8c6b37463..80fb957a8 100644 --- a/assets/css/screenplay.scss +++ b/assets/css/screenplay.scss @@ -43,8 +43,8 @@ $form-feedback-invalid-color: $text-error; @import "sort-label.scss"; @import "search-bar.scss"; @import "dashboard/picker.scss"; -@import "dashboard/error-toast.scss"; @import "error-modal.scss"; +@import "dashboard/toast.scss"; html { font-size: 16px; diff --git a/assets/css/variables.scss b/assets/css/variables.scss index c4d0949a6..cb3720377 100644 --- a/assets/css/variables.scss +++ b/assets/css/variables.scss @@ -67,3 +67,4 @@ $button-secondary-outline-active-bg: #d9d9d93d; $text-button-blue-hover-color: #c1e4ff14; $text-button-grey-hover-color: #f8f9fa14; $alert-yellow: #ffdd00; +$accessibility-blue: #165c96; diff --git a/assets/js/components/Dashboard/ErrorToast.tsx b/assets/js/components/Dashboard/ErrorToast.tsx deleted file mode 100644 index 1996f3068..000000000 --- a/assets/js/components/Dashboard/ErrorToast.tsx +++ /dev/null @@ -1,54 +0,0 @@ -import React from "react"; -import { Alert } from "react-bootstrap"; -import { ExclamationTriangleFill } from "react-bootstrap-icons"; - -interface Props { - errorMessage: string | null; - errors: string[]; - onClose: () => void; -} - -const ErrorToast = ({ errorMessage, errors, onClose }: Props) => { - const getErrorMessageFromField = (error: string) => { - switch (error) { - case "sign_ids": - return "Add Stations & Zones"; - case "visual_text": - return "Visual Text"; - case "audio_text": - return "Phoentic Audio"; - case "start_datetime": - return "Start date/time"; - case "end_datetime": - return "End date/time"; - default: - return ""; - } - }; - - return ( -
- - -
- {errorMessage} - {errors.length > 0 && ( -
    - {errors.map((error, i) => { - return
  • {getErrorMessageFromField(error)}
  • ; - })} -
- )} -
-
-
- ); -}; - -export default ErrorToast; diff --git a/assets/js/components/Dashboard/PaMessageForm/PaMessageForm.tsx b/assets/js/components/Dashboard/PaMessageForm/PaMessageForm.tsx index 41f01ecc8..5bef918fc 100644 --- a/assets/js/components/Dashboard/PaMessageForm/PaMessageForm.tsx +++ b/assets/js/components/Dashboard/PaMessageForm/PaMessageForm.tsx @@ -6,7 +6,7 @@ import SelectStationsAndZones from "./SelectStationsAndZones"; import AssociateAlert from "./AssociateAlert"; import { Alert, InformedEntity } from "Models/alert"; import { usePlacesWithPaEss } from "Hooks/usePlacesWithPaEss"; -import ErrorToast from "Components/ErrorToast"; +import Toast from "Components/Toast"; import { busRouteIdsAtPlaces, getRouteIdsForSign } from "../../../util"; import fp from "lodash/fp"; @@ -217,8 +217,9 @@ const PaMessageForm = ({ setEndWithEffectPeriod={setEndWithEffectPeriod} /> )} - { onErrorsChange([]); diff --git a/assets/js/components/Dashboard/PlaceRow.tsx b/assets/js/components/Dashboard/PlaceRow.tsx index 9fd48b4dd..c1b23a4e1 100644 --- a/assets/js/components/Dashboard/PlaceRow.tsx +++ b/assets/js/components/Dashboard/PlaceRow.tsx @@ -31,6 +31,7 @@ const typeMap: Record = { bus_eink_v2: "Bus E-Ink", solari: "Sectional", busway_v2: "Sectional", + elevator_v2: "Elevator", }; const inlineMap = (place: Place, line: string) => { diff --git a/assets/js/components/Dashboard/PlaceRowAccordion.tsx b/assets/js/components/Dashboard/PlaceRowAccordion.tsx index 4f667d47b..173f2113e 100644 --- a/assets/js/components/Dashboard/PlaceRowAccordion.tsx +++ b/assets/js/components/Dashboard/PlaceRowAccordion.tsx @@ -15,6 +15,7 @@ import ScreenDetail from "Components/ScreenDetail"; import { sortScreens } from "../../util"; import { useUpdateAnimation } from "Hooks/useUpdateAnimation"; import classNames from "classnames"; +import fp from "lodash/fp"; type ScreenGroup = { screens: Screen[]; @@ -22,12 +23,14 @@ type ScreenGroup = { }; const groupScreens = (screens: Screen[]): ScreenGroup[] => { + const inlineScreenTypes = ["busway_v2", "solari", "elevator_v2"]; + const inlineScreens = screens.filter((screen) => - ["busway_v2", "solari"].includes(screen.type), + inlineScreenTypes.includes(screen.type), ); const paEssScreens = screens.filter((screen) => screen.type === "pa_ess"); const otherScreens = screens.filter( - (screen) => !["busway_v2", "pa_ess", "solari"].includes(screen.type), + (screen) => ![...inlineScreenTypes, "pa_ess"].includes(screen.type), ); const groups = otherScreens.map((screen) => ({ @@ -36,7 +39,14 @@ const groupScreens = (screens: Screen[]): ScreenGroup[] => { })); if (inlineScreens.length > 0) { - groups.push({ screens: inlineScreens, isInline: true }); + const groupedInlineScreens: Screen[][] = fp.flow( + fp.groupBy((screen: Screen) => screen.type), + fp.map((screens) => screens), + )(inlineScreens); + + groupedInlineScreens.forEach((screens) => + groups.push({ screens: screens, isInline: true }), + ); } if (paEssScreens.length > 0) { diff --git a/assets/js/components/Dashboard/Toast.tsx b/assets/js/components/Dashboard/Toast.tsx new file mode 100644 index 000000000..3db3fa6d7 --- /dev/null +++ b/assets/js/components/Dashboard/Toast.tsx @@ -0,0 +1,63 @@ +import React from "react"; +import { Toast as BSToast, ToastContainer } from "react-bootstrap"; +import { + CheckCircleFill, + ExclamationTriangleFill, +} from "react-bootstrap-icons"; +import { classWithModifier } from "../../util"; + +interface ToastProps { + variant: "warning" | "info"; + message: string | null; + errors?: string[]; + onClose?: () => void; +} + +const Toast = ({ message, errors = [], onClose, variant }: ToastProps) => { + const getErrorMessageFromField = (error: string) => { + switch (error) { + case "sign_ids": + return "Add Stations & Zones"; + case "visual_text": + return "Visual Text"; + case "audio_text": + return "Phonetic Audio"; + case "start_datetime": + return "Start date/time"; + case "end_datetime": + return "End date/time"; + default: + return ""; + } + }; + + const Icon = + variant === "warning" ? ExclamationTriangleFill : CheckCircleFill; + + return ( + + + + {} +
+ {message} + {errors.length > 0 && ( +
    + {errors.map((error, i) => { + return
  • {getErrorMessageFromField(error)}
  • ; + })} +
+ )} +
+
+
+
+ ); +}; + +export default Toast; diff --git a/assets/js/constants/constants.ts b/assets/js/constants/constants.ts index d9b12d2f0..9a54d2e19 100644 --- a/assets/js/constants/constants.ts +++ b/assets/js/constants/constants.ts @@ -50,7 +50,7 @@ export const SCREEN_TYPES: { label: string; ids: string[] }[] = [ label: "E-Ink: Green Line", ids: ["gl_eink_single", "gl_eink_double", "gl_eink_v2"], }, - { label: "Elevator", ids: ["elevator"] }, + { label: "Elevator", ids: ["elevator_v2"] }, { label: "PA ESS", ids: ["pa_ess"] }, { label: "Pre Fare Duo", ids: ["pre_fare_v2"] }, { label: "Sectional", ids: ["busway_v2", "solari"] }, diff --git a/assets/js/util.ts b/assets/js/util.ts index cda460da1..26abddff0 100644 --- a/assets/js/util.ts +++ b/assets/js/util.ts @@ -212,6 +212,7 @@ const screenTypeOrder = [ "gl_eink_double", "gl_eink_v2", "pre_fare_v2", + "elevator_v2", "pa_ess", ]; diff --git a/assets/package-lock.json b/assets/package-lock.json index 1f529ba5e..ca66fe624 100644 --- a/assets/package-lock.json +++ b/assets/package-lock.json @@ -35,7 +35,7 @@ "@testing-library/react": "^16.0.1", "@types/date-fns": "^2.6.0", "@types/jest": "^29.5.13", - "@types/lodash": "^4.17.10", + "@types/lodash": "^4.17.12", "@types/phoenix": "^1.6.5", "@types/react": "^18.3.11", "@types/react-dom": "^18.3.1", @@ -3381,9 +3381,9 @@ "license": "MIT" }, "node_modules/@types/lodash": { - "version": "4.17.10", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.10.tgz", - "integrity": "sha512-YpS0zzoduEhuOWjAotS6A5AVCva7X4lVlYLF0FYHAY9sdraBfnatttHItlWeZdGhuEkf+OzMNg2ZYAx8t+52uQ==", + "version": "4.17.12", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.12.tgz", + "integrity": "sha512-sviUmCE8AYdaF/KIHLDJBQgeYzPBI0vf/17NaYehBJfYD1j6/L95Slh07NlyK2iNyBNaEkb3En2jRt+a8y3xZQ==", "dev": true }, "node_modules/@types/node": { diff --git a/assets/package.json b/assets/package.json index 1578dfdcb..eae7ebe0a 100644 --- a/assets/package.json +++ b/assets/package.json @@ -42,7 +42,7 @@ "@testing-library/react": "^16.0.1", "@types/date-fns": "^2.6.0", "@types/jest": "^29.5.13", - "@types/lodash": "^4.17.10", + "@types/lodash": "^4.17.12", "@types/phoenix": "^1.6.5", "@types/react": "^18.3.11", "@types/react-dom": "^18.3.1", diff --git a/config/config.exs b/config/config.exs index d1abda82a..990682a47 100644 --- a/config/config.exs +++ b/config/config.exs @@ -73,6 +73,11 @@ config :ueberauth, Ueberauth, config :elixir, :time_zone_database, Tzdata.TimeZoneDatabase +config :screenplay, Oban, + engine: Oban.Engines.Basic, + queues: [default: 10], + repo: Screenplay.Repo + import_config "outfront_takeover_tool_screens.exs" # Import environment specific config. This must remain at the bottom diff --git a/config/dev.exs b/config/dev.exs index e524e8a2a..2309bdead 100644 --- a/config/dev.exs +++ b/config/dev.exs @@ -86,7 +86,8 @@ config :screenplay, local_paess_labels_file_spec: {:priv, "paess_labels.json"}, api_v3_key: System.get_env("API_V3_KEY"), github_api_client: Screenplay.GithubApi.FakeClient, - local_signs_json_path: "../realtime_signs/priv/signs.json" + local_signs_json_path: "../realtime_signs/priv/signs.json", + watts_client: Screenplay.Watts.FakeClient config :ueberauth, Ueberauth, providers: [ diff --git a/config/runtime.exs b/config/runtime.exs index d314573c8..2c0ec1526 100644 --- a/config/runtime.exs +++ b/config/runtime.exs @@ -60,11 +60,17 @@ if sentry_dsn not in [nil, ""] do environment_name: env end -scheduler_jobs = - if env == "prod", - do: [{"0 7 * * *", {Screenplay.Jobs.TakeoverToolTestingJob, :run, []}}], - else: [] - -config :screenplay, Screenplay.Scheduler, jobs: scheduler_jobs +if env == "prod" do + config :screenplay, Oban, + plugins: [ + {Oban.Plugins.Cron, + crontab: [ + {"0 7 * * *", Screenplay.Jobs.TakeoverToolTestingJob} + ]}, + Oban.Plugins.Pruner, + Oban.Plugins.Lifeline, + Oban.Plugins.Reindexer + ] +end config :screenplay, Screenplay.Repo, pool_size: 10 diff --git a/config/test.exs b/config/test.exs index 72b8a78b5..5f02ca638 100644 --- a/config/test.exs +++ b/config/test.exs @@ -22,7 +22,8 @@ config :screenplay, github_api_client: Screenplay.GithubApi.FakeClient, local_signs_json_path: {:test, "signs.json"}, stops_mod: Screenplay.Stops.Mock, - routes_mod: Screenplay.Routes.Mock + routes_mod: Screenplay.Routes.Mock, + facilities_mod: Screenplay.Facilities.Mock config :ueberauth, Ueberauth, providers: [ @@ -38,13 +39,9 @@ config :ueberauth_oidcc, ] ] -config :screenplay, Screenplay.Repo, - adapter: Ecto.Adapters.Postgres, - database: "screenplay_test", - pool: Ecto.Adapters.SQL.Sandbox, - username: "postgres", - password: "postgres", - hostname: "localhost" +config :screenplay, Screenplay.Repo, database: "screenplay_test", pool: Ecto.Adapters.SQL.Sandbox + +config :screenplay, Oban, testing: :inline # Print only warnings and errors during test config :logger, level: :warning diff --git a/lib/screenplay/application.ex b/lib/screenplay/application.ex index dcd6cb766..213434a8a 100644 --- a/lib/screenplay/application.ex +++ b/lib/screenplay/application.ex @@ -11,6 +11,7 @@ defmodule Screenplay.Application do {Ecto.Migrator, repos: Application.fetch_env!(:screenplay, :ecto_repos)}, # Start the Ecto repository Screenplay.Repo, + {Oban, Application.fetch_env!(:screenplay, Oban)}, # Start the Telemetry supervisor ScreenplayWeb.Telemetry, # Start the PubSub system @@ -19,8 +20,7 @@ defmodule Screenplay.Application do ScreenplayWeb.Endpoint, Screenplay.OutfrontTakeoverTool.Alerts.State, Screenplay.OutfrontTakeoverTool.Alerts.Reminders, - Screenplay.ScreensConfig, - Screenplay.Scheduler + Screenplay.ScreensConfig ] ++ if Application.get_env(:screenplay, :start_cache_processes) do [Screenplay.Alerts.Cache, Screenplay.Places] diff --git a/lib/screenplay/facilities/facility.ex b/lib/screenplay/facilities/facility.ex new file mode 100644 index 000000000..b66492912 --- /dev/null +++ b/lib/screenplay/facilities/facility.ex @@ -0,0 +1,15 @@ +defmodule Screenplay.Facilities.Facility do + @moduledoc """ + Functions used to fetch facility data from the V3 API. + """ + + alias Screenplay.V3Api + + @callback fetch(String.t()) :: {:ok, map()} | :error + def fetch(facility_id) do + case V3Api.get_json("/facilities/#{facility_id}") do + {:ok, %{"data" => data}} -> {:ok, data} + _ -> :error + end + end +end diff --git a/lib/screenplay/jobs/takeover_tool_testing_job.ex b/lib/screenplay/jobs/takeover_tool_testing_job.ex index 9c522eb6d..23e694ae8 100644 --- a/lib/screenplay/jobs/takeover_tool_testing_job.ex +++ b/lib/screenplay/jobs/takeover_tool_testing_job.ex @@ -7,6 +7,8 @@ defmodule Screenplay.Jobs.TakeoverToolTestingJob do """ @dialyzer {:no_match, write_image: 3, delete_image: 2} + use Oban.Worker, unique: true + alias Screenplay.Outfront.SFTP require Logger @@ -16,7 +18,8 @@ defmodule Screenplay.Jobs.TakeoverToolTestingJob do @portrait_dir Application.compile_env!(:screenplay, :portrait_dir) @test_image :screenplay |> :code.priv_dir() |> Path.join("takeover_test.png") |> File.read!() - def run do + @impl Oban.Worker + def perform(_) do SFTP.run(fn conn -> test_creating_and_removing_images(conn) test_all_directories_exist(conn) diff --git a/lib/screenplay/outfront/sftp.ex b/lib/screenplay/outfront/sftp.ex index db5751b17..b723bea8e 100644 --- a/lib/screenplay/outfront/sftp.ex +++ b/lib/screenplay/outfront/sftp.ex @@ -10,6 +10,7 @@ defmodule Screenplay.Outfront.SFTP do @portrait_dir Application.compile_env!(:screenplay, :portrait_dir) @retries 3 + @spec run((SFTPClient.Conn.t() -> :ok)) :: :ok def run(work_fn) do conn = start_connection() diff --git a/lib/screenplay/permanent_config.ex b/lib/screenplay/permanent_config.ex index 772218917..d67e169a5 100644 --- a/lib/screenplay/permanent_config.ex +++ b/lib/screenplay/permanent_config.ex @@ -12,7 +12,7 @@ defmodule Screenplay.PermanentConfig do alias Screenplay.ScreensConfig, as: ScreensConfigStore alias Screenplay.ScreensConfig.Fetch, as: PublishedScreensFetch alias ScreensConfig.{Config, PendingConfig, Screen} - alias ScreensConfig.V2.{Alerts, Audio, Departures, Footer, GlEink, LineMap} + alias ScreensConfig.V2.{Alerts, Departures, Footer, GlEink, LineMap} alias ScreensConfig.V2.Departures.{Query, Section} alias ScreensConfig.V2.Header.Destination @@ -290,7 +290,6 @@ defmodule Screenplay.PermanentConfig do app_id: :gl_eink_v2, app_params: struct(GlEink, - audio: default_enabled_audio_config(), departures: struct(Departures, sections: [ @@ -364,14 +363,6 @@ defmodule Screenplay.PermanentConfig do end) end - defp default_enabled_audio_config do - %Audio{ - start_time: ~T[00:00:00], - stop_time: ~T[23:59:59], - days_active: [1, 2, 3, 4, 5, 6, 7] - } - end - # Each screen type will look in a different part of the configuration to find it's physical location defp get_route_id(:gl_eink_v2, updated_pending_screens, new_pending_screens) do updated_pending_screens diff --git a/lib/screenplay/places/builder.ex b/lib/screenplay/places/builder.ex index abbec12fc..f0181bb4b 100644 --- a/lib/screenplay/places/builder.ex +++ b/lib/screenplay/places/builder.ex @@ -20,6 +20,7 @@ defmodule Screenplay.Places.Builder do Busway, Departures, Dup, + Elevator, Footer, GlEink, Header, @@ -34,6 +35,11 @@ defmodule Screenplay.Places.Builder do @config_fetcher Application.compile_env!(:screenplay, :config_fetcher) @stops_mod Application.compile_env(:screenplay, :stops_mod, Screenplay.Stops.Stop) @routes_mod Application.compile_env(:screenplay, :routes_mod, Screenplay.Routes.Route) + @facilities_mod Application.compile_env( + :screenplay, + :facilities_mod, + Screenplay.Facilities.Facility + ) @github_api_client Application.compile_env( :screenplay, :github_api_client, @@ -228,6 +234,12 @@ defmodule Screenplay.Places.Builder do stop_id end + defp get_stop_id({_id, %{app_params: %Elevator{elevator_id: elevator_id}}}) do + {:ok, facility} = @facilities_mod.fetch(elevator_id) + %{"relationships" => %{"stop" => %{"data" => %{"id" => stop_id}}}} = facility + stop_id + end + defp split_multi_place_screens( {id, %Screen{ diff --git a/lib/screenplay/scheduler.ex b/lib/screenplay/scheduler.ex deleted file mode 100644 index 6832da512..000000000 --- a/lib/screenplay/scheduler.ex +++ /dev/null @@ -1,4 +0,0 @@ -defmodule Screenplay.Scheduler do - @moduledoc false - use Quantum, otp_app: :screenplay -end diff --git a/lib/screenplay/watts.ex b/lib/screenplay/watts/client.ex similarity index 57% rename from lib/screenplay/watts.ex rename to lib/screenplay/watts/client.ex index 4af0495b8..12a7ece7a 100644 --- a/lib/screenplay/watts.ex +++ b/lib/screenplay/watts/client.ex @@ -1,14 +1,22 @@ -defmodule Screenplay.Watts do +defmodule Screenplay.Watts.ClientBehaviour do + @moduledoc false + + @doc """ + Fetches an audio file from Watts given a string. + """ + @callback fetch_tts(String.t()) :: {:ok, binary()} | :error +end + +defmodule Screenplay.Watts.Client do @moduledoc """ - Module used to fetch TTS audio files from the Watts app. + Client used to fetch TTS audio files from the Watts app. """ require Logger - @doc """ - Fetches an audio file from Watts given a string. - """ - @spec fetch_tts(String.t()) :: :error | {:ok, binary()} + @behaviour Screenplay.Watts.ClientBehaviour + + @impl true def fetch_tts(text) do watts_url = Application.fetch_env!(:screenplay, :watts_url) watts_api_key = Application.fetch_env!(:screenplay, :watts_api_key) @@ -41,3 +49,26 @@ defmodule Screenplay.Watts do :error end end + +defmodule Screenplay.Watts.FakeClient do + @moduledoc false + + require Logger + + @behaviour Screenplay.Watts.ClientBehaviour + + @impl true + # sobelow_skip ["Traversal.FileModule"] + def fetch_tts(_) do + path = Path.join(:code.priv_dir(:screenplay), "static.mp3") + + case File.read(path) do + {:ok, file} -> + {:ok, file} + + {:error, _} -> + Logger.error("Could not fetch static.mp3.") + :error + end + end +end diff --git a/lib/screenplay_web/controllers/pa_messages_api_controller.ex b/lib/screenplay_web/controllers/pa_messages_api_controller.ex index aec7f0c17..0abff0590 100644 --- a/lib/screenplay_web/controllers/pa_messages_api_controller.ex +++ b/lib/screenplay_web/controllers/pa_messages_api_controller.ex @@ -6,12 +6,14 @@ defmodule ScreenplayWeb.PaMessagesApiController do alias Screenplay.PaMessages alias Screenplay.PaMessages.ListParams + @watts_client Application.compile_env(:screenplay, :watts_client, Screenplay.Watts.Client) + def active(conn, _params) do json(conn, PaMessages.get_active_messages()) end def preview_audio(conn, %{"text" => text}) do - case Screenplay.Watts.fetch_tts(text) do + case @watts_client.fetch_tts(text) do {:ok, audio_data} -> send_download(conn, {:binary, audio_data}, filename: "preview.mp3") diff --git a/mix.exs b/mix.exs index d610a3460..5f5268e74 100644 --- a/mix.exs +++ b/mix.exs @@ -64,14 +64,14 @@ defmodule Screenplay.MixProject do {:postgrex, ">= 0.0.0"}, {:screens_config, git: "https://github.com/mbta/screens-config-lib.git", - ref: "594c88ae0a4e9deb43697ab5e0567f1c97f19671"}, + ref: "8ec6e1684a129b089edc5e867a32dfc90028b2e0"}, {:mox, "~> 1.0", only: :test}, - {:quantum, "~> 3.0"}, {:tzdata, "~> 1.1"}, {:ex_machina, "~> 2.7", only: :test}, {:remote_ip, "~> 1.2"}, {:faker, "~> 0.18"}, - {:nebulex, "~> 2.6"} + {:nebulex, "~> 2.6"}, + {:oban, "~> 2.18"} ] end diff --git a/mix.lock b/mix.lock index 903afaf2a..e00d56943 100644 --- a/mix.lock +++ b/mix.lock @@ -1,27 +1,25 @@ %{ "bunt": {:hex, :bunt, "1.0.0", "081c2c665f086849e6d57900292b3a161727ab40431219529f13c4ddcf3e7a44", [:mix], [], "hexpm", "dc5f86aa08a5f6fa6b8096f0735c4e76d54ae5c9fa2c143e5a1fc7c1cd9bb6b5"}, - "castore": {:hex, :castore, "1.0.7", "b651241514e5f6956028147fe6637f7ac13802537e895a724f90bf3e36ddd1dd", [:mix], [], "hexpm", "da7785a4b0d2a021cd1292a60875a784b6caef71e76bf4917bdee1f390455cf5"}, + "castore": {:hex, :castore, "1.0.9", "5cc77474afadf02c7c017823f460a17daa7908e991b0cc917febc90e466a375c", [:mix], [], "hexpm", "5ea956504f1ba6f2b4eb707061d8e17870de2bee95fb59d512872c2ef06925e7"}, "certifi": {:hex, :certifi, "2.12.0", "2d1cca2ec95f59643862af91f001478c9863c2ac9cb6e2f89780bfd8de987329", [:rebar3], [], "hexpm", "ee68d85df22e554040cdb4be100f33873ac6051387baf6a8f6ce82272340ff1c"}, "combine": {:hex, :combine, "0.10.0", "eff8224eeb56498a2af13011d142c5e7997a80c8f5b97c499f84c841032e429f", [:mix], [], "hexpm", "1b1dbc1790073076580d0d1d64e42eae2366583e7aecd455d1215b0d16f2451b"}, "cowboy": {:hex, :cowboy, "2.10.0", "ff9ffeff91dae4ae270dd975642997afe2a1179d94b1887863e43f681a203e26", [:make, :rebar3], [{:cowlib, "2.12.1", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "1.8.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "3afdccb7183cc6f143cb14d3cf51fa00e53db9ec80cdcd525482f5e99bc41d6b"}, "cowboy_telemetry": {:hex, :cowboy_telemetry, "0.4.0", "f239f68b588efa7707abce16a84d0d2acf3a0f50571f8bb7f56a15865aae820c", [:rebar3], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "7d98bac1ee4565d31b62d59f8823dfd8356a169e7fcbb83831b8a5397404c9de"}, "cowlib": {:hex, :cowlib, "2.12.1", "a9fa9a625f1d2025fe6b462cb865881329b5caff8f1854d1cbc9f9533f00e1e1", [:make, :rebar3], [], "hexpm", "163b73f6367a7341b33c794c4e88e7dbfe6498ac42dcd69ef44c5bc5507c8db0"}, "credo": {:hex, :credo, "1.7.8", "9722ba1681e973025908d542ec3d95db5f9c549251ba5b028e251ad8c24ab8c5", [:mix], [{:bunt, "~> 0.2.1 or ~> 1.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2 or ~> 1.0", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "cb9e87cc64f152f3ed1c6e325e7b894dea8f5ef2e41123bd864e3cd5ceb44968"}, - "crontab": {:hex, :crontab, "1.1.13", "3bad04f050b9f7f1c237809e42223999c150656a6b2afbbfef597d56df2144c5", [:mix], [{:ecto, "~> 1.0 or ~> 2.0 or ~> 3.0", [hex: :ecto, repo: "hexpm", optional: true]}], "hexpm", "d67441bec989640e3afb94e123f45a2bc42d76e02988c9613885dc3d01cf7085"}, "db_connection": {:hex, :db_connection, "2.7.0", "b99faa9291bb09892c7da373bb82cba59aefa9b36300f6145c5f201c7adf48ec", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "dcf08f31b2701f857dfc787fbad78223d61a32204f217f15e881dd93e4bdd3ff"}, "decimal": {:hex, :decimal, "2.1.1", "5611dca5d4b2c3dd497dec8f68751f1f1a54755e8ed2a966c2633cf885973ad6", [:mix], [], "hexpm", "53cfe5f497ed0e7771ae1a475575603d77425099ba5faef9394932b35020ffcc"}, "dialyxir": {:hex, :dialyxir, "1.4.4", "fb3ce8741edeaea59c9ae84d5cec75da00fa89fe401c72d6e047d11a61f65f70", [:mix], [{:erlex, ">= 0.2.7", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "cd6111e8017ccd563e65621a4d9a4a1c5cd333df30cebc7face8029cacb4eff6"}, - "ecto": {:hex, :ecto, "3.11.2", "e1d26be989db350a633667c5cda9c3d115ae779b66da567c68c80cfb26a8c9ee", [:mix], [{:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "3c38bca2c6f8d8023f2145326cc8a80100c3ffe4dcbd9842ff867f7fc6156c65"}, - "ecto_sql": {:hex, :ecto_sql, "3.11.3", "4eb7348ff8101fbc4e6bbc5a4404a24fecbe73a3372d16569526b0cf34ebc195", [:mix], [{:db_connection, "~> 2.4.1 or ~> 2.5", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.11.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.6", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.16 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.1 or ~> 2.2", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "e5f36e3d736b99c7fee3e631333b8394ade4bafe9d96d35669fca2d81c2be928"}, + "ecto": {:hex, :ecto, "3.12.4", "267c94d9f2969e6acc4dd5e3e3af5b05cdae89a4d549925f3008b2b7eb0b93c3", [:mix], [{:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "ef04e4101688a67d061e1b10d7bc1fbf00d1d13c17eef08b71d070ff9188f747"}, + "ecto_sql": {:hex, :ecto_sql, "3.12.1", "c0d0d60e85d9ff4631f12bafa454bc392ce8b9ec83531a412c12a0d415a3a4d0", [:mix], [{:db_connection, "~> 2.4.1 or ~> 2.5", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.12", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.7", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.19 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.1 or ~> 2.2", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "aff5b958a899762c5f09028c847569f7dfb9cc9d63bdb8133bff8a5546de6bf5"}, "erlex": {:hex, :erlex, "0.2.7", "810e8725f96ab74d17aac676e748627a07bc87eb950d2b83acd29dc047a30595", [:mix], [], "hexpm", "3ed95f79d1a844c3f6bf0cea61e0d5612a42ce56da9c03f01df538685365efb0"}, "ex_aws": {:hex, :ex_aws, "2.5.6", "6f642e0f82eff10a9b470044f084b81a791cf15b393d647ea5f3e65da2794e3d", [:mix], [{:configparser_ex, "~> 4.0", [hex: :configparser_ex, repo: "hexpm", optional: true]}, {:hackney, "~> 1.16", [hex: :hackney, repo: "hexpm", optional: true]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: true]}, {:jsx, "~> 2.8 or ~> 3.0", [hex: :jsx, repo: "hexpm", optional: true]}, {:mime, "~> 1.2 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:req, "~> 0.3", [hex: :req, repo: "hexpm", optional: true]}, {:sweet_xml, "~> 0.7", [hex: :sweet_xml, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "c69eec59e31fdd89d0beeb1d97e16518dd1b23ad95b3d5c9f1dcfec23d97f960"}, "ex_aws_rds": {:hex, :ex_aws_rds, "2.0.2", "38dd8e83d57cf4b7286c4f6f5c978f700c40c207ffcdd6ca5d738e5eba933f9a", [:mix], [{:ex_aws, "~> 2.0", [hex: :ex_aws, repo: "hexpm", optional: false]}], "hexpm", "9e5b5cc168077874cbd0d29ba65d01caf1877e705fb5cecacf0667dd19bfa75c"}, "ex_aws_s3": {:hex, :ex_aws_s3, "2.5.4", "87aaf4a2f24a48f516d7f5aaced9d128dd5d0f655c4431f9037a11a85c71109c", [:mix], [{:ex_aws, "~> 2.0", [hex: :ex_aws, repo: "hexpm", optional: false]}, {:sweet_xml, ">= 0.0.0", [hex: :sweet_xml, repo: "hexpm", optional: true]}], "hexpm", "c06e7f68b33f7c0acba1361dbd951c79661a28f85aa2e0582990fccca4425355"}, - "ex_machina": {:hex, :ex_machina, "2.7.0", "b792cc3127fd0680fecdb6299235b4727a4944a09ff0fa904cc639272cd92dc7", [:mix], [{:ecto, "~> 2.2 or ~> 3.0", [hex: :ecto, repo: "hexpm", optional: true]}, {:ecto_sql, "~> 3.0", [hex: :ecto_sql, repo: "hexpm", optional: true]}], "hexpm", "419aa7a39bde11894c87a615c4ecaa52d8f107bbdd81d810465186f783245bf8"}, + "ex_machina": {:hex, :ex_machina, "2.8.0", "a0e847b5712065055ec3255840e2c78ef9366634d62390839d4880483be38abe", [:mix], [{:ecto, "~> 2.2 or ~> 3.0", [hex: :ecto, repo: "hexpm", optional: true]}, {:ecto_sql, "~> 3.0", [hex: :ecto_sql, repo: "hexpm", optional: true]}], "hexpm", "79fe1a9c64c0c1c1fab6c4fa5d871682cb90de5885320c187d117004627a7729"}, "expo": {:hex, :expo, "0.5.2", "beba786aab8e3c5431813d7a44b828e7b922bfa431d6bfbada0904535342efe2", [:mix], [], "hexpm", "8c9bfa06ca017c9cb4020fabe980bc7fdb1aaec059fd004c2ab3bff03b1c599c"}, "faker": {:hex, :faker, "0.18.0", "943e479319a22ea4e8e39e8e076b81c02827d9302f3d32726c5bf82f430e6e14", [:mix], [], "hexpm", "bfbdd83958d78e2788e99ec9317c4816e651ad05e24cfd1196ce5db5b3e81797"}, "file_system": {:hex, :file_system, "1.0.1", "79e8ceaddb0416f8b8cd02a0127bdbababe7bf4a23d2a395b983c1f8b3f73edd", [:mix], [], "hexpm", "4414d1f38863ddf9120720cd976fce5bdde8e91d8283353f0e31850fa89feb9e"}, - "gen_stage": {:hex, :gen_stage, "1.2.1", "19d8b5e9a5996d813b8245338a28246307fd8b9c99d1237de199d21efc4c76a1", [:mix], [], "hexpm", "83e8be657fa05b992ffa6ac1e3af6d57aa50aace8f691fcf696ff02f8335b001"}, "gettext": {:hex, :gettext, "0.24.0", "6f4d90ac5f3111673cbefc4ebee96fe5f37a114861ab8c7b7d5b30a1108ce6d8", [:mix], [{:expo, "~> 0.5.1", [hex: :expo, repo: "hexpm", optional: false]}], "hexpm", "bdf75cdfcbe9e4622dd18e034b227d77dd17f0f133853a1c73b97b3d6c770e8b"}, "guardian": {:hex, :guardian, "2.3.2", "78003504b987f2b189d76ccf9496ceaa6a454bb2763627702233f31eb7212881", [:mix], [{:jose, "~> 1.8", [hex: :jose, repo: "hexpm", optional: false]}, {:plug, "~> 1.3.3 or ~> 1.4", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "b189ff38cd46a22a8a824866a6867ca8722942347f13c33f7d23126af8821b52"}, "hackney": {:hex, :hackney, "1.20.1", "8d97aec62ddddd757d128bfd1df6c5861093419f8f7a4223823537bad5d064e2", [:rebar3], [{:certifi, "~> 2.12.0", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "~> 6.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "~> 1.0.0", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~> 1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "3.4.1", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~> 1.1.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}, {:unicode_util_compat, "~> 0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "fe9094e5f1a2a2c0a7d10918fee36bfec0ec2a979994cff8cfe8058cd9af38e3"}, @@ -34,9 +32,10 @@ "mime": {:hex, :mime, "2.0.6", "8f18486773d9b15f95f4f4f1e39b710045fa1de891fada4516559967276e4dc2", [:mix], [], "hexpm", "c9945363a6b26d747389aac3643f8e0e09d30499a138ad64fe8fd1d13d9b153e"}, "mimerl": {:hex, :mimerl, "1.3.0", "d0cd9fc04b9061f82490f6581e0128379830e78535e017f7780f37fea7545726", [:rebar3], [], "hexpm", "a1e15a50d1887217de95f0b9b0793e32853f7c258a5cd227650889b38839fe9d"}, "mox": {:hex, :mox, "1.1.0", "0f5e399649ce9ab7602f72e718305c0f9cdc351190f72844599545e4996af73c", [:mix], [], "hexpm", "d44474c50be02d5b72131070281a5d3895c0e7a95c780e90bc0cfe712f633a13"}, - "nebulex": {:hex, :nebulex, "2.6.3", "78af348ed9f8a338871b41e0b6de718c1808e627ce03fbe86598cbda2bdda2f5", [:mix], [{:decorator, "~> 1.4", [hex: :decorator, repo: "hexpm", optional: true]}, {:shards, "~> 1.1", [hex: :shards, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm", "09cdcbb62f8463ffcec7cae4936425ce91e25d92a6cd37e48b5dda7c851958d5"}, - "nimble_options": {:hex, :nimble_options, "1.1.0", "3b31a57ede9cb1502071fade751ab0c7b8dbe75a9a4c2b5bbb0943a690b63172", [:mix], [], "hexpm", "8bbbb3941af3ca9acc7835f5655ea062111c9c27bcac53e004460dfd19008a99"}, - "nimble_ownership": {:hex, :nimble_ownership, "0.3.1", "99d5244672fafdfac89bfad3d3ab8f0d367603ce1dc4855f86a1c75008bce56f", [:mix], [], "hexpm", "4bf510adedff0449a1d6e200e43e57a814794c8b5b6439071274d248d272a549"}, + "nebulex": {:hex, :nebulex, "2.6.4", "4b00706e0e676474783d988962abf74614480e13c0a32645acb89bb32b660e09", [:mix], [{:decorator, "~> 1.4", [hex: :decorator, repo: "hexpm", optional: true]}, {:shards, "~> 1.1", [hex: :shards, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm", "25bdabf3fb86035c8151bba60bda20f80f96ae0261db7bd4090878ff63b03581"}, + "nimble_options": {:hex, :nimble_options, "1.1.1", "e3a492d54d85fc3fd7c5baf411d9d2852922f66e69476317787a7b2bb000a61b", [:mix], [], "hexpm", "821b2470ca9442c4b6984882fe9bb0389371b8ddec4d45a9504f00a66f650b44"}, + "nimble_ownership": {:hex, :nimble_ownership, "0.3.2", "d4fa4056ade0ae33b5a9eb64554a1b3779689282e37513260125d2d6b32e4874", [:mix], [], "hexpm", "28b9a9f4094fda1aa8ca72f732ff3223eb54aa3eda4fed9022254de2c152b138"}, + "oban": {:hex, :oban, "2.18.3", "1608c04f8856c108555c379f2f56bc0759149d35fa9d3b825cb8a6769f8ae926", [:mix], [{:ecto_sql, "~> 3.10", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:ecto_sqlite3, "~> 0.9", [hex: :ecto_sqlite3, repo: "hexpm", optional: true]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.16", [hex: :postgrex, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "36ca6ca84ef6518f9c2c759ea88efd438a3c81d667ba23b02b062a0aa785475e"}, "oidcc": {:hex, :oidcc, "3.2.4", "0bbe0f6059682dcb3bb70f682ede606779ea7b73337803a05c7d8eb3ae76acc0", [:mix, :rebar3], [{:jose, "~> 1.11", [hex: :jose, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.2", [hex: :telemetry, repo: "hexpm", optional: false]}, {:telemetry_registry, "~> 0.3.1", [hex: :telemetry_registry, repo: "hexpm", optional: false]}], "hexpm", "984956348f6f833577b7a6cb72b325936cab3fd1c9cf28d7d54773d3ea48a20a"}, "parse_trans": {:hex, :parse_trans, "3.4.1", "6e6aa8167cb44cc8f39441d05193be6e6f4e7c2946cb2759f015f8c56b76e5ff", [:rebar3], [], "hexpm", "620a406ce75dada827b82e453c19cf06776be266f5a67cff34e1ef2cbb60e49a"}, "phoenix": {:hex, :phoenix, "1.7.14", "a7d0b3f1bc95987044ddada111e77bd7f75646a08518942c72a8440278ae7825", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.7", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:websock_adapter, "~> 0.5.3", [hex: :websock_adapter, repo: "hexpm", optional: false]}], "hexpm", "c7859bc56cc5dfef19ecfc240775dae358cbaa530231118a9e014df392ace61a"}, @@ -50,13 +49,12 @@ "plug": {:hex, :plug, "1.16.1", "40c74619c12f82736d2214557dedec2e9762029b2438d6d175c5074c933edc9d", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "a13ff6b9006b03d7e33874945b2755253841b238c34071ed85b0e86057f8cddc"}, "plug_cowboy": {:hex, :plug_cowboy, "2.7.2", "fdadb973799ae691bf9ecad99125b16625b1c6039999da5fe544d99218e662e4", [:mix], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:cowboy_telemetry, "~> 0.3", [hex: :cowboy_telemetry, repo: "hexpm", optional: false]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "245d8a11ee2306094840c000e8816f0cbed69a23fc0ac2bcf8d7835ae019bb2f"}, "plug_crypto": {:hex, :plug_crypto, "2.1.0", "f44309c2b06d249c27c8d3f65cfe08158ade08418cf540fd4f72d4d6863abb7b", [:mix], [], "hexpm", "131216a4b030b8f8ce0f26038bc4421ae60e4bb95c5cf5395e1421437824c4fa"}, - "postgrex": {:hex, :postgrex, "0.19.1", "73b498508b69aded53907fe48a1fee811be34cc720e69ef4ccd568c8715495ea", [:mix], [{:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "8bac7885a18f381e091ec6caf41bda7bb8c77912bb0e9285212829afe5d8a8f8"}, - "quantum": {:hex, :quantum, "3.5.3", "ee38838a07761663468145f489ad93e16a79440bebd7c0f90dc1ec9850776d99", [:mix], [{:crontab, "~> 1.1", [hex: :crontab, repo: "hexpm", optional: false]}, {:gen_stage, "~> 0.14 or ~> 1.0", [hex: :gen_stage, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:telemetry_registry, "~> 0.2", [hex: :telemetry_registry, repo: "hexpm", optional: false]}], "hexpm", "500fd3fa77dcd723ed9f766d4a175b684919ff7b6b8cfd9d7d0564d58eba8734"}, + "postgrex": {:hex, :postgrex, "0.19.2", "34d6884a332c7bf1e367fc8b9a849d23b43f7da5c6e263def92784d03f9da468", [:mix], [{:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "618988886ab7ae8561ebed9a3c7469034bf6a88b8995785a3378746a4b9835ec"}, "ranch": {:hex, :ranch, "1.8.0", "8c7a100a139fd57f17327b6413e4167ac559fbc04ca7448e9be9057311597a1d", [:make, :rebar3], [], "hexpm", "49fbcfd3682fab1f5d109351b61257676da1a2fdbe295904176d5e521a2ddfe5"}, "remote_ip": {:hex, :remote_ip, "1.2.0", "fb078e12a44414f4cef5a75963c33008fe169b806572ccd17257c208a7bc760f", [:mix], [{:combine, "~> 0.10", [hex: :combine, repo: "hexpm", optional: false]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "2ff91de19c48149ce19ed230a81d377186e4412552a597d6a5137373e5877cb7"}, - "screens_config": {:git, "https://github.com/mbta/screens-config-lib.git", "594c88ae0a4e9deb43697ab5e0567f1c97f19671", [ref: "594c88ae0a4e9deb43697ab5e0567f1c97f19671"]}, + "screens_config": {:git, "https://github.com/mbta/screens-config-lib.git", "8ec6e1684a129b089edc5e867a32dfc90028b2e0", [ref: "8ec6e1684a129b089edc5e867a32dfc90028b2e0"]}, "sentry": {:hex, :sentry, "10.4.0", "d8ffe8ce15b4b53f5e879299c3c222324c289a47a507c0b251c4f91ce7bae9ff", [:mix], [{:hackney, "~> 1.8", [hex: :hackney, repo: "hexpm", optional: true]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: true]}, {:nimble_options, "~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:nimble_ownership, "~> 0.3.0", [hex: :nimble_ownership, repo: "hexpm", optional: false]}, {:plug, "~> 1.6", [hex: :plug, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm", "e5f98892152879dc87363b1b7f774eeddb8cf7dddfa7355e40eba188b2cae58a"}, - "sftp_client": {:hex, :sftp_client, "2.0.1", "0611d7e4cdb4abb04627dd259c3d77fddec76c68462582abf001a284e030bc52", [:mix], [], "hexpm", "0b0b47071b0a44a898c9c508d307a8e77534f7de9348707efbf7c88c7f33f010"}, + "sftp_client": {:hex, :sftp_client, "2.1.0", "e1de4a116437427cfc4b5b303968655a18ac837514f5ca03d42184ef1d77e6b5", [:mix], [], "hexpm", "b87a6b85454f14a170d7fdc42e5ce3edd699f2795d0f8c65d4e0b3a2ebf0e326"}, "sobelow": {:hex, :sobelow, "0.13.0", "218afe9075904793f5c64b8837cc356e493d88fddde126a463839351870b8d1e", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "cd6e9026b85fc35d7529da14f95e85a078d9dd1907a9097b3ba6ac7ebbe34a0d"}, "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.7", "354c321cf377240c7b8716899e182ce4890c5938111a1296add3ec74cf1715df", [:make, :mix, :rebar3], [], "hexpm", "fe4c190e8f37401d30167c8c405eda19469f34577987c76dde613e838bbc67f8"}, "stream_data": {:hex, :stream_data, "1.1.2", "05499eaec0443349ff877aaabc6e194e82bda6799b9ce6aaa1aadac15a9fdb4d", [:mix], [], "hexpm", "129558d2c77cbc1eb2f4747acbbea79e181a5da51108457000020a906813a1a9"}, @@ -70,5 +68,5 @@ "ueberauth_oidcc": {:hex, :ueberauth_oidcc, "0.4.0", "3fbfbc38735b4dba54ed8bf3e9b80f5054f73cc1ec9af6ae88b7886d25934768", [:mix], [{:oidcc, "~> 3.2.0", [hex: :oidcc, repo: "hexpm", optional: false]}, {:plug, "~> 1.11", [hex: :plug, repo: "hexpm", optional: false]}, {:ueberauth, "~> 0.10", [hex: :ueberauth, repo: "hexpm", optional: false]}], "hexpm", "cdd8517d773cfe499c0b692f795f213b2eb33119afbec34aefd8be0a85c62b21"}, "unicode_util_compat": {:hex, :unicode_util_compat, "0.7.0", "bc84380c9ab48177092f43ac89e4dfa2c6d62b40b8bd132b1059ecc7232f9a78", [:rebar3], [], "hexpm", "25eee6d67df61960cf6a794239566599b09e17e668d3700247bc498638152521"}, "websock": {:hex, :websock, "0.5.3", "2f69a6ebe810328555b6fe5c831a851f485e303a7c8ce6c5f675abeb20ebdadc", [:mix], [], "hexpm", "6105453d7fac22c712ad66fab1d45abdf049868f253cf719b625151460b8b453"}, - "websock_adapter": {:hex, :websock_adapter, "0.5.6", "0437fe56e093fd4ac422de33bf8fc89f7bc1416a3f2d732d8b2c8fd54792fe60", [:mix], [{:bandit, ">= 0.6.0", [hex: :bandit, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.6", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "e04378d26b0af627817ae84c92083b7e97aca3121196679b73c73b99d0d133ea"}, + "websock_adapter": {:hex, :websock_adapter, "0.5.7", "65fa74042530064ef0570b75b43f5c49bb8b235d6515671b3d250022cb8a1f9e", [:mix], [{:bandit, ">= 0.6.0", [hex: :bandit, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.6", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "d0f478ee64deddfec64b800673fd6e0c8888b079d9f3444dd96d2a98383bdbd1"}, } diff --git a/priv/repo/migrations/20241025121807_add_oban_jobs_table.exs b/priv/repo/migrations/20241025121807_add_oban_jobs_table.exs new file mode 100644 index 000000000..7595a678f --- /dev/null +++ b/priv/repo/migrations/20241025121807_add_oban_jobs_table.exs @@ -0,0 +1,13 @@ +defmodule Screenplay.Repo.Migrations.AddObanJobsTable do + use Ecto.Migration + + def up do + Oban.Migration.up(version: 12) + end + + # We specify `version: 1` in `down`, ensuring that we'll roll all the way back down if + # necessary, regardless of which version we've migrated `up` to. + def down do + Oban.Migration.down(version: 1) + end +end diff --git a/priv/static.mp3 b/priv/static.mp3 new file mode 100644 index 000000000..73ca54ccc Binary files /dev/null and b/priv/static.mp3 differ diff --git a/test/fixtures/builder/screens_config.json b/test/fixtures/builder/screens_config.json index bca56dbcb..5d94dd64c 100644 --- a/test/fixtures/builder/screens_config.json +++ b/test/fixtures/builder/screens_config.json @@ -12,16 +12,6 @@ "alerts": { "stop_id": "70232" }, - "audio": { - "start_time": "00:00:00", - "days_active": [1, 2, 3, 4, 5, 6, 7], - "daytime_start_time": "00:00:00", - "daytime_stop_time": "23:59:59", - "daytime_volume": 1, - "interval_offset_seconds": 0, - "nighttime_volume": 1, - "stop_time": "23:59:59" - }, "departures": { "sections": [ { @@ -210,14 +200,8 @@ "stop_id": "10413" }, "audio": { - "start_time": "04:45:00", - "days_active": [1, 2, 3, 4, 5, 6, 7], - "daytime_start_time": "07:00:00", - "daytime_stop_time": "21:00:00", - "daytime_volume": 1, - "interval_offset_seconds": 150, - "nighttime_volume": 0.5, - "stop_time": "01:45:00" + "interval_enabled": true, + "interval_offset_seconds": 150 }, "departures": { "sections": [ @@ -345,7 +329,7 @@ "medium_asset_path": "images/bus-shelter/survey/10413-weld-sb-medium.png" } }, - "vendor": "lg-mri", + "vendor": "lg_mri", "device_id": "TEST", "hidden_from_screenplay": false }, @@ -359,16 +343,6 @@ "header": { "stop_name": "Haymarket" }, - "audio": { - "start_time": "00:00:00", - "days_active": [1, 2, 3, 4, 5, 6, 7], - "daytime_start_time": "00:00:00", - "daytime_stop_time": "00:00:00", - "daytime_volume": 0, - "interval_offset_seconds": 0, - "nighttime_volume": 0, - "stop_time": "23:59:59" - }, "departures": { "sections": [ { @@ -570,6 +544,20 @@ "vendor": "outfront", "device_id": null, "hidden_from_screenplay": true + }, + "ELE-101": { + "disabled": false, + "name": "", + "tags": [], + "app_id": "elevator_v2", + "app_params": { + "evergreen_content": [], + "elevator_id": "842" + }, + "refresh_if_loaded_before": null, + "hidden_from_screenplay": false, + "vendor": "mimo", + "device_id": "" } } } diff --git a/test/screenplay/permanent_config_test.exs b/test/screenplay/permanent_config_test.exs index 6fedb0e10..d3e668a62 100644 --- a/test/screenplay/permanent_config_test.exs +++ b/test/screenplay/permanent_config_test.exs @@ -8,7 +8,7 @@ defmodule Screenplay.PermanentConfigTest do alias Screenplay.Places.{Cache, Place} alias Screenplay.Places.Place.ShowtimeScreen alias ScreensConfig.{PendingConfig, Screen} - alias ScreensConfig.V2.{Alerts, Audio, Departures, Footer, GlEink, Header, LineMap} + alias ScreensConfig.V2.{Alerts, Departures, Footer, GlEink, Header, LineMap} def fetch_current_config_version do {:ok, _config, metadata} = Local.fetch_config() @@ -125,16 +125,6 @@ defmodule Screenplay.PermanentConfigTest do route_id: "Green-B" }, evergreen_content: [], - audio: %Audio{ - start_time: ~T[00:00:00], - stop_time: ~T[23:59:59], - daytime_start_time: ~T[00:00:00], - daytime_stop_time: ~T[00:00:00], - days_active: [1, 2, 3, 4, 5, 6, 7], - daytime_volume: 0.0, - nighttime_volume: 0.0, - interval_offset_seconds: 0 - }, platform_location: "front" }, tags: [] @@ -207,16 +197,6 @@ defmodule Screenplay.PermanentConfigTest do route_id: "Green-B" }, evergreen_content: [], - audio: %Audio{ - start_time: ~T[00:00:00], - stop_time: ~T[23:59:59], - daytime_start_time: ~T[00:00:00], - daytime_stop_time: ~T[00:00:00], - days_active: [1, 2, 3, 4, 5, 6, 7], - daytime_volume: 0.0, - nighttime_volume: 0.0, - interval_offset_seconds: 0 - }, platform_location: "back" }, tags: [] @@ -355,16 +335,6 @@ defmodule Screenplay.PermanentConfigTest do route_id: "Green-B" }, evergreen_content: [], - audio: %Audio{ - start_time: ~T[00:00:00], - stop_time: ~T[23:59:59], - daytime_start_time: ~T[00:00:00], - daytime_stop_time: ~T[00:00:00], - days_active: [1, 2, 3, 4, 5, 6, 7], - daytime_volume: 0.0, - nighttime_volume: 0.0, - interval_offset_seconds: 0 - }, platform_location: "back" }, tags: [] @@ -404,16 +374,6 @@ defmodule Screenplay.PermanentConfigTest do route_id: "Green-B" }, evergreen_content: [], - audio: %Audio{ - start_time: ~T[00:00:00], - stop_time: ~T[23:59:59], - daytime_start_time: ~T[00:00:00], - daytime_stop_time: ~T[00:00:00], - days_active: [1, 2, 3, 4, 5, 6, 7], - daytime_volume: 0.0, - nighttime_volume: 0.0, - interval_offset_seconds: 0 - }, platform_location: "back" }, tags: [] diff --git a/test/screenplay/places/builder_test.exs b/test/screenplay/places/builder_test.exs index 856c14ab3..d454f111d 100644 --- a/test/screenplay/places/builder_test.exs +++ b/test/screenplay/places/builder_test.exs @@ -37,6 +37,10 @@ defmodule Screenplay.Places.BuilderTest do {:ok, [%{"id" => "Red", "attributes" => %{"type" => 1}}]} end) + expect(Screenplay.Facilities.Mock, :fetch, 1, fn _ -> + {:ok, %{"relationships" => %{"stop" => %{"data" => %{"id" => "place-tapst"}}}}} + end) + assert {:noreply, _} = Builder.handle_info(:build, []) assert [ @@ -45,6 +49,13 @@ defmodule Screenplay.Places.BuilderTest do name: "Tappan Street", routes: ["Red"], screens: [ + %Place.ShowtimeScreen{ + direction_id: nil, + disabled: false, + id: "ELE-101", + location: "", + type: :elevator_v2 + }, %Place.ShowtimeScreen{ id: "EIG-546", type: :gl_eink_v2, @@ -76,6 +87,10 @@ defmodule Screenplay.Places.BuilderTest do {:ok, [%{"id" => "108", "attributes" => %{"type" => 3}}]} end) + expect(Screenplay.Facilities.Mock, :fetch, 1, fn _ -> + {:ok, %{"relationships" => %{"stop" => %{"data" => %{"id" => "place-tapst"}}}}} + end) + assert {:noreply, _} = Builder.handle_info(:build, []) assert [ @@ -132,6 +147,10 @@ defmodule Screenplay.Places.BuilderTest do ]} end) + expect(Screenplay.Facilities.Mock, :fetch, 1, fn _ -> + {:ok, %{"relationships" => %{"stop" => %{"data" => %{"id" => "place-tapst"}}}}} + end) + assert {:noreply, _} = Builder.handle_info(:build, []) assert [ @@ -179,6 +198,10 @@ defmodule Screenplay.Places.BuilderTest do {:ok, [%{"id" => "Blue", "attributes" => %{"type" => 1}}]} end) + expect(Screenplay.Facilities.Mock, :fetch, 1, fn _ -> + {:ok, %{"relationships" => %{"stop" => %{"data" => %{"id" => "place-tapst"}}}}} + end) + assert {:noreply, _} = Builder.handle_info(:build, []) assert [ @@ -241,6 +264,10 @@ defmodule Screenplay.Places.BuilderTest do {:ok, [%{"id" => "Orange", "attributes" => %{"type" => 1}}]} end) + expect(Screenplay.Facilities.Mock, :fetch, 1, fn _ -> + {:ok, %{"relationships" => %{"stop" => %{"data" => %{"id" => "place-tapst"}}}}} + end) + assert {:noreply, _} = Builder.handle_info(:build, []) assert [ diff --git a/test/support/mocks.ex b/test/support/mocks.ex index ce4e6f635..ea4da7ebb 100644 --- a/test/support/mocks.ex +++ b/test/support/mocks.ex @@ -1,3 +1,4 @@ Mox.defmock(Screenplay.RoutePatterns.Mock, for: Screenplay.RoutePatterns.Behaviour) Mox.defmock(Screenplay.Stops.Mock, for: Screenplay.Stops.Stop) Mox.defmock(Screenplay.Routes.Mock, for: Screenplay.Routes.Route) +Mox.defmock(Screenplay.Facilities.Mock, for: Screenplay.Facilities.Facility) diff --git a/test/test_helper.exs b/test/test_helper.exs index e09d88c55..257e0a34c 100644 --- a/test/test_helper.exs +++ b/test/test_helper.exs @@ -1,6 +1,4 @@ Application.put_env(:screenplay, :route_pattern_mod, Screenplay.RoutePatterns.Mock) -Application.put_env(:screenplay, :stops_mod, Screenplay.Stops.Mock) -Application.put_env(:screenplay, :routes_mod, Screenplay.Routes.Mock) Ecto.Adapters.SQL.Sandbox.mode(Screenplay.Repo, :manual) ExUnit.start()