mirror of
https://github.com/Team254/cheesy-arena-lite.git
synced 2026-03-10 06:06:47 -04:00
Added event settings setup page.
This commit is contained in:
@@ -2,7 +2,12 @@
|
||||
CREATE TABLE event_settings (
|
||||
id INTEGER PRIMARY KEY,
|
||||
name VARCHAR(255),
|
||||
code VARCHAR(16)
|
||||
code VARCHAR(16),
|
||||
displaybackgroundcolor VARCHAR(16),
|
||||
numelimalliances int,
|
||||
selectionround1order VARCHAR(1),
|
||||
selectionround2order VARCHAR(1),
|
||||
selectionround3order VARCHAR(1)
|
||||
);
|
||||
|
||||
-- +goose Down
|
||||
|
||||
@@ -6,9 +6,14 @@
|
||||
package main
|
||||
|
||||
type EventSettings struct {
|
||||
Id int
|
||||
Name string
|
||||
Code string
|
||||
Id int
|
||||
Name string
|
||||
Code string
|
||||
DisplayBackgroundColor string
|
||||
NumElimAlliances int
|
||||
SelectionRound1Order string
|
||||
SelectionRound2Order string
|
||||
SelectionRound3Order string
|
||||
}
|
||||
|
||||
const eventSettingsId = 0
|
||||
@@ -18,11 +23,17 @@ func (database *Database) GetEventSettings() (*EventSettings, error) {
|
||||
err := database.eventSettingsMap.Get(eventSettings, eventSettingsId)
|
||||
if err != nil {
|
||||
// Database record doesn't exist yet; create it now.
|
||||
eventSettings.Name = "Untitled Event"
|
||||
eventSettings.Code = "UE"
|
||||
eventSettings.DisplayBackgroundColor = "#00ff00"
|
||||
eventSettings.NumElimAlliances = 8
|
||||
eventSettings.SelectionRound1Order = "F"
|
||||
eventSettings.SelectionRound2Order = "L"
|
||||
eventSettings.SelectionRound3Order = ""
|
||||
err = database.eventSettingsMap.Insert(eventSettings)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return new(EventSettings), nil
|
||||
}
|
||||
return eventSettings, nil
|
||||
}
|
||||
|
||||
@@ -17,10 +17,15 @@ func TestEventSettingsReadWrite(t *testing.T) {
|
||||
|
||||
eventSettings, err := db.GetEventSettings()
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, *new(EventSettings), *eventSettings)
|
||||
assert.Equal(t, EventSettings{0, "Untitled Event", "UE", "#00ff00", 8, "F", "L", ""}, *eventSettings)
|
||||
|
||||
eventSettings.Name = "Chezy Champs"
|
||||
eventSettings.Code = "cc"
|
||||
eventSettings.DisplayBackgroundColor = "#ff00ff"
|
||||
eventSettings.NumElimAlliances = 6
|
||||
eventSettings.SelectionRound1Order = "F"
|
||||
eventSettings.SelectionRound2Order = "F"
|
||||
eventSettings.SelectionRound3Order = "L"
|
||||
err = db.SaveEventSettings(eventSettings)
|
||||
assert.Nil(t, err)
|
||||
eventSettings2, err := db.GetEventSettings()
|
||||
|
||||
8
main.go
8
main.go
@@ -10,10 +10,16 @@ import (
|
||||
)
|
||||
|
||||
var db *Database
|
||||
var eventSettings *EventSettings
|
||||
|
||||
func main() {
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
db, _ = OpenDatabase("test.db")
|
||||
var err error
|
||||
db, err = OpenDatabase("test.db")
|
||||
checkErr(err)
|
||||
eventSettings, err = db.GetEventSettings()
|
||||
checkErr(err)
|
||||
|
||||
ServeWebInterface()
|
||||
}
|
||||
|
||||
|
||||
15
reports.go
15
reports.go
@@ -67,11 +67,6 @@ func RankingsPdfReportHandler(w http.ResponseWriter, r *http.Request) {
|
||||
handleWebErr(w, err)
|
||||
return
|
||||
}
|
||||
eventSettings, err := db.GetEventSettings()
|
||||
if err != nil {
|
||||
handleWebErr(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
// The widths of the table columns in mm, stored here so that they can be referenced for each row.
|
||||
colWidths := map[string]float64{"Rank": 13, "Team": 23, "QS": 20, "Assist": 20, "Auto": 20,
|
||||
@@ -161,11 +156,6 @@ func SchedulePdfReportHandler(w http.ResponseWriter, r *http.Request) {
|
||||
if len(teams) > 0 {
|
||||
matchesPerTeam = len(matches) * teamsPerMatch / len(teams)
|
||||
}
|
||||
eventSettings, err := db.GetEventSettings()
|
||||
if err != nil {
|
||||
handleWebErr(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
// The widths of the table columns in mm, stored here so that they can be referenced for each row.
|
||||
colWidths := map[string]float64{"Time": 35, "Type": 25, "Match": 15, "Team": 20}
|
||||
@@ -272,11 +262,6 @@ func TeamsPdfReportHandler(w http.ResponseWriter, r *http.Request) {
|
||||
handleWebErr(w, err)
|
||||
return
|
||||
}
|
||||
eventSettings, err := db.GetEventSettings()
|
||||
if err != nil {
|
||||
handleWebErr(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
// The widths of the table columns in mm, stored here so that they can be referenced for each row.
|
||||
colWidths := map[string]float64{"Id": 12, "Name": 80, "Location": 80, "RookieYear": 23}
|
||||
|
||||
@@ -5,8 +5,6 @@ package main
|
||||
|
||||
import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
@@ -33,6 +31,7 @@ func TestRankingsPdfReport(t *testing.T) {
|
||||
clearDb()
|
||||
defer clearDb()
|
||||
db, _ = OpenDatabase(testDbPath)
|
||||
eventSettings, _ = db.GetEventSettings()
|
||||
ranking1 := Ranking{1114, 2, 18, 1100, 625, 90, 554, 0.254, 9, 1, 0, 0, 10}
|
||||
ranking2 := Ranking{254, 1, 20, 1100, 625, 90, 554, 0.254, 10, 0, 0, 0, 10}
|
||||
db.CreateRanking(&ranking1)
|
||||
@@ -72,6 +71,7 @@ func TestSchedulePdfReport(t *testing.T) {
|
||||
clearDb()
|
||||
defer clearDb()
|
||||
db, _ = OpenDatabase(testDbPath)
|
||||
eventSettings, _ = db.GetEventSettings()
|
||||
match := Match{Type: "practice", DisplayName: "1", Time: time.Unix(0, 0), Red1: 1, Red2: 2, Red3: 3,
|
||||
Blue1: 4, Blue2: 5, Blue3: 6, Blue1IsSurrogate: true, Blue2IsSurrogate: true, Blue3IsSurrogate: true}
|
||||
db.CreateMatch(&match)
|
||||
@@ -106,6 +106,7 @@ func TestTeamsPdfReport(t *testing.T) {
|
||||
clearDb()
|
||||
defer clearDb()
|
||||
db, _ = OpenDatabase(testDbPath)
|
||||
eventSettings, _ = db.GetEventSettings()
|
||||
team := Team{254, "NASA", "The Cheesy Poofs", "San Jose", "CA", "USA", 1999, "Barrage"}
|
||||
db.CreateTeam(&team)
|
||||
|
||||
@@ -114,10 +115,3 @@ func TestTeamsPdfReport(t *testing.T) {
|
||||
assert.Equal(t, 200, recorder.Code)
|
||||
assert.Equal(t, "application/pdf", recorder.HeaderMap["Content-Type"][0])
|
||||
}
|
||||
|
||||
func getHttpResponse(path string) *httptest.ResponseRecorder {
|
||||
recorder := httptest.NewRecorder()
|
||||
req, _ := http.NewRequest("GET", path, nil)
|
||||
newHandler().ServeHTTP(recorder, req)
|
||||
return recorder
|
||||
}
|
||||
|
||||
67
setup_settings.go
Normal file
67
setup_settings.go
Normal file
@@ -0,0 +1,67 @@
|
||||
// Copyright 2014 Team 254. All Rights Reserved.
|
||||
// Author: pat@patfairbank.com (Patrick Fairbank)
|
||||
//
|
||||
// Web routes for configuring the event settings.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"html/template"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// Shows the event settings editing page.
|
||||
func SettingsGetHandler(w http.ResponseWriter, r *http.Request) {
|
||||
renderSettings(w, r, "")
|
||||
}
|
||||
|
||||
// Saves the event settings.
|
||||
func SettingsPostHandler(w http.ResponseWriter, r *http.Request) {
|
||||
err := r.ParseForm()
|
||||
if err != nil {
|
||||
handleWebErr(w, err)
|
||||
return
|
||||
}
|
||||
eventSettings.Name = r.PostFormValue("name")
|
||||
eventSettings.Code = r.PostFormValue("code")
|
||||
match, _ := regexp.MatchString("^#([0-9A-Fa-f]{3}){1,2}$", r.PostFormValue("displayBackgroundColor"))
|
||||
if !match {
|
||||
renderSettings(w, r, "Display background color must be a valid hex color value.")
|
||||
return
|
||||
}
|
||||
eventSettings.DisplayBackgroundColor = r.PostFormValue("displayBackgroundColor")
|
||||
numAlliances, _ := strconv.Atoi(r.PostFormValue("numElimAlliances"))
|
||||
if numAlliances < 2 || numAlliances > 16 {
|
||||
renderSettings(w, r, "Number of alliances must be between 2 and 16.")
|
||||
return
|
||||
}
|
||||
eventSettings.NumElimAlliances = numAlliances
|
||||
eventSettings.SelectionRound1Order = r.PostFormValue("selectionRound1Order")
|
||||
eventSettings.SelectionRound2Order = r.PostFormValue("selectionRound2Order")
|
||||
eventSettings.SelectionRound3Order = r.PostFormValue("selectionRound3Order")
|
||||
err = db.SaveEventSettings(eventSettings)
|
||||
if err != nil {
|
||||
handleWebErr(w, err)
|
||||
return
|
||||
}
|
||||
renderSettings(w, r, "")
|
||||
}
|
||||
|
||||
func renderSettings(w http.ResponseWriter, r *http.Request, errorMessage string) {
|
||||
template, err := template.ParseFiles("templates/settings.html", "templates/base.html")
|
||||
if err != nil {
|
||||
handleWebErr(w, err)
|
||||
return
|
||||
}
|
||||
data := struct {
|
||||
*EventSettings
|
||||
ErrorMessage string
|
||||
}{eventSettings, errorMessage}
|
||||
err = template.ExecuteTemplate(w, "base", data)
|
||||
if err != nil {
|
||||
handleWebErr(w, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
54
setup_settings_test.go
Normal file
54
setup_settings_test.go
Normal file
@@ -0,0 +1,54 @@
|
||||
// Copyright 2014 Team 254. All Rights Reserved.
|
||||
// Author: pat@patfairbank.com (Patrick Fairbank)
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestSetupSettings(t *testing.T) {
|
||||
clearDb()
|
||||
defer clearDb()
|
||||
var err error
|
||||
db, err = OpenDatabase(testDbPath)
|
||||
assert.Nil(t, err)
|
||||
defer db.Close()
|
||||
eventSettings, _ = db.GetEventSettings()
|
||||
|
||||
// Check the default setting values.
|
||||
recorder := getHttpResponse("/setup/settings")
|
||||
assert.Equal(t, 200, recorder.Code)
|
||||
assert.Contains(t, recorder.Body.String(), "Untitled Event")
|
||||
assert.Contains(t, recorder.Body.String(), "UE")
|
||||
assert.Contains(t, recorder.Body.String(), "#00ff00")
|
||||
assert.Contains(t, recorder.Body.String(), "8")
|
||||
|
||||
// Change the settings and check the response.
|
||||
recorder = postHttpResponse("/setup/settings", "name=Chezy Champs&code=CC&displayBackgroundColor=#ff00ff&"+
|
||||
"numElimAlliances=16")
|
||||
assert.Equal(t, 200, recorder.Code)
|
||||
assert.Contains(t, recorder.Body.String(), "Chezy Champs")
|
||||
assert.Contains(t, recorder.Body.String(), "CC")
|
||||
assert.Contains(t, recorder.Body.String(), "#ff00ff")
|
||||
assert.Contains(t, recorder.Body.String(), "16")
|
||||
}
|
||||
|
||||
func TestSetupSettingsInvalidValues(t *testing.T) {
|
||||
clearDb()
|
||||
defer clearDb()
|
||||
var err error
|
||||
db, err = OpenDatabase(testDbPath)
|
||||
assert.Nil(t, err)
|
||||
defer db.Close()
|
||||
eventSettings, _ = db.GetEventSettings()
|
||||
|
||||
// Invalid color value.
|
||||
recorder := postHttpResponse("/setup/settings", "numAlliances=8&displayBackgroundColor=blorpy")
|
||||
assert.Contains(t, recorder.Body.String(), "must be a valid hex color value")
|
||||
|
||||
// Invalid number of alliances.
|
||||
recorder = postHttpResponse("/setup/settings", "numAlliances=1&displayBackgroundColor=#000")
|
||||
assert.Contains(t, recorder.Body.String(), "must be between 2 and 16")
|
||||
}
|
||||
@@ -96,7 +96,11 @@ func TeamEditGetHandler(w http.ResponseWriter, r *http.Request) {
|
||||
handleWebErr(w, err)
|
||||
return
|
||||
}
|
||||
err = template.ExecuteTemplate(w, "base", team)
|
||||
data := struct {
|
||||
*EventSettings
|
||||
*Team
|
||||
}{eventSettings, team}
|
||||
err = template.ExecuteTemplate(w, "base", data)
|
||||
if err != nil {
|
||||
handleWebErr(w, err)
|
||||
return
|
||||
@@ -127,8 +131,7 @@ func TeamEditPostHandler(w http.ResponseWriter, r *http.Request) {
|
||||
team.City = r.PostFormValue("city")
|
||||
team.StateProv = r.PostFormValue("stateProv")
|
||||
team.Country = r.PostFormValue("country")
|
||||
rookieYear, _ := strconv.Atoi(r.PostFormValue("rookieYear"))
|
||||
team.RookieYear = rookieYear
|
||||
team.RookieYear, _ = strconv.Atoi(r.PostFormValue("rookieYear"))
|
||||
team.RobotName = r.PostFormValue("robotName")
|
||||
err = db.SaveTeam(team)
|
||||
if err != nil {
|
||||
@@ -177,9 +180,10 @@ func renderTeams(w http.ResponseWriter, r *http.Request, showErrorMessage bool)
|
||||
return
|
||||
}
|
||||
data := struct {
|
||||
*EventSettings
|
||||
Teams []Team
|
||||
ShowErrorMessage bool
|
||||
}{teams, showErrorMessage}
|
||||
}{eventSettings, teams, showErrorMessage}
|
||||
err = template.ExecuteTemplate(w, "base", data)
|
||||
if err != nil {
|
||||
handleWebErr(w, err)
|
||||
|
||||
@@ -8,7 +8,6 @@ import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
@@ -19,6 +18,7 @@ func TestSetupTeams(t *testing.T) {
|
||||
db, err = OpenDatabase(testDbPath)
|
||||
assert.Nil(t, err)
|
||||
defer db.Close()
|
||||
eventSettings, _ = db.GetEventSettings()
|
||||
|
||||
// Check that there are no teams to start.
|
||||
recorder := getHttpResponse("/setup/teams")
|
||||
@@ -74,6 +74,7 @@ func TestSetupTeamsDisallowModification(t *testing.T) {
|
||||
db, err = OpenDatabase(testDbPath)
|
||||
assert.Nil(t, err)
|
||||
defer db.Close()
|
||||
eventSettings, _ = db.GetEventSettings()
|
||||
db.CreateTeam(&Team{Id: 254, Nickname: "The Cheesy Poofs"})
|
||||
db.CreateMatch(&Match{Type: "qualification"})
|
||||
|
||||
@@ -120,11 +121,3 @@ func TestSetupTeamsBadReqest(t *testing.T) {
|
||||
assert.Equal(t, 400, recorder.Code)
|
||||
assert.Contains(t, recorder.Body.String(), "No such team")
|
||||
}
|
||||
|
||||
func postHttpResponse(path string, body string) *httptest.ResponseRecorder {
|
||||
recorder := httptest.NewRecorder()
|
||||
req, _ := http.NewRequest("POST", path, strings.NewReader(body))
|
||||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded; param=value")
|
||||
newHandler().ServeHTTP(recorder, req)
|
||||
return recorder
|
||||
}
|
||||
|
||||
9
static/css/bootstrap-colorpicker.min.css
vendored
Executable file
9
static/css/bootstrap-colorpicker.min.css
vendored
Executable file
@@ -0,0 +1,9 @@
|
||||
/*!
|
||||
* Bootstrap Colorpicker
|
||||
* http://mjolnic.github.io/bootstrap-colorpicker/
|
||||
*
|
||||
* Originally written by (c) 2012 Stefan Petre
|
||||
* Licensed under the Apache License v2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.txt
|
||||
*
|
||||
*/.colorpicker-saturation{float:left;width:100px;height:100px;cursor:crosshair;background-image:url("../img/bootstrap-colorpicker/saturation.png")}.colorpicker-saturation i{position:absolute;top:0;left:0;display:block;width:5px;height:5px;margin:-4px 0 0 -4px;border:1px solid #000;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px}.colorpicker-saturation i b{display:block;width:5px;height:5px;border:1px solid #fff;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px}.colorpicker-hue,.colorpicker-alpha{float:left;width:15px;height:100px;margin-bottom:4px;margin-left:4px;cursor:row-resize}.colorpicker-hue i,.colorpicker-alpha i{position:absolute;top:0;left:0;display:block;width:100%;height:1px;margin-top:-1px;background:#000;border-top:1px solid #fff}.colorpicker-hue{background-image:url("../img/bootstrap-colorpicker/hue.png")}.colorpicker-alpha{display:none;background-image:url("../img/bootstrap-colorpicker/alpha.png")}.colorpicker{top:0;left:0;z-index:2500;min-width:130px;padding:4px;margin-top:1px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;*zoom:1}.colorpicker:before,.colorpicker:after{display:table;line-height:0;content:""}.colorpicker:after{clear:both}.colorpicker:before{position:absolute;top:-7px;left:6px;display:inline-block;border-right:7px solid transparent;border-bottom:7px solid #ccc;border-left:7px solid transparent;border-bottom-color:rgba(0,0,0,0.2);content:''}.colorpicker:after{position:absolute;top:-6px;left:7px;display:inline-block;border-right:6px solid transparent;border-bottom:6px solid #fff;border-left:6px solid transparent;content:''}.colorpicker div{position:relative}.colorpicker.colorpicker-with-alpha{min-width:140px}.colorpicker.colorpicker-with-alpha .colorpicker-alpha{display:block}.colorpicker-color{height:10px;margin-top:5px;clear:both;background-image:url("../img/bootstrap-colorpicker/alpha.png");background-position:0 100%}.colorpicker-color div{height:10px}.colorpicker-element .input-group-addon i,.colorpicker-element .add-on i{display:inline-block;width:16px;height:16px;vertical-align:text-top;cursor:pointer}.colorpicker.colorpicker-inline{position:relative;z-index:auto;display:inline-block;float:none}.colorpicker.colorpicker-horizontal{width:110px;height:auto;min-width:110px}.colorpicker.colorpicker-horizontal .colorpicker-saturation{margin-bottom:4px}.colorpicker.colorpicker-horizontal .colorpicker-color{width:100px}.colorpicker.colorpicker-horizontal .colorpicker-hue,.colorpicker.colorpicker-horizontal .colorpicker-alpha{float:left;width:100px;height:15px;margin-bottom:4px;margin-left:0;cursor:col-resize}.colorpicker.colorpicker-horizontal .colorpicker-hue i,.colorpicker.colorpicker-horizontal .colorpicker-alpha i{position:absolute;top:0;left:0;display:block;width:1px;height:15px;margin-top:0;background:#fff;border:0}.colorpicker.colorpicker-horizontal .colorpicker-hue{background-image:url("../img/bootstrap-colorpicker/hue-horizontal.png")}.colorpicker.colorpicker-horizontal .colorpicker-alpha{background-image:url("../img/bootstrap-colorpicker/alpha-horizontal.png")}.colorpicker.colorpicker-hidden{display:none}.colorpicker.colorpicker-visible{display:block}.colorpicker-inline.colorpicker-visible{display:inline-block}
|
||||
BIN
static/img/bootstrap-colorpicker/alpha-horizontal.png
Executable file
BIN
static/img/bootstrap-colorpicker/alpha-horizontal.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 3.5 KiB |
BIN
static/img/bootstrap-colorpicker/alpha.png
Executable file
BIN
static/img/bootstrap-colorpicker/alpha.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 3.2 KiB |
BIN
static/img/bootstrap-colorpicker/hue-horizontal.png
Executable file
BIN
static/img/bootstrap-colorpicker/hue-horizontal.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 2.8 KiB |
BIN
static/img/bootstrap-colorpicker/hue.png
Executable file
BIN
static/img/bootstrap-colorpicker/hue.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 2.9 KiB |
BIN
static/img/bootstrap-colorpicker/saturation.png
Executable file
BIN
static/img/bootstrap-colorpicker/saturation.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 8.6 KiB |
1
static/js/bootstrap-colorpicker.min.js
vendored
Executable file
1
static/js/bootstrap-colorpicker.min.js
vendored
Executable file
File diff suppressed because one or more lines are too long
@@ -2,9 +2,10 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>{{template "title" .}}</title>
|
||||
<title>Cheesy Arena - {{.EventSettings.Name}} - {{template "title" .}}</title>
|
||||
<link rel="shortcut icon" href="/static/img/favicon32.png">
|
||||
<link href="/static/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="/static/css/bootstrap-colorpicker.min.css" rel="stylesheet">
|
||||
</head>
|
||||
<body>
|
||||
<div class="navbar navbar-default navbar-static-top" role="navigation">
|
||||
@@ -18,7 +19,7 @@
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Setup</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="#">Event Wizard</a></li>
|
||||
<li><a href="#">Settings</a></li>
|
||||
<li><a href="/setup/settings">Settings</a></li>
|
||||
<li><a href="/setup/teams">Team List</a></li>
|
||||
<li><a href="#">Match Scheduling</a></li>
|
||||
<li><a href="#">Alliance Selection</a></li>
|
||||
@@ -79,6 +80,8 @@
|
||||
</div>
|
||||
<script src="/static/lib/jquery.min.js"></script>
|
||||
<script src="/static/lib/bootstrap.min.js"></script>
|
||||
<script src="/static/js/bootstrap-colorpicker.min.js"></script>
|
||||
{{template "script" .}}
|
||||
</body>
|
||||
</html>
|
||||
{{end}}
|
||||
|
||||
@@ -1,51 +1,51 @@
|
||||
{{define "title"}}Cheesy Arena{{end}}
|
||||
{{define "title"}}Edit Team{{end}}
|
||||
{{define "body"}}
|
||||
<div class="row">
|
||||
<div class="col-lg-6 col-lg-offset-3">
|
||||
<div class="well">
|
||||
<form class="form-horizontal" action="/setup/teams/{{.Id}}/edit" method="POST">
|
||||
<form class="form-horizontal" action="/setup/teams/{{.Team.Id}}/edit" method="POST">
|
||||
<fieldset>
|
||||
<legend>Edit Team {{.Id}}</legend>
|
||||
<legend>Edit Team {{.Team.Id}}</legend>
|
||||
<div class="form-group">
|
||||
<label for="textArea" class="col-lg-3 control-label">Name</label>
|
||||
<div class="col-lg-9">
|
||||
<textarea class="form-control" rows="5" name="name">{{.Name}}</textarea>
|
||||
<textarea class="form-control" rows="5" name="name">{{.Team.Name}}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="inputEmail" class="col-lg-3 control-label">Nickname</label>
|
||||
<div class="col-lg-9">
|
||||
<input type="text" class="form-control" name="nickname" value="{{.Nickname}}">
|
||||
<input type="text" class="form-control" name="nickname" value="{{.Team.Nickname}}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="inputEmail" class="col-lg-3 control-label">City</label>
|
||||
<div class="col-lg-9">
|
||||
<input type="text" class="form-control" name="city" value="{{.City}}">
|
||||
<input type="text" class="form-control" name="city" value="{{.Team.City}}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="inputEmail" class="col-lg-3 control-label">State/Province</label>
|
||||
<div class="col-lg-9">
|
||||
<input type="text" class="form-control" name="stateProv" value="{{.StateProv}}">
|
||||
<input type="text" class="form-control" name="stateProv" value="{{.Team.StateProv}}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="inputEmail" class="col-lg-3 control-label">Country</label>
|
||||
<div class="col-lg-9">
|
||||
<input type="text" class="form-control" name="country" value="{{.Country}}">
|
||||
<input type="text" class="form-control" name="country" value="{{.Team.Country}}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="inputEmail" class="col-lg-3 control-label">Rookie Year</label>
|
||||
<div class="col-lg-9">
|
||||
<input type="text" class="form-control" name="rookieYear" value="{{.RookieYear}}">
|
||||
<input type="text" class="form-control" name="rookieYear" value="{{.Team.RookieYear}}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="inputEmail" class="col-lg-3 control-label">Robot Name</label>
|
||||
<div class="col-lg-9">
|
||||
<input type="text" class="form-control" name="robotName" value="{{.RobotName}}">
|
||||
<input type="text" class="form-control" name="robotName" value="{{.Team.RobotName}}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
@@ -60,3 +60,4 @@
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
{{define "script"}}{{end}}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{{define "title"}}Cheesy Arena{{end}}
|
||||
{{define "title"}}Home{{end}}
|
||||
{{define "body"}}
|
||||
<div class="jumbotron">
|
||||
<h2>Welcome to Cheesy Arena.</h2>
|
||||
@@ -6,3 +6,4 @@
|
||||
or launch displays.</p>
|
||||
</div>
|
||||
{{end}}
|
||||
{{define "script"}}{{end}}
|
||||
|
||||
124
templates/settings.html
Normal file
124
templates/settings.html
Normal file
@@ -0,0 +1,124 @@
|
||||
{{define "title"}}Settings{{end}}
|
||||
{{define "body"}}
|
||||
<div class="row">
|
||||
<div class="col-lg-6 col-lg-offset-3">
|
||||
<div class="well">
|
||||
<form class="form-horizontal" action="/setup/settings" method="POST">
|
||||
<fieldset>
|
||||
<legend>Event Settings</legend>
|
||||
{{if .ErrorMessage}}
|
||||
<div class="alert alert-dismissable alert-danger">
|
||||
<button type="button" class="close" data-dismiss="alert">×</button>
|
||||
{{.ErrorMessage}}
|
||||
</div>
|
||||
{{end}}
|
||||
<div class="form-group">
|
||||
<label for="textArea" class="col-lg-5 control-label">Name</label>
|
||||
<div class="col-lg-7">
|
||||
<input type="text" class="form-control" name="name" value="{{.Name}}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="inputEmail" class="col-lg-5 control-label">Code</label>
|
||||
<div class="col-lg-7">
|
||||
<input type="text" class="form-control" name="code" value="{{.Code}}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="inputEmail" class="col-lg-5 control-label">Display Background Color</label>
|
||||
<div class="col-lg-7">
|
||||
<div class="input-group" id="displayBackgroundColor">
|
||||
<input type="text" class="form-control" name="displayBackgroundColor"
|
||||
value="{{.DisplayBackgroundColor}}">
|
||||
<span class="input-group-addon"><i></i></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="inputEmail" class="col-lg-5 control-label">Number of Alliances</label>
|
||||
<div class="col-lg-7">
|
||||
<input type="text" class="form-control" name="numElimAlliances" value="{{.NumElimAlliances}}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="inputEmail" class="col-lg-5 control-label">Round 1 Selection Order</label>
|
||||
<div class="col-lg-7">
|
||||
<div class="radio">
|
||||
<label>
|
||||
<input type="radio" name="selectionRound1Order" value="F"
|
||||
{{if eq .SelectionRound1Order "F"}}checked{{end}}>
|
||||
First to Last
|
||||
</label>
|
||||
</div>
|
||||
<div class="radio">
|
||||
<label>
|
||||
<input type="radio" name="selectionRound1Order" value="L"
|
||||
{{if eq .SelectionRound1Order "L"}}checked{{end}}>
|
||||
Last to First
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="inputEmail" class="col-lg-5 control-label">Round 2 Selection Order</label>
|
||||
<div class="col-lg-7">
|
||||
<div class="radio">
|
||||
<label>
|
||||
<input type="radio" name="selectionRound2Order" value="F"
|
||||
{{if eq .SelectionRound2Order "F"}}checked{{end}}>
|
||||
First to Last
|
||||
</label>
|
||||
</div>
|
||||
<div class="radio">
|
||||
<label>
|
||||
<input type="radio" name="selectionRound2Order" value="L"
|
||||
{{if eq .SelectionRound2Order "L"}}checked{{end}}>
|
||||
Last to First
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="inputEmail" class="col-lg-5 control-label">Round 3 Selection Order</label>
|
||||
<div class="col-lg-7">
|
||||
<div class="radio">
|
||||
<label>
|
||||
<input type="radio" name="selectionRound3Order" value="F"
|
||||
{{if eq .SelectionRound3Order "F"}}checked{{end}}>
|
||||
First to Last
|
||||
</label>
|
||||
</div>
|
||||
<div class="radio">
|
||||
<label>
|
||||
<input type="radio" name="selectionRound3Order" value="L"
|
||||
{{if eq .SelectionRound3Order "L"}}checked{{end}}>
|
||||
Last to First
|
||||
</label>
|
||||
</div>
|
||||
<div class="radio">
|
||||
<label>
|
||||
<input type="radio" name="selectionRound3Order" value=""
|
||||
{{if eq .SelectionRound3Order ""}}checked{{end}}>
|
||||
None
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-lg-7 col-lg-offset-5">
|
||||
<button type="submit" class="btn btn-info">Save</button>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
{{define "script"}}
|
||||
<script>
|
||||
$(function() {
|
||||
$("#displayBackgroundColor").colorpicker();
|
||||
});
|
||||
</script>
|
||||
{{end}}
|
||||
@@ -1,4 +1,4 @@
|
||||
{{define "title"}}Cheesy Arena{{end}}
|
||||
{{define "title"}}Team List{{end}}
|
||||
{{define "body"}}
|
||||
{{if .ShowErrorMessage}}
|
||||
<div class="alert alert-dismissable alert-danger">
|
||||
@@ -87,3 +87,4 @@
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
{{define "script"}}{{end}}
|
||||
|
||||
7
web.go
7
web.go
@@ -24,7 +24,10 @@ func IndexHandler(w http.ResponseWriter, r *http.Request) {
|
||||
handleWebErr(w, err)
|
||||
return
|
||||
}
|
||||
err = template.ExecuteTemplate(w, "base", nil)
|
||||
data := struct {
|
||||
*EventSettings
|
||||
}{eventSettings}
|
||||
err = template.ExecuteTemplate(w, "base", data)
|
||||
if err != nil {
|
||||
handleWebErr(w, err)
|
||||
return
|
||||
@@ -60,6 +63,8 @@ func ServeWebInterface() {
|
||||
|
||||
func newHandler() http.Handler {
|
||||
router := mux.NewRouter()
|
||||
router.HandleFunc("/setup/settings", SettingsGetHandler).Methods("GET")
|
||||
router.HandleFunc("/setup/settings", SettingsPostHandler).Methods("POST")
|
||||
router.HandleFunc("/setup/teams", TeamsGetHandler).Methods("GET")
|
||||
router.HandleFunc("/setup/teams", TeamsPostHandler).Methods("POST")
|
||||
router.HandleFunc("/setup/teams/clear", TeamsClearHandler).Methods("POST")
|
||||
|
||||
41
web_test.go
Normal file
41
web_test.go
Normal file
@@ -0,0 +1,41 @@
|
||||
// Copyright 2014 Team 254. All Rights Reserved.
|
||||
// Author: pat@patfairbank.com (Patrick Fairbank)
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestIndex(t *testing.T) {
|
||||
clearDb()
|
||||
defer clearDb()
|
||||
var err error
|
||||
db, err = OpenDatabase(testDbPath)
|
||||
assert.Nil(t, err)
|
||||
defer db.Close()
|
||||
eventSettings, _ = db.GetEventSettings()
|
||||
|
||||
recorder := getHttpResponse("/")
|
||||
assert.Equal(t, 200, recorder.Code)
|
||||
assert.Contains(t, recorder.Body.String(), "Cheesy Arena - Untitled Event")
|
||||
}
|
||||
|
||||
func getHttpResponse(path string) *httptest.ResponseRecorder {
|
||||
recorder := httptest.NewRecorder()
|
||||
req, _ := http.NewRequest("GET", path, nil)
|
||||
newHandler().ServeHTTP(recorder, req)
|
||||
return recorder
|
||||
}
|
||||
|
||||
func postHttpResponse(path string, body string) *httptest.ResponseRecorder {
|
||||
recorder := httptest.NewRecorder()
|
||||
req, _ := http.NewRequest("POST", path, strings.NewReader(body))
|
||||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded; param=value")
|
||||
newHandler().ServeHTTP(recorder, req)
|
||||
return recorder
|
||||
}
|
||||
Reference in New Issue
Block a user