sklad: styling, add a basic view for containers

This commit is contained in:
Přemysl Eric Janouch 2019-04-14 01:05:05 +02:00
parent bcfb9fbc2b
commit 7eb84cd937
Signed by: p
GPG Key ID: A0420B94F92B9493
4 changed files with 84 additions and 20 deletions

View File

@ -7,18 +7,33 @@
html, body { min-height: 100vh; } html, body { min-height: 100vh; }
body { padding: 1em; box-sizing: border-box; body { padding: 1em; box-sizing: border-box;
margin: 0 auto; max-width: 50em; margin: 0 auto; max-width: 50em;
border-left: 1px solid gray; border-right: 1px solid gray; border-left: 1px solid #ccc; border-right: 1px solid #ccc;
font-family: sans-serif; } font-family: sans-serif; }
header { display: flex; justify-content: space-between; align-items: center;
flex-wrap: wrap; margin: -1em -1em 0 -1em; padding: 0 1em;
background: linear-gradient(0deg, #fff, #eee); }
header * { display: inline-block; }
a { color: inherit; }
</style> </style>
</head> </head>
<body> <body>
<header>
<h1>sklad</h1> <h1>sklad</h1>
{{ if .LoggedIn }} {{ if .LoggedIn }}
<a href=/>Obaly</a>
<a href=/series>Řady</a>
<form method=get action=/search>
<input type=text name=q><input type=submit value="Hledat">
</form>
<form method=post action=/logout> <form method=post action=/logout>
<input type=submit value="Odhlásit"> <input type=submit value="Odhlásit">
</form> </form>
{{ end }} {{ end }}
</header>
{{ template "Content" . }} {{ template "Content" . }}
</body> </body>

View File

@ -1,6 +1,27 @@
{{ define "Title" }}Přehled{{ end }} {{ define "Title" }}Přehled{{ end }}
{{ define "Content" }} {{ define "Content" }}
<p>TODO {{ if .Id }}
<h2>{{ .Id }}</h2>
{{ else }}
<h2>Obaly nejvyšší úrovně</h2>
{{ end }}
{{ if .Description }}
<p>{{ .Description }}
{{ end }}
{{ if .Children }}
{{ range .Children }}
<fieldset>
<h3><a href="/container?id={{ .Id }}">{{ .Id }}</a></h3>
{{ if .Description }}
<p>{{ .Description }}
{{ end }}
</fieldset>
{{ end }}
{{ else }}
<p>Obal je prázdný.
{{ end }}
{{ end }} {{ end }}

View File

@ -1,6 +1,8 @@
{{ define "Title" }}Přihlášení{{ end }} {{ define "Title" }}Přihlášení{{ end }}
{{ define "Content" }} {{ define "Content" }}
<h2>Přihlášení</h2>
<form method=post> <form method=post>
<label for=password>Heslo:</label> <label for=password>Heslo:</label>
<input type=password name=password id=password> <input type=password name=password id=password>

View File

@ -11,22 +11,31 @@ import (
"time" "time"
) )
var ( var templates = map[string]*template.Template{}
templates = map[string]*template.Template{}
)
// TODO: Consider wrapping the data object in something that always contains
// a LoggedIn member, so that we don't need to duplicate it.
func executeTemplate(name string, w io.Writer, data interface{}) { func executeTemplate(name string, w io.Writer, data interface{}) {
if err := templates[name].Execute(w, data); err != nil { if err := templates[name].Execute(w, data); err != nil {
panic(err) panic(err)
} }
} }
func handleLogin(w http.ResponseWriter, r *http.Request) { func wrap(inner func(http.ResponseWriter, *http.Request)) func(
http.ResponseWriter, *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
if err := r.ParseForm(); err != nil { if err := r.ParseForm(); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError) http.Error(w, err.Error(), http.StatusInternalServerError)
return return
} }
if r.Method == http.MethodGet {
w.Header().Set("Cache-Control", "no-store")
}
inner(w, r)
}
}
func handleLogin(w http.ResponseWriter, r *http.Request) {
redirect := r.FormValue("redirect") redirect := r.FormValue("redirect")
if redirect == "" { if redirect == "" {
redirect = "/" redirect = "/"
@ -45,7 +54,7 @@ func handleLogin(w http.ResponseWriter, r *http.Request) {
switch r.Method { switch r.Method {
case http.MethodGet: case http.MethodGet:
w.Header().Set("Cache-Control", "no-store") // We're just going to render the template.
case http.MethodPost: case http.MethodPost:
if r.FormValue("password") == db.Password { if r.FormValue("password") == db.Password {
session.LoggedIn = true session.LoggedIn = true
@ -78,10 +87,27 @@ func handleContainer(w http.ResponseWriter, r *http.Request) {
return return
} }
children := []*Container{}
id := ContainerId(r.FormValue("id"))
description := ""
if id == "" {
children = db.Containers
} else if container, ok := indexContainer[id]; ok {
children = indexChildren[id]
description = container.Description
}
params := struct { params := struct {
LoggedIn bool LoggedIn bool
Id ContainerId
Description string
Children []*Container
}{ }{
LoggedIn: true, LoggedIn: true,
Id: id,
Description: description,
Children: children,
} }
executeTemplate("container.tmpl", w, &params) executeTemplate("container.tmpl", w, &params)
@ -127,11 +153,11 @@ func main() {
// - https://stackoverflow.com/a/33880971/76313 // - https://stackoverflow.com/a/33880971/76313
// - POST /label?id=UA1 // - POST /label?id=UA1
http.HandleFunc("/", sessionWrap(handleContainer)) http.HandleFunc("/", sessionWrap(wrap(handleContainer)))
http.HandleFunc("/container", sessionWrap(handleContainer)) http.HandleFunc("/container", sessionWrap(wrap(handleContainer)))
http.HandleFunc("/login", handleLogin) http.HandleFunc("/login", wrap(handleLogin))
http.HandleFunc("/logout", sessionWrap(handleLogout)) http.HandleFunc("/logout", sessionWrap(wrap(handleLogout)))
log.Fatalln(http.ListenAndServe(address, nil)) log.Fatalln(http.ListenAndServe(address, nil))
} }