Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Elevator Closures at home station #2338

Merged
merged 18 commits into from
Dec 9, 2024
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions assets/css/colors.scss
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ $true-grey-45: #737373;
$true-grey-70: #b2b1af;

$warm-neutral-80: #cccbc8;
$warm-neutral-85: #d9d6d0;
$warm-neutral-90: #e5e4e1;

$cool-black-15: #171f26;
Expand Down
19 changes: 2 additions & 17 deletions assets/css/elevator_v2.scss
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ body {
}
}

.outside-elevator-closures,
.elevator-closures-list,
.current-elevator-closed {
position: relative;
display: flex;
Expand All @@ -51,21 +51,6 @@ body {
color: $cool-black-15;
background-color: $warm-neutral-90;

hr.thick {
min-height: 24px;
margin: 0;
background-color: $cool-black-15;
border: none;
}

hr.thin {
min-height: 2px;
margin: 24px 0;
background-color: $true-grey-45;
border: none;
opacity: 0.5;
}

.subheading {
font-size: 80px;
font-weight: 700;
Expand All @@ -84,4 +69,4 @@ body {
}

@import "v2/elevator/current_elevator_closed";
@import "v2/elevator/outside_elevator_closures";
@import "v2/elevator/elevator_closures_list";
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
.outside-elevator-closures {
.elevator-closures-list {
display: flex;
flex: 1;
flex-direction: column;

.in-station-summary {
position: relative;
display: flex;
justify-content: space-between;
padding: 24px 48px;
Expand All @@ -15,9 +16,19 @@
.text {
margin-right: 82px;
}

&::after {
position: absolute;
top: 100%;
left: 0;
width: 100%;
height: 24px;
content: "";
background: $cool-black-15;
}
}

.outside-closure-list {
.closures-list {
height: 100%;
background-color: $warm-neutral-90;

Expand Down Expand Up @@ -49,8 +60,35 @@
transform: translateX(calc(-100% * var(--closure-list-offset)));

.closure-row {
position: relative;
width: 1080px;
padding: 0 48px;
padding: 26px 48px 24px;

&:not(&--current-station) {
&::after,
&:first-child::before {
position: absolute;
left: 0;
width: 100%;
height: 2px;
margin: 0 24px;
content: "";
background: $true-grey-45;
opacity: 0.5;
}

&::after {
top: 100%;
}

&::before {
top: 0;
}
}

&--current-station {
background-color: $warm-neutral-85;
}

&__station-name {
font-size: 62px;
Expand Down
15 changes: 15 additions & 0 deletions assets/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions assets/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
"lodash": "^4.17.21",
"moment": "^2.30.1",
"moment-timezone": "^0.5.46",
"number-to-words": "^1.2.4",
"qrcode.react": "^1.0.1",
"raven-js": "^3.27.2",
"react": "^17.0.2",
Expand All @@ -50,6 +51,7 @@
"@sentry/webpack-plugin": "^2.22.6",
"@svgr/webpack": "^5.5.0",
"@types/lodash": "^4.17.13",
"@types/number-to-words": "^1.2.3",
"@types/react": "^17.0.14",
"@types/react-dom": "^17.0.9",
"@types/react-router-dom": "^5.1.8",
Expand Down
4 changes: 2 additions & 2 deletions assets/src/apps/v2/elevator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@ import EvergreenContent from "Components/v2/evergreen_content";
import ScreenPage from "Components/v2/screen_page";
import { MappingContext } from "Components/v2/widget";
import MultiScreenPage from "Components/v2/multi_screen_page";
import OutsideElevatorClosures from "Components/v2/elevator/outside_elevator_closures";
import ElevatorClosuresList from "Components/v2/elevator/elevator_closures_list";
import CurrentElevatorClosed from "Components/v2/elevator/current_elevator_closed";
import SimulationScreenPage from "Components/v2/simulation_screen_page";
import Footer from "Components/v2/elevator/footer";
import NormalHeader from "Components/v2/normal_header";

const TYPE_TO_COMPONENT = {
normal: NormalScreen,
outside_elevator_closures: OutsideElevatorClosures,
elevator_closures_list: ElevatorClosuresList,
current_elevator_closed: CurrentElevatorClosed,
evergreen_content: EvergreenContent,
footer: Footer,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, { ComponentType, useLayoutEffect, useRef, useState } from "react";
import cx from "classnames";
import _ from "lodash";
import numberToWords from "number-to-words";
import RoutePill, { routePillKey } from "Components/v2/departures/route_pill";
import makePersistent, {
WrappedComponentProps,
Expand All @@ -13,11 +14,34 @@ import {
import useClientPaging from "Hooks/v2/use_client_paging";
import NormalService from "Images/svgr_bundled/normal-service.svg";
import AccessibilityAlert from "Images/svgr_bundled/accessibility-alert.svg";
import { classWithModifier } from "Util/util";

interface ClosureRowProps {
station: StationWithClosures;
}

const CurrentStationClosureRow = ({ station }: ClosureRowProps) => {
const { closures } = station;

return (
<div className={classWithModifier("closure-row", "current-station")}>
<div className="closure-row__name-and-pills">
<div className="closure-row__station-name">At this station</div>
</div>
{closures.map((closure) => (
<div
key={closure.id}
className={cx("closure-row__elevator-name", {
"list-item": closures.length > 1,
})}
>
{closure.elevator_name} ({closure.elevator_id})
</div>
))}
</div>
);
};

const ClosureRow = ({ station }: ClosureRowProps) => {
const { name, closures, route_icons, id } = station;

Expand All @@ -39,33 +63,55 @@ const ClosureRow = ({ station }: ClosureRowProps) => {
{closure.elevator_name} ({closure.elevator_id})
</div>
))}
<hr className="thin" />
</div>
);
};

const InStationSummary = () => {
interface InStationSummaryProps {
closures: Closure[];
}

const InStationSummary = ({ closures }: InStationSummaryProps) => {
let text;
if (closures.length === 0) {
text = "All elevators at this station are currently working";
} else if (closures.length === 1) {
text = (
<>
<b>This elevator is working.</b> Another elevator at this station is
down.
</>
);
} else {
text = (
<>
<b>This elevator is working.</b>{" "}
{_.capitalize(numberToWords.toWords(closures.length))} other elevators
digitalcora marked this conversation as resolved.
Show resolved Hide resolved
at this station are down.
</>
);
}

return (
<>
<div className="in-station-summary">
<span className="text">
All elevators at this station are currently working
</span>
<span className="text">{text}</span>
<span>
<NormalService height={72} width={72} fill="#145A06" />
</span>
</div>
<hr className="thick" />
</>
);
};

interface OutsideClosureListProps extends WrappedComponentProps {
stations: StationWithClosures[];
stationId: string;
}

const OutsideClosureList = ({
stations,
stationId,
lastUpdate,
onFinish,
}: OutsideClosureListProps) => {
Expand Down Expand Up @@ -103,15 +149,14 @@ const OutsideClosureList = ({
}, [stations]);

return (
<div className="outside-closure-list">
<div className="closures-list">
<div className="header-container">
<div className="header">
<div className="header__title">MBTA Elevator Closures</div>
<div>
<AccessibilityAlert height={128} width={155} />
</div>
</div>
<hr className="thin" />
</div>
<div className="closure-list-container">
{
Expand All @@ -124,9 +169,18 @@ const OutsideClosureList = ({
}
ref={ref}
>
{stations.map((station) => (
<ClosureRow station={station} key={station.id} />
))}
{stations
.sort((a, _b) => (a.id === stationId ? 0 : 1))
.map((station) =>
station.id === stationId ? (
<CurrentStationClosureRow
station={station}
key={station.id}
/>
) : (
<ClosureRow station={station} key={station.id} />
),
)}
</div>
}
</div>
Expand All @@ -144,20 +198,26 @@ const OutsideClosureList = ({

interface Props extends WrappedComponentProps {
id: string;
in_station_closures: Closure[];
other_stations_with_closures: StationWithClosures[];
stations_with_closures: StationWithClosures[];
station_id: string;
}

const OutsideElevatorClosures = ({
other_stations_with_closures: stations,
const ElevatorClosuresList = ({
stations_with_closures: stations,
station_id: stationId,
lastUpdate,
onFinish,
}: Props) => {
return (
<div className="outside-elevator-closures">
<InStationSummary />
<div className="elevator-closures-list">
<InStationSummary
closures={stations
.filter((s) => s.id === stationId)
.flatMap((s) => s.closures)}
/>
<OutsideClosureList
stations={stations}
stationId={stationId}
lastUpdate={lastUpdate}
onFinish={onFinish}
/>
Expand All @@ -166,5 +226,5 @@ const OutsideElevatorClosures = ({
};

export default makePersistent(
OutsideElevatorClosures as ComponentType<WrappedComponentProps>,
ElevatorClosuresList as ComponentType<WrappedComponentProps>,
);
4 changes: 3 additions & 1 deletion config/test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,9 @@ config :screens,
headway_headsign: "Test"
}
]
}
},
elevator_redundancy_data_path:
Path.join(~w[#{File.cwd!()} test fixtures elevator_redundancy_data.json])

config :screens, ScreensWeb.AuthManager, secret_key: "test key"

Expand Down
5 changes: 5 additions & 0 deletions lib/screens/alerts/alert.ex
Original file line number Diff line number Diff line change
Expand Up @@ -374,4 +374,9 @@ defmodule Screens.Alerts.Alert do
end

def partial_station_closure?(_, _), do: false

@spec informs_stop_id?(Alert.t(), Stop.id()) :: boolean()
def informs_stop_id?(%__MODULE__{informed_entities: informed_entities}, stop_id) do
Enum.any?(informed_entities, &(&1.stop == stop_id))
end
end
Loading
Loading