Skip to content

Commit

Permalink
Add a display which shows an arbitrary web page (closes #140).
Browse files Browse the repository at this point in the history
  • Loading branch information
patfair committed May 23, 2024
1 parent 1d25f5e commit def8c0e
Show file tree
Hide file tree
Showing 8 changed files with 151 additions and 0 deletions.
3 changes: 3 additions & 0 deletions field/display.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ const (
RankingsDisplay
TwitchStreamDisplay
WallDisplay
WebpageDisplay
)

var DisplayTypeNames = map[DisplayType]string{
Expand All @@ -49,6 +50,7 @@ var DisplayTypeNames = map[DisplayType]string{
RankingsDisplay: "Rankings",
TwitchStreamDisplay: "Twitch Stream",
WallDisplay: "Wall",
WebpageDisplay: "Web Page",
}

var displayTypePaths = map[DisplayType]string{
Expand All @@ -62,6 +64,7 @@ var displayTypePaths = map[DisplayType]string{
RankingsDisplay: "/displays/rankings",
TwitchStreamDisplay: "/displays/twitch",
WallDisplay: "/displays/wall",
WebpageDisplay: "/displays/webpage",
}

var displayRegistryMutex sync.Mutex
Expand Down
20 changes: 20 additions & 0 deletions static/css/webpage_display.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
Copyright 2024 Team 254. All Rights Reserved.
Author: [email protected] (Patrick Fairbank)
*/

html {
overflow: hidden;
}
body {
margin: 0;
background-color: #000;
}
#webpageFrame {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
border: none;
}
17 changes: 17 additions & 0 deletions static/js/webpage_display.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright 2024 Team 254. All Rights Reserved.
// Author: [email protected] (Patrick Fairbank)
//
// Client-side logic for the web page display.

var websocket;

$(function() {
// Read the configuration for this display from the URL query string.
var urlParams = new URLSearchParams(window.location.search);
console.log(urlParams.get("url"));
$("#webpageFrame").attr("src", urlParams.get("url"));

// Set up the websocket back to the server.
websocket = new CheesyWebsocket("/displays/webpage/websocket", {
});
});
1 change: 1 addition & 0 deletions templates/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@
<a class="dropdown-item" href="/displays/queueing">Queueing</a>
<a class="dropdown-item" href="/displays/rankings">Standings</a>
<a class="dropdown-item" href="/displays/wall">Wall</a>
<a class="dropdown-item" href="/displays/webpage">Web Page</a>
<div class="dropdown-divider"></div>
<div class="dropdown-header">Alliance Station</div>
<a class="dropdown-item" href="/displays/alliance_station?station=R1">Red 1</a>
Expand Down
22 changes: 22 additions & 0 deletions templates/webpage_display.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{{/*
Copyright 2024 Team 254. All Rights Reserved.
Author: [email protected] (Patrick Fairbank)

Display to show an arbitrary web page.
*/}}
<!DOCTYPE html>
<html>
<head>
<title>Web Page Display - {{.EventSettings.Name}} - Cheesy Arena </title>
<link rel="shortcut icon" href="/static/img/favicon.ico">
<link rel="stylesheet" href="/static/css/webpage_display.css" />
</head>
<body>
<iframe id="webpageFrame"></iframe>
<script src="/static/js/lib/jquery.min.js"></script>
<script src="/static/js/lib/jquery.json-2.4.min.js"></script>
<script src="/static/js/lib/jquery.websocket-0.0.1.js"></script>
<script src="/static/js/cheesy-websocket.js"></script>
<script src="/static/js/webpage_display.js"></script>
</body>
</html>
2 changes: 2 additions & 0 deletions web/web.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,8 @@ func (web *Web) newHandler() http.Handler {
mux.HandleFunc("GET /displays/twitch/websocket", web.twitchDisplayWebsocketHandler)
mux.HandleFunc("GET /displays/wall", web.wallDisplayHandler)
mux.HandleFunc("GET /displays/wall/websocket", web.wallDisplayWebsocketHandler)
mux.HandleFunc("GET /displays/webpage", web.webpageDisplayHandler)
mux.HandleFunc("GET /displays/webpage/websocket", web.webpageDisplayWebsocketHandler)
mux.HandleFunc("GET /login", web.loginHandler)
mux.HandleFunc("POST /login", web.loginPostHandler)
mux.HandleFunc("GET /match_play", web.matchPlayHandler)
Expand Down
53 changes: 53 additions & 0 deletions web/webpage_display.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// Copyright 2024 Team 254. All Rights Reserved.
// Author: [email protected] (Patrick Fairbank)
//
// Web routes for a display to show an arbitrary web page.

package web

import (
"github.com/Team254/cheesy-arena/model"
"github.com/Team254/cheesy-arena/websocket"
"net/http"
)

// Renders the web page view.
func (web *Web) webpageDisplayHandler(w http.ResponseWriter, r *http.Request) {
if !web.enforceDisplayConfiguration(w, r, map[string]string{"url": "https://www.team254.com"}) {
return
}

template, err := web.parseFiles("templates/webpage_display.html")
if err != nil {
handleWebErr(w, err)
return
}
data := struct {
*model.EventSettings
}{web.arena.EventSettings}
err = template.ExecuteTemplate(w, "webpage_display.html", data)
if err != nil {
handleWebErr(w, err)
return
}
}

// The websocket endpoint for sending configuration commands to the display.
func (web *Web) webpageDisplayWebsocketHandler(w http.ResponseWriter, r *http.Request) {
display, err := web.registerDisplay(r)
if err != nil {
handleWebErr(w, err)
return
}
defer web.arena.MarkDisplayDisconnected(display.DisplayConfiguration.Id)

ws, err := websocket.NewWebsocket(w, r)
if err != nil {
handleWebErr(w, err)
return
}
defer ws.Close()

// Subscribe the websocket to the notifiers whose messages will be passed on to the client.
ws.HandleNotifiers(display.Notifier, web.arena.ReloadDisplaysNotifier)
}
33 changes: 33 additions & 0 deletions web/webpage_display_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Copyright 2024 Team 254. All Rights Reserved.
// Author: [email protected] (Patrick Fairbank)

package web

import (
"github.com/Team254/cheesy-arena/websocket"
gorillawebsocket "github.com/gorilla/websocket"
"github.com/stretchr/testify/assert"
"testing"
)

func TestWebpageDisplay(t *testing.T) {
web := setupTestWeb(t)

recorder := web.getHttpResponse("/displays/webpage?displayId=1&url=https://www.team254.com")
assert.Equal(t, 200, recorder.Code)
assert.Contains(t, recorder.Body.String(), "Web Page Display - Untitled Event - Cheesy Arena")
}

func TestWebpageDisplayWebsocket(t *testing.T) {
web := setupTestWeb(t)

server, wsUrl := web.startTestServer()
defer server.Close()
conn, _, err := gorillawebsocket.DefaultDialer.Dial(wsUrl+"/displays/webpage/websocket?displayId=123", nil)
assert.Nil(t, err)
defer conn.Close()
ws := websocket.NewTestWebsocket(conn)

// Should get a few status updates right after connection.
readWebsocketType(t, ws, "displayConfiguration")
}

0 comments on commit def8c0e

Please sign in to comment.