1
0
Fork 0
forked from boyska/feedpanel

Merge branch 'ui-refactor'

This commit is contained in:
boyska 2018-12-11 13:29:30 +01:00
commit 6fdff2109e
12 changed files with 202 additions and 26 deletions

View file

@ -9,4 +9,5 @@ FROM busybox
WORKDIR /usr/bin/
COPY --from=builder /go/bin/panelcli /usr/bin/
COPY --from=builder /go/bin/userpanel /usr/bin/
COPY panelui/res/ /go/src/git.lattuga.net/boyska/feedpanel/panelui/res/
ENTRYPOINT ["./userpanel"]

View file

@ -2,37 +2,31 @@ package main
import (
"fmt"
"html/template"
"net/http"
"os"
"github.com/namsral/flag"
"git.lattuga.net/boyska/feedpanel/panelui"
"github.com/urfave/negroni"
)
var helloTmpl *template.Template
func init() {
helloTmpl = template.Must(template.New("hello").Parse(`
<html><body>Hello, {{.User}}
<p>Go to <a href="/tt-rss/">Feed Reader</a></p>
</body></html>`))
}
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
user := r.Context().Value(keyUser)
if user == nil {
panic("Authentication middleware failed!")
}
w.WriteHeader(200)
w.Header().Set("Content-type", "text/html")
helloTmpl.Execute(w, map[string]interface{}{"User": user})
})
fs := flag.NewFlagSetWithEnvPrefix(os.Args[0], "PANEL", 0)
allowedName := fs.String("allowed-name", "", "Name allowed to forward auth")
addr := fs.String("listen-addr", ":8000", "Address to listen on")
fs.Parse(os.Args[1:])
ha := HeaderAuth{AllowedNames: []string{"feedati-fe"}, RequireUser: true}
var allowedNames []string
if *allowedName != "" {
allowedNames = []string{*allowedName}
} else {
allowedNames = []string{}
}
ha := panelui.HeaderAuth{AllowedNames: allowedNames, RequireUser: true}
n := negroni.New(negroni.NewRecovery(), negroni.NewLogger(), ha)
n.UseHandler(mux)
addr := ":8000"
fmt.Println("Listening on", addr)
http.ListenAndServe(addr, n)
n.UseHandler(panelui.GetMux())
fmt.Println("Listening on", *addr)
http.ListenAndServe(*addr, n)
}

4
go.mod
View file

@ -1,10 +1,14 @@
module git.lattuga.net/boyska/feedpanel
require (
github.com/GeertJohan/go.rice v0.0.0-20170420135705-c02ca9a983da
github.com/daaku/go.zipexe v0.0.0-20150329023125-a5fe2436ffcb // indirect
github.com/go-pg/pg v6.15.0+incompatible
github.com/howeyc/gopass v0.0.0-20170109162249-bf9dde6d0d2c
github.com/jinzhu/inflection v0.0.0-20180308033659-04140366298a // indirect
github.com/kardianos/osext v0.0.0-20170510131534-ae77be60afb1 // indirect
github.com/kr/pretty v0.1.0 // indirect
github.com/namsral/flag v1.7.4-pre
github.com/onsi/gomega v1.4.2 // indirect
github.com/pkg/errors v0.8.0
github.com/urfave/negroni v1.0.0

8
go.sum
View file

@ -1,3 +1,7 @@
github.com/GeertJohan/go.rice v0.0.0-20170420135705-c02ca9a983da h1:UVU3a9pRUyLdnBtn60WjRl0s4SEyJc2ChCY56OAR6wI=
github.com/GeertJohan/go.rice v0.0.0-20170420135705-c02ca9a983da/go.mod h1:DgrzXonpdQbfN3uYaGz1EG4Sbhyum/MMIn6Cphlh2bw=
github.com/daaku/go.zipexe v0.0.0-20150329023125-a5fe2436ffcb h1:tUf55Po0vzOendQ7NWytcdK0VuzQmfAgvGBUOQvN0WA=
github.com/daaku/go.zipexe v0.0.0-20150329023125-a5fe2436ffcb/go.mod h1:U0vRfAucUOohvdCxt5MWLF+TePIL0xbCkbKIiV8TQCE=
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/go-pg/pg v6.15.0+incompatible h1:jwhQz62bkCc+VqBXyUTHzcESgACF6S9qsHAJigcLYzQ=
@ -10,11 +14,15 @@ github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/jinzhu/inflection v0.0.0-20180308033659-04140366298a h1:eeaG9XMUvRBYXJi4pg1ZKM7nxc5AfXfojeLLW7O5J3k=
github.com/jinzhu/inflection v0.0.0-20180308033659-04140366298a/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
github.com/kardianos/osext v0.0.0-20170510131534-ae77be60afb1 h1:PJPDf8OUfOK1bb/NeTKd4f1QXZItOX389VN3B6qC8ro=
github.com/kardianos/osext v0.0.0-20170510131534-ae77be60afb1/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/namsral/flag v1.7.4-pre h1:b2ScHhoCUkbsq0d2C15Mv+VU8bl8hAXV8arnWiOHNZs=
github.com/namsral/flag v1.7.4-pre/go.mod h1:OXldTctbM6SWH1K899kPZcf65KxJiD7MsceFUpB5yDo=
github.com/onsi/ginkgo v1.6.0 h1:Ix8l273rp3QzYgXSR+c8d1fTG7UPgYkOSELPhiY/YGw=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v1.4.2 h1:3mYCb7aPxS/RU7TI1y4rkEn1oKmPRjNJLNEXgw7MH2I=

29
panelui/main.go Normal file
View file

@ -0,0 +1,29 @@
package panelui
import (
"net/http"
"github.com/GeertJohan/go.rice"
)
var templates, static *rice.Box
func init() {
templates = rice.MustFindBox("res/templates")
static = rice.MustFindBox("res/static")
}
// GetMux returns a ready-to-use mux
func GetMux() *http.ServeMux {
mux := http.NewServeMux()
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
user := r.Context().Value(keyUser)
if user == nil {
panic("Authentication middleware failed!")
}
templateExecute(w, r, "home.html", templates,
map[string]interface{}{"User": user})
})
mux.Handle("/static/", http.StripPrefix("/static/", http.FileServer(static.HTTPBox())))
return mux
}

View file

@ -1,4 +1,4 @@
package main
package panelui
import (
"context"

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,8 @@
/*!
* Bootstrap Reboot v4.1.3 (https://getbootstrap.com/)
* Copyright 2011-2018 The Bootstrap Authors
* Copyright 2011-2018 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
*/*,::after,::before{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;-ms-overflow-style:scrollbar;-webkit-tap-highlight-color:transparent}@-ms-viewport{width:device-width}article,aside,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-size:1rem;font-weight:400;line-height:1.5;color:#212529;text-align:left;background-color:#fff}[tabindex="-1"]:focus{outline:0!important}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem}p{margin-top:0;margin-bottom:1rem}abbr[data-original-title],abbr[title]{text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;border-bottom:0}address{margin-bottom:1rem;font-style:normal;line-height:inherit}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}dfn{font-style:italic}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#007bff;text-decoration:none;background-color:transparent;-webkit-text-decoration-skip:objects}a:hover{color:#0056b3;text-decoration:underline}a:not([href]):not([tabindex]){color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus,a:not([href]):not([tabindex]):hover{color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus{outline:0}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em}pre{margin-top:0;margin-bottom:1rem;overflow:auto;-ms-overflow-style:scrollbar}figure{margin:0 0 1rem}img{vertical-align:middle;border-style:none}svg{overflow:hidden;vertical-align:middle}table{border-collapse:collapse}caption{padding-top:.75rem;padding-bottom:.75rem;color:#6c757d;text-align:left;caption-side:bottom}th{text-align:inherit}label{display:inline-block;margin-bottom:.5rem}button{border-radius:0}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}[type=reset],[type=submit],button,html [type=button]{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{padding:0;border-style:none}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=date],input[type=datetime-local],input[type=month],input[type=time]{-webkit-appearance:listbox}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;max-width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit;color:inherit;white-space:normal}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-cancel-button,[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item;cursor:pointer}template{display:none}[hidden]{display:none!important}
/*# sourceMappingURL=bootstrap-reboot.min.css.map */

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,69 @@
<html>
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="{{.BaseURL}}static/css/bootstrap.min.css" />
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<a class="navbar-brand" href="#">Grog</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav mr-auto">
<li class="nav-item active"> <a class="nav-link" href="#">Home <span class="sr-only">(current)</span></a> </li>
</ul>
<ul class="navbar-nav ml-auto">
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
{{.User}}
</a>
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
<a class="dropdown-item" href="/logout.html">Logout</a>
<a class="dropdown-item" href="#">Profile</a>
</div>
</ul>
</div>
</nav>
<div class="container">
<div class="row">
<div class="col-sm-4">
<!-- TODO: hai delle notizie non lette... -->
<p>Go to <a class="btn btn-primary" href="/tt-rss/">Feed Reader</a></p>
</div>
</div>
<!-- IF hai uno spazio abilitato... -->
<div class="row row-pubblicazione"><!-- Il tuo spazio -->
<div class="col-sm-6">
<div class="card">
<h3>Feed che stai pubblicando nel tuo spazio</h3>
<ul>
<li>Antani</li>
<li>Sblindola</li>
<li>Tapioco</li>
</ul>
<a class="btn btn-light">Aggiungi un nuovo feed</a>
</div>
</div>
<div class="col-sm-6">
<div class="card">
<h3>La tua lista dei feed è attualmente pubblica</h3>
Questo vuol dire che sul tuo spazio chiunque potrà vedere tutti i feed che stai seguendo.
<a class="btn btn-small btn-info">Maggiori informazioni</a>
<a class="btn btn-small btn-warning">Nascondi lista di feed</a>
</div>
</div>
</div>
</div>
<!-- TODO: move to static/ -->
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="{{.BaseURL}}static/js/bootstrap.min.js"></script>
</body>
</html>

42
panelui/template_utils.go Normal file
View file

@ -0,0 +1,42 @@
package panelui
import (
"fmt"
"html/template"
"net/http"
"os"
"strings"
"github.com/GeertJohan/go.rice"
)
func templateGet(w http.ResponseWriter, r *http.Request, name string, box *rice.Box) (*template.Template, error) {
tmplRaw, err := box.Bytes(name)
if err != nil {
w.WriteHeader(500)
fmt.Fprintln(os.Stderr, err)
fmt.Fprintln(w, "Unexpected error processing template")
return nil, err
}
tmpl := template.Must(template.New(name).Parse(string(tmplRaw)))
return tmpl, nil
}
func templateExecute(w http.ResponseWriter, r *http.Request, name string, box *rice.Box, data map[string]interface{}) error {
tmpl, err := templateGet(w, r, name, box)
if err != nil {
return err
}
// TODO: run template _before_ writing it (to a buffer) so that appropriate error can be checked
w.WriteHeader(200)
if strings.HasSuffix(name, ".html") {
w.Header().Set("Content-type", "text/html")
}
if pref, has := os.LookupEnv("PANEL_PREFIX"); has {
data["BaseURL"] = pref
} else {
data["BaseURL"] = "/"
}
tmpl.Execute(w, data)
return nil
}