Skip to content

Commit

Permalink
feat: Triptych app "plumbing" (#1833)
Browse files Browse the repository at this point in the history
* Rename `isDup` -> `isOFM` since we now run on two different OFM screen types

* Triptych app setup + packaging instructions

* Working triptych app with viewport shifter

* Remove TODO--made an asana task for it

* Use matching param for triptych pane in data requests

* Cleanup and fix accidentally committed test code

* Working triptych frontend with new route + cleaned up OFM utilities

* Address credo complaints

* Use default simulation component for triptychs

* Add triptych player name mapping for tests

* fix: Tweak config so vscode can consistently resolve aliased import paths

* Remove a few console.logs that I missed

* Unclutter useBaseApiResponse and memoize logic that computes API url

* Add some missing config for the test env :doh:

* A no-op change in lib/, because the last commit didn't trigger CI for some reason??

* Revert "A no-op change in lib/, because the last commit didn't trigger CI for some reason??"

This reverts commit 88e5511.

* Revert "Revert "A no-op change in lib/, because the last commit didn't trigger CI for some reason??""

This reverts commit 7db3eae.

* Uncomment accidentally commented line of code

* Revert `isDUP` name to `isDup`

* Rename a few more isDUPs that the vscode refactor tool missed

* Run prettier

* Rename split-screen slots to left_, middle_, right_pane for consistency

* "Closed" -> "Car closed" per designs (plus some tweaks to avoid prettier making a mess of the existing code)

* Add packaging README section on communicating with Outfront

* Document `platform_position` value

* Adjust no-data/disabled templates to match new slot names

* Finish documenting OFM util functions and hooks

* Reorder lines for consistency with surrounding functions

* Use getMRAID in useCurrentPage + update fake MRAID with new fields for that

* Prettier
  • Loading branch information
jzimbel-mbta authored Aug 30, 2023
1 parent 927d5cc commit 0c1e7b0
Show file tree
Hide file tree
Showing 63 changed files with 1,016 additions and 236 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ npm-debug.log
# Local config files
/priv/local.json
/priv/signs_ui_config.json
/priv/triptych_player_to_screen_id.json

# local environment variables
/priv/local.env
Expand Down
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ Some examples of the various client apps, as of January 2023:
| [Multimodal LCD][solari sample] | used at high-traffic transfer stations served by many routes/modes |
| [Pre-fare duo LCD][pre_fare sample] | posted outside of fare gates at rapid transit stations; content is split across two portrait-oriented 1080p physical displays |
| ["Digital Urban Panel" LCD][dup sample] | content appears in rotation with ads on screens posted outside rapid transit station entrances |
| Triptych trio LCD | (:construction: WIP!) posted across the tracks from platforms at major stations; content is split across three portrait-oriented 1080p physical displays and appears in rotation with ads |

and more to come!

Expand All @@ -34,11 +35,11 @@ On <sup>almost</sup> all of our screen types, we use a common "framework" to fet

Check out [ARCHITECTURE.md](/ARCHITECTURE.md) for an overview of the application architecture, as well as links to further more detailed documentation.

## Packaging the DUP app
## Packaging the DUP and Triptych apps

The DUP screens require the client app to be packaged into a single HTML file rather than dynamically served from our Phoenix server.
The DUP and Triptych screens require the client app to be packaged into a single HTML file rather than dynamically served from our Phoenix server.

You can find instructions on the packaging process [here](assets/src/components/v2/dup/README.md).
You can find instructions on the DUP packaging process [here](assets/src/components/v2/dup/README.md), the triptych packaging process [here](assets/src/components/v2/triptych/README.md).

## Version upgrade guide

Expand Down
3 changes: 3 additions & 0 deletions assets/css/dup_v2.scss
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,10 @@

@import "v2/multi_screen_page";
@import "v2/dup/simulation";

@import "v2/outfront_common/debug";
@import "v2/dup/debug";

@import "v2/dup/empty_state";

body {
Expand Down
15 changes: 14 additions & 1 deletion assets/css/triptych_v2.scss
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,26 @@
line-height: 118px;
}

// Top level stuff
@import "v2/triptych/screen_container";
@import "v2/triptych/viewport";

// Layout/slot elements
@import "v2/triptych/screen/full_screen";
@import "v2/train_crowding";

// No-data states
@import "v2/lcd_common_styles/page_load_no_data";
@import "v2/lcd_common_styles/no_data";
@import "v2/triptych/no_data";

// Widgets
@import "v2/train_crowding";
@import "v2/placeholder";

// Debug overlay for test packages
@import "v2/outfront_common/debug";
@import "v2/triptych/debug";

body {
margin: 0px;
font-family: Inter, sans-serif;
Expand Down
26 changes: 5 additions & 21 deletions assets/css/v2/dup/debug.scss
Original file line number Diff line number Diff line change
@@ -1,24 +1,8 @@
#debug {
position: absolute;
bottom: 0;
right: 0;
width: 100%;
background: rgba(0, 0, 0, 0.5);
color: #fff;
display: flex;
flex-wrap: wrap;
flex-direction: column;
height: 100%;
font-size: 1.5em;
z-index: 10000;
#debug.dup {
width: 1920px;
height: 1080px;
}

#debug p {
position: relative;
z-index: 9999;
font-size: 1.5em;
bottom: unset;
left: unset;
letter-spacing: normal;
font-family: Arial;
#debug .line {
width: 640px;
}
23 changes: 23 additions & 0 deletions assets/css/v2/outfront_common/debug.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#debug {
position: absolute;
top: 0;
left: 0;
z-index: 10000;
overflow-y: hidden;
overflow-x: hidden;

background: rgba(0, 0, 0, 0.5);

display: flex;
flex-flow: column wrap;

color: #fff;
font-size: 1.5em;
font-family: monospace;
}

#debug .line {
box-sizing: border-box;
padding-left: 8px;
overflow-wrap: break-word;
}
9 changes: 0 additions & 9 deletions assets/css/v2/triptych/body/normal.scss

This file was deleted.

8 changes: 8 additions & 0 deletions assets/css/v2/triptych/debug.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#debug.triptych {
width: 1080px;
height: 1920px;
}

#debug .line {
width: 540px;
}
11 changes: 11 additions & 0 deletions assets/css/v2/triptych/no_data.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
.no-data-middle {
position: absolute;
top: 0px;
left: 1080px;
}

.no-data-right {
position: absolute;
top: 0px;
left: 2160px;
}
31 changes: 31 additions & 0 deletions assets/css/v2/triptych/viewport.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
.triptych-screen-viewport {
width: 1080px;
height: 1920px;
overflow: hidden;
position: relative;
margin-left: auto;
margin-right: auto;

.triptych-shifter {
width: 3240px;
height: 1920px;
overflow: hidden;
position: absolute;
}

.triptych-shifter--left {
left: 0;
}

.triptych-shifter--middle {
left: -1080px;
}

.triptych-shifter--right {
right: 0px;
}
}

.triptych-screen-viewport--all {
width: 3240px;
}
2 changes: 1 addition & 1 deletion assets/src/apps/dup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import {
MultiRotationPage,
SimulationPage,
} from "Components/dup/dup_screen_page";
import { isDup } from "Util/util";
import { isDup } from "Util/outfront";

const App = (): JSX.Element => {
if (isDup()) {
Expand Down
8 changes: 4 additions & 4 deletions assets/src/apps/v2/dup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ import {
import PageLoadNoData from "Components/v2/dup/page_load_no_data";
import NoData from "Components/v2/dup/no_data";
import OvernightDepartures from "Components/v2/dup/overnight_departures";
import useOutfrontPlayerName from "Hooks/use_outfront_player_name";
import { usePlayerName } from "Hooks/outfront";
import { isDup } from "Util/outfront";

const TYPE_TO_COMPONENT = {
screen_normal: NormalScreen,
Expand Down Expand Up @@ -122,9 +123,8 @@ const responseMapper: ResponseMapper = (apiResponse) => {
};

const App = (): JSX.Element => {
const playerName = useOutfrontPlayerName();

if (playerName !== null) {
if (isDup()) {
const playerName = usePlayerName()!;
const id = `DUP-${playerName.trim()}`;
return (
<MappingContext.Provider value={TYPE_TO_COMPONENT}>
Expand Down
53 changes: 44 additions & 9 deletions assets/src/apps/v2/triptych.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,27 @@ require("../../../css/triptych_v2.scss");
import React from "react";
import ReactDOM from "react-dom";
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
import ScreenPage from "Components/v2/screen_page";

import { usePlayerName } from "Hooks/outfront";
import { isTriptych } from "Util/outfront";

import { MappingContext } from "Components/v2/widget";
import {
ResponseMapper,
ResponseMapperContext,
LOADING_LAYOUT,
} from "Components/v2/screen_container";
import { MappingContext } from "Components/v2/widget";

import ScreenPage from "Components/v2/screen_page";
import MultiScreenPage from "Components/v2/multi_screen_page";
import SimulationScreenPage from "Components/v2/simulation_screen_page";
import Viewport from "Components/v2/triptych/viewport";

import FullScreen from "Components/v2/basic_layouts/full_screen";

import Placeholder from "Components/v2/placeholder";
import PageLoadNoData from "Components/v2/triptych/page_load_no_data";
import NoData from "Components/v2/triptych/no_data";

import SimulationScreenPage from "Components/v2/simulation_screen_page";
import PageLoadNoData from "Components/v2/lcd/page_load_no_data";
import NoData from "Components/v2/lcd/no_data";
import Placeholder from "Components/v2/placeholder";
import TrainCrowding from "Components/v2/train_crowding";

const TYPE_TO_COMPONENT = {
Expand All @@ -30,12 +36,19 @@ const TYPE_TO_COMPONENT = {
train_crowding: TrainCrowding,
};

const LOADING_LAYOUT = {
full_screen: {
type: "page_load_no_data",
},
type: "screen_normal",
};

const DISABLED_LAYOUT = {
full_screen: {
type: "no_data",
show_alternatives: true,
},
type: "screen_takeover",
type: "screen_normal",
};

const FAILURE_LAYOUT = DISABLED_LAYOUT;
Expand All @@ -55,9 +68,29 @@ const responseMapper: ResponseMapper = (apiResponse) => {
};

const App = (): JSX.Element => {
if (isTriptych()) {
const playerName = usePlayerName()!;

return (
<MappingContext.Provider value={TYPE_TO_COMPONENT}>
<ResponseMapperContext.Provider value={responseMapper}>
<Viewport>
<ScreenPage id={playerName} />
</Viewport>
</ResponseMapperContext.Provider>
</MappingContext.Provider>
);
}

return (
<Router>
<Switch>
<Route exact path="/v2/screen/triptych_v2">
<MultiScreenPage
components={TYPE_TO_COMPONENT}
responseMapper={responseMapper}
/>
</Route>
<Route exact path="/v2/screen/:id/simulation">
<MappingContext.Provider value={TYPE_TO_COMPONENT}>
<ResponseMapperContext.Provider value={responseMapper}>
Expand All @@ -68,7 +101,9 @@ const App = (): JSX.Element => {
<Route path="/v2/screen/:id">
<MappingContext.Provider value={TYPE_TO_COMPONENT}>
<ResponseMapperContext.Provider value={responseMapper}>
<ScreenPage />
<Viewport>
<ScreenPage />
</Viewport>
</ResponseMapperContext.Provider>
</MappingContext.Provider>
</Route>
Expand Down
9 changes: 5 additions & 4 deletions assets/src/components/dup/README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# DUP app packaging

- Ensure [Corsica](https://hexdocs.pm/corsica/Corsica.html) is used on the server to allow CORS requests (ideally limited to just the DUP-relevant routes). It should already be configured at [this line](/lib/screens_web/controllers/screen_api_controller.ex#L7) in the API controller--if it is, you don't need to do anything for this step.
- Double check that any behavior specific to the DUP screen environment happens inside of an `isDup()` check. This includes:
- Double check that any behavior specific to the DUP screen environment happens inside of an `isOFM()` check. This includes:
- `buildApiPath` in use_api_response.tsx should return a full URL for the API path: prefix `apiPath` string with "https://screens.mbta.com".
- `App` component in dup.tsx should just return `<ScreenPage screenContainer={ScreenContainer} />`.
- `imagePath` in util.tsx should return relative paths (no leading `/`).
Expand All @@ -16,7 +16,6 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Screens</title>
<link rel="stylesheet" href="inter_font_face.css" />
<link rel="stylesheet" href="dup.css" />
</head>

Expand All @@ -40,8 +39,10 @@
for ROTATION_INDEX in {0..2}; do
echo "export const ROTATION_INDEX = ${ROTATION_INDEX};" > ../../assets/src/components/dup/rotation_index.tsx
npm --prefix ../../assets run deploy
cp -r css/dup.css js/polyfills.js js/dup.js ../inter_font_face.css ../fonts ../template.json ../preview.png .
zip -r dup-app-${ROTATION_INDEX}.zip dup.css polyfills.js dup.js inter_font_face.css fonts images dup-app.html template.json preview.png
cp -r css/dup.css js/polyfills.js js/dup.js ../dup_preview.png .
cp ../dup_template.json ./template.json
sed -i "" "s/DUP APP ./DUP APP ${ROTATION_INDEX}/" template.json
zip -r dup-app-${ROTATION_INDEX}.zip dup.css polyfills.js dup.js fonts images dup-app.html template.json dup_preview.png
done
```
- Commit the version bump on a branch, push it, and create a PR to mark the deploy.
Expand Down
6 changes: 3 additions & 3 deletions assets/src/components/dup/dup_screen_page.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import React from "react";
import { useParams } from "react-router-dom";

import useOutfrontStation from "Hooks/use_outfront_station";
import { ROTATION_INDEX } from "./rotation_index";
import { NoDataLayout } from "Components/dup/screen_container";
import { isDup } from "Util/util";
import { isDup } from "Util/outfront";
import { useStationName } from "Hooks/outfront";
import { fetchDatasetValue } from "Util/dataset";
import { DUP_SIMULATION_REFRESH_MS } from "Constants";

Expand All @@ -13,7 +13,7 @@ const DupScreenPage = ({
}: {
screenContainer: React.ComponentType;
}): JSX.Element => {
const station = useOutfrontStation();
const station = useStationName();

if (station !== null) {
const id = `DUP-${station.replace(/\s/g, "")}`;
Expand Down
6 changes: 3 additions & 3 deletions assets/src/components/dup/screen_container.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ import PartialAlerts from "Components/dup/partial_alert";
import FreeText from "Components/dup/free_text";

import useApiResponse from "Hooks/use_api_response";
import useOutfrontStation from "Hooks/use_outfront_station";
import useCurrentPage from "Hooks/use_current_dup_page";

import { formatTimeString, classWithModifier, imagePath } from "Util/util";
import Loading from "Components/v2/bundled_svg/loading";
import { useStationName } from "Hooks/outfront";

const LinkArrow = ({ width, color }) => {
const height = 40;
Expand Down Expand Up @@ -66,7 +66,7 @@ const REPLACEMENTS = {
};

const NoDataLayout = ({ code }: { code?: string }): JSX.Element => {
let stationName = useOutfrontStation() || "Transit information";
let stationName = useStationName();
stationName = REPLACEMENTS[stationName] || stationName;

return (
Expand Down Expand Up @@ -94,7 +94,7 @@ const NoDataLayout = ({ code }: { code?: string }): JSX.Element => {
};

const LoadingLayout = (): JSX.Element => {
let stationName = useOutfrontStation() || "Transit information";
let stationName = useStationName();
stationName = REPLACEMENTS[stationName] || stationName;

return (
Expand Down
Loading

0 comments on commit 0c1e7b0

Please sign in to comment.