internal/relui: adjust new workflow page HTML and CSS

Make its presentation more friendly for entering single-line string
parameters of longer lengths, as will happen in the tweet workflows.

Add a confirmation prompt when submitting a workflow, to avoid the risk
that a single rogue misclick may otherwise immediately submit and start
the workflow (similar to how releasebot asks for Y/n confirmation right
before taking important action).

Add a new server parameter that allows controlling the site header
programmatically. This will be used in the next CL in the stack.

Change-Id: Icede1454c7b07341d139d953b9c4ea40d4f1c369
Reviewed-on: https://go-review.googlesource.com/c/build/+/385615
Trust: Dmitri Shuralyov <dmitshur@golang.org>
Run-TryBot: Dmitri Shuralyov <dmitshur@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Alex Rakoczy <alex@golang.org>
This commit is contained in:
Dmitri Shuralyov 2022-02-14 09:55:11 -05:00
Родитель e9b946c2ca
Коммит 3831dabe9d
6 изменённых файлов: 46 добавлений и 15 удалений

Просмотреть файл

@ -57,7 +57,7 @@ func main() {
log.Fatalf("url.Parse(%q) = %v, %v", *baseURL, base, err)
}
}
s := relui.NewServer(db, w, base)
s := relui.NewServer(db, w, base, relui.SiteHeader{Title: "Go Releases"})
if err != nil {
log.Fatalf("relui.NewServer() = %v", err)
}

Просмотреть файл

@ -50,7 +50,8 @@ h6 {
font-size: 1.5rem;
margin: 0;
}
.Workflows {
.Workflows,
.NewWorkflow {
padding: 0 0.625rem;
}
.Workflows-header {
@ -97,6 +98,22 @@ h6 {
margin-top: 1rem;
padding: 0 0.5rem;
}
.NewWorkflow-workflowSelect {
padding-bottom: 0.5rem;
border-bottom: 0.0625rem solid #d6d6d6;
}
.NewWorkflow-parameter {
padding: 0.5rem 0;
display: flex;
gap: 0.5rem;
}
.NewWorkflow-parameter input {
flex-grow: 1;
}
.NewWorkflow-workflowCreate {
padding-top: 0.5rem;
border-top: 0.0625rem solid #d6d6d6;
}
.TaskList {
align-items: center;
border-bottom: 0.0625rem solid #d6d6d6;

Просмотреть файл

@ -5,14 +5,14 @@
-->
<!DOCTYPE html>
<html lang="en">
<title>Go Releases</title>
<title>{{.SiteHeader.Title}}</title>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="stylesheet" href="{{baseLink "/static/styles.css"}}" />
<script async defer src="{{baseLink "/static/site.js"}}"></script>
<body class="Site">
<header class="Site-header">
<header class="Site-header {{.SiteHeader.CSSClass}}">
<div class="Header">
<h1 class="Header-title">Go Releases</h1>
<h1 class="Header-title">{{.SiteHeader.Title}}</h1>
</div>
</header>
<main class="Site-content">

Просмотреть файл

@ -6,7 +6,7 @@
{{define "content"}}
<section class="NewWorkflow">
<h2>New Go Release</h2>
<form action="{{baseLink "/workflows/new"}}" method="get">
<form class="NewWorkflow-workflowSelect" action="{{baseLink "/workflows/new"}}" method="get">
<label for="workflow.name">Workflow:</label>
<select id="workflow.name" name="workflow.name" onchange="this.form.submit()">
<option value="">Select Workflow</option>
@ -24,12 +24,14 @@
<form action="{{baseLink "/workflows/create"}}" method="post">
<input type="hidden" id="workflow.name" name="workflow.name" value="{{$.Name}}" />
{{range $name := .Selected.ParameterNames}}
<div class="NewWorkflow-Parameter">
<div class="NewWorkflow-parameter">
<label for="workflow.params.{{$name}}">{{$name}}</label>
<input id="workflow.params.{{$name}}" name="workflow.params.{{$name}}" value="" />
</div>
{{end}}
<input name="workflow.create" type="submit" value="Create" />
<div class="NewWorkflow-workflowCreate">
<input name="workflow.create" type="submit" value="Create" onclick="return confirm('This will create and immediately run this workflow.\n\nReady to proceed?')" />
</div>
</form>
{{end}}
</section>

Просмотреть файл

@ -43,12 +43,19 @@ func fileServerHandler(fs fs.FS, next http.Handler) http.Handler {
})
}
// SiteHeader configures the relui site header.
type SiteHeader struct {
Title string // Site title. For example, "Go Releases".
CSSClass string // Site header CSS class name. Optional.
}
// Server implements the http handlers for relui.
type Server struct {
db *pgxpool.Pool
m *http.ServeMux
w *Worker
baseURL *url.URL
header SiteHeader
// mux used if baseURL is set
bm *http.ServeMux
@ -56,13 +63,15 @@ type Server struct {
newWorkflowTmpl *template.Template
}
// NewServer initializes a server with the provided connection pool.
func NewServer(p *pgxpool.Pool, w *Worker, baseURL *url.URL) *Server {
// NewServer initializes a server with the provided connection pool,
// worker, base URL and site header.
func NewServer(p *pgxpool.Pool, w *Worker, baseURL *url.URL, header SiteHeader) *Server {
s := &Server{
db: p,
m: new(http.ServeMux),
w: w,
baseURL: baseURL,
header: header,
}
helpers := map[string]interface{}{
"baseLink": s.BaseLink,
@ -109,6 +118,7 @@ func (s *Server) BaseLink(target string) string {
}
type homeResponse struct {
SiteHeader SiteHeader
Workflows []db.Workflow
WorkflowTasks map[uuid.UUID][]db.Task
TaskLogs map[uuid.UUID]map[string][]db.TaskLog
@ -170,10 +180,11 @@ func (s *Server) buildHomeResponse(ctx context.Context) (*homeResponse, error) {
}
wftlogs[l.WorkflowID][l.TaskName] = append(wftlogs[l.WorkflowID][l.TaskName], l)
}
return &homeResponse{Workflows: ws, WorkflowTasks: wfTasks, TaskLogs: wftlogs}, nil
return &homeResponse{SiteHeader: s.header, Workflows: ws, WorkflowTasks: wfTasks, TaskLogs: wftlogs}, nil
}
type newWorkflowResponse struct {
SiteHeader SiteHeader
Definitions map[string]*workflow.Definition
Name string
}
@ -186,6 +197,7 @@ func (n *newWorkflowResponse) Selected() *workflow.Definition {
func (s *Server) newWorkflowHandler(w http.ResponseWriter, r *http.Request) {
out := bytes.Buffer{}
resp := &newWorkflowResponse{
SiteHeader: s.header,
Definitions: s.w.dh.Definitions(),
Name: r.FormValue("workflow.name"),
}

Просмотреть файл

@ -116,7 +116,7 @@ func TestServerHomeHandler(t *testing.T) {
req := httptest.NewRequest(http.MethodGet, "/", nil)
w := httptest.NewRecorder()
s := NewServer(p, NewWorker(NewDefinitionHolder(), p, &PGListener{p}), nil)
s := NewServer(p, NewWorker(NewDefinitionHolder(), p, &PGListener{p}), nil, SiteHeader{})
s.homeHandler(w, req)
resp := w.Result()
@ -152,7 +152,7 @@ func TestServerNewWorkflowHandler(t *testing.T) {
req := httptest.NewRequest(http.MethodGet, u.String(), nil)
w := httptest.NewRecorder()
s := NewServer(nil, NewWorker(NewDefinitionHolder(), nil, nil), nil)
s := NewServer(nil, NewWorker(NewDefinitionHolder(), nil, nil), nil, SiteHeader{})
s.newWorkflowHandler(w, req)
resp := w.Result()
@ -219,7 +219,7 @@ func TestServerCreateWorkflowHandler(t *testing.T) {
rec := httptest.NewRecorder()
q := db.New(p)
s := NewServer(p, NewWorker(NewDefinitionHolder(), p, &PGListener{p}), nil)
s := NewServer(p, NewWorker(NewDefinitionHolder(), p, &PGListener{p}), nil, SiteHeader{})
s.createWorkflowHandler(rec, req)
resp := rec.Result()
@ -411,7 +411,7 @@ func TestServerBaseLink(t *testing.T) {
if err != nil {
t.Fatalf("url.Parse(%q) = %v, %v, wanted no error", c.baseURL, base, err)
}
s := NewServer(nil, nil, base)
s := NewServer(nil, nil, base, SiteHeader{})
got := s.BaseLink(c.target)
if got != c.want {