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()