зеркало из https://github.com/golang/build.git
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:
Родитель
e9b946c2ca
Коммит
3831dabe9d
|
@ -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 {
|
||||
|
|
Загрузка…
Ссылка в новой задаче