Skip to content

Commit

Permalink
feat: Select screen type page (#235)
Browse files Browse the repository at this point in the history
  • Loading branch information
cmaddox5 authored Dec 20, 2023
1 parent 5621525 commit 20cac0f
Show file tree
Hide file tree
Showing 17 changed files with 287 additions and 8 deletions.
11 changes: 11 additions & 0 deletions assets/css/dashboard/appbar.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
.navbar-dark {
background: $cool-gray-15;

.navbar-brand {
color: $text-primary;
}

.btn-close {
background-color: transparent;
}
}
30 changes: 30 additions & 0 deletions assets/css/dashboard/button-image.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
.button-image-container {
display: flex;

.button-image {
display: flex;
flex-direction: column;
height: 268px;
border-radius: 16px;
background: #2b3741;
border-color: transparent;
flex: 1 1 306px;
align-items: center;
padding-bottom: 18px;

&:hover {
background: $cool-gray-30;
border-color: transparent;
}

&__image-container {
margin-top: auto;
margin-bottom: auto;
}

&__label {
font-size: 16px;
font-weight: 700;
}
}
}
29 changes: 29 additions & 0 deletions assets/css/dashboard/configure-screens-page.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
.configure-screens-page {
display: flex;
flex-direction: column;
color: $text-primary;
background: #0f1417;
overflow-y: scroll;
min-height: 100%;

.select-screen-type {
max-width: 1320px;

&__title {
white-space: nowrap;
width: fit-content;
}

.row {
justify-content: center;
gap: 24px;
margin-bottom: 32px;
}

.col {
width: fit-content;
flex-grow: 0;
min-width: 306px;
}
}
}
17 changes: 14 additions & 3 deletions assets/css/screenplay.scss
Original file line number Diff line number Diff line change
@@ -1,15 +1,23 @@
@import "variables.scss";

$theme-colors: (
"primary": $theme-primary,
);

$form-check-input-checked-color: #0f1417;
$form-check-input-checked-bg-color: #8ecdff;
$form-check-input-bg: #0f1417;
$form-check-input-border: 1px solid #8b9198;

@import "~bootstrap/scss/bootstrap";
@import "variables.scss";
@import "dashboard.scss";
@import "dashboard/places-page.scss";
@import "dashboard/alerts-page.scss";
@import "dashboard/overrides-page.scss";
@import "dashboard/alert-details.scss";
@import "dashboard/configure-screens-page.scss";
@import "dashboard/button-image.scss";
@import "dashboard/appbar.scss";
@import "place-row.scss";
@import "places-action-bar.scss";
@import "filter-dropdown.scss";
Expand All @@ -24,8 +32,6 @@ $form-check-input-border: 1px solid #8b9198;
@import "animation.scss";
@import "screen-detail-action-bar.scss";

$body-bg: $cool-gray-30;

html {
font-size: 16px;
}
Expand Down Expand Up @@ -68,3 +74,8 @@ button,
input[type="button"] {
letter-spacing: 0.5px;
}

.h3 {
font-weight: 700;
font-size: 28px;
}
9 changes: 5 additions & 4 deletions assets/css/variables.scss
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,6 @@ $gray-700: #374151;
$gray-800: #1f2937;
$gray-900: #111827;

$cool-gray-20: #1e2933;
$cool-gray-30: #2e3f4d;
$cool-gray-40: #3d5366;

$pink-100: #fce7f3;
$pink-700: #be185d;
$pink-900: #831843;
Expand All @@ -27,6 +23,7 @@ $bright-yellow: #fbdd01;
$cool-gray-15: #171f26;
$cool-gray-20: #1e2933;
$cool-gray-30: #2e3f4d;
$cool-gray-40: #3d5366;

$main-blue: #0075db;
$hover-blue: #0075db99;
Expand All @@ -38,3 +35,7 @@ $mbta-orange: #ed8b00;
$mbta-bus: #ffc72c;

$sidebar-width: 260px;

$text-primary: #f8f9fa;

$theme-primary: #384956;
8 changes: 7 additions & 1 deletion assets/js/components/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ const AlertDetails = React.lazy(() => import("./Dashboard/AlertDetails"));
const PendingScreensPage = React.lazy(
() => import("./Dashboard/PendingScreensPage")
);
const ConfigureScreensPage = React.lazy(
() => import("./Dashboard/PermanentConfiguration/ConfigureScreensPage")
);

class AppRoutes extends React.Component {
render() {
Expand All @@ -34,7 +37,10 @@ class AppRoutes extends React.Component {
<Route path="alerts" element={<AlertsPage />}></Route>
<Route path="alerts/:id" element={<AlertDetails />}></Route>
<Route path="pending" element={<PendingScreensPage />}></Route>
<Route path="configure-screens" element={<></>}></Route>
<Route
path="configure-screens"
element={<ConfigureScreensPage />}
/>
</Route>
</Routes>
</React.Suspense>
Expand Down
23 changes: 23 additions & 0 deletions assets/js/components/Dashboard/PermanentConfiguration/AppBar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import React, { ComponentType } from "react";
import { CloseButton, Container, Navbar } from "react-bootstrap";
import { useNavigate } from "react-router-dom";

interface AppBarProps {
title: string;
}

const Appbar: ComponentType<AppBarProps> = (props: AppBarProps) => {
const { title } = props;
const navigate = useNavigate();

return (
<Navbar variant="dark" data-bs-theme="dark">
<Container>
<Navbar.Brand>{title}</Navbar.Brand>
<CloseButton variant="white" onClick={() => navigate(-1)} />
</Container>
</Navbar>
);
};

export default Appbar;
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import React, { ComponentType } from "react";
import { Button } from "react-bootstrap";

interface ButtonImageProps {
fileName: string;
label: string;
onClick: () => unknown;
}

const ButtonImage: ComponentType<ButtonImageProps> = (
props: ButtonImageProps
) => {
const { fileName, label, onClick } = props;
return (
<div className="button-image-container">
<Button className="button-image" onClick={onClick}>
<div className="button-image__image-container">
<img alt="" src={`/images/${fileName}`} />
</div>
<div className="button-image__label">{label}</div>
</Button>
</div>
);
};

export default ButtonImage;
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
import React, { ComponentType, useState } from "react";
import { Col, Container, Row } from "react-bootstrap";
import AppBar from "./AppBar";
import ButtonImage from "./ButtonImage";
import "../../../../css/screenplay.scss";
import { Place } from "../../../models/place";
import { useScreenplayContext } from "../../../hooks/useScreenplayContext";

const ConfigureScreensPage: ComponentType = () => {
const [selectedScreenType, setSelectedScreenType] = useState<string>();
const { places } = useScreenplayContext();

const getPlacesList = (screenType: string) => {
let filteredPlaces: Place[] = [];
switch (screenType) {
case "gl-eink":
filteredPlaces = places.filter((place) =>
place.routes.some((route) => route.startsWith("Green"))
);
break;
default:
throw new Error(
`getPlacesList not implemented for screen type ${screenType}`
);
}

return filteredPlaces;
};

const selectScreenType = (screenType: string) =>
setSelectedScreenType(screenType);

let layout;
switch (selectedScreenType) {
case "gl-eink":
layout = <GlEinkConfigPage places={getPlacesList("gl-eink")} />;
break;
default:
layout = (
<SelectScreenTypeComponent selectScreenType={selectScreenType} />
);
}

return (
<div className="configure-screens-page">
<AppBar title="Configure Screens" />
{layout}
</div>
);
};

interface SelectScreenTypeComponentProps {
selectScreenType: (screenType: string) => void;
}

const SelectScreenTypeComponent: ComponentType<SelectScreenTypeComponentProps> =
(props: SelectScreenTypeComponentProps) => {
const { selectScreenType } = props;

return (
<Container className="select-screen-type p-5">
<Row>
<Col>
<div className="h3 select-screen-type__title">
Select screen type
</div>
</Col>
<Col></Col>
<Col></Col>
</Row>
<Row md={2} lg={3}>
<Col>
<ButtonImage
fileName="bus-eink.png"
label="Bus E-Ink"
onClick={() => selectScreenType("bus-eink")}
/>
</Col>
<Col>
<ButtonImage
fileName="bus-shelter.png"
label="Bus Shelter"
onClick={() => selectScreenType("bus-shelter")}
/>
</Col>
<Col>
<ButtonImage
fileName="gl-eink.png"
label="Green Line E-Ink"
onClick={() => selectScreenType("gl-eink")}
/>
</Col>
<Col>
<ButtonImage
fileName="dup.png"
label="DUP"
onClick={() => selectScreenType("dup")}
/>
</Col>
<Col>
<ButtonImage
fileName="pre-fare.png"
label="Pre Fare"
onClick={() => selectScreenType("pre-fare")}
/>
</Col>
<Col>
<ButtonImage
fileName="solari.png"
label="Solari"
onClick={() => selectScreenType("solari")}
/>
</Col>
</Row>
</Container>
);
};

interface SubwayConfigPageProps {
places: Place[];
}

const GlEinkConfigPage: ComponentType<SubwayConfigPageProps> = ({
places,
}: SubwayConfigPageProps) => {
return (
<>
<div>GL-Eink</div>
{places.map((place) => (
<div key={place.id}>{place.name}</div>
))}
</>
);
};

export default ConfigureScreensPage;
2 changes: 2 additions & 0 deletions assets/js/components/Dashboard/Sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import TSquare from "../../../static/images/t-square.svg";

const Sidebar: ComponentType = () => {
const pathname = useLocation().pathname.replace(/\//g, "");
if (pathname.includes("configure-screens")) return null;

// @ts-ignore Suppressing "object could be null" warning
const username = document
.querySelector("meta[name=username]")
Expand Down
Binary file added assets/static/images/bus-eink.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/static/images/bus-shelter.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/static/images/dup.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/static/images/gl-eink.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/static/images/pre-fare.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/static/images/solari.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions lib/screenplay_web/controllers/config_controller.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ defmodule ScreenplayWeb.ConfigController do

alias Screenplay.Config.PermanentConfig

def index(conn, _params) do
render(conn, "index.html")
end

def add(conn, %{"screen_id" => screen_id, "screen" => screen, "etag" => etag}) do
case PermanentConfig.add_new_screen(screen_id, screen, etag) do
:ok ->
Expand Down

0 comments on commit 20cac0f

Please sign in to comment.