forked from boyska/feedpanel
Merge branch 'ui-refactor'
This commit is contained in:
commit
6fdff2109e
12 changed files with 202 additions and 26 deletions
|
@ -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"]
|
||||
|
|
|
@ -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
4
go.mod
|
@ -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
8
go.sum
|
@ -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
29
panelui/main.go
Normal 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
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package main
|
||||
package panelui
|
||||
|
||||
import (
|
||||
"context"
|
7
panelui/res/static/css/bootstrap-grid.min.css
vendored
Normal file
7
panelui/res/static/css/bootstrap-grid.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
8
panelui/res/static/css/bootstrap-reboot.min.css
vendored
Normal file
8
panelui/res/static/css/bootstrap-reboot.min.css
vendored
Normal 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 */
|
7
panelui/res/static/css/bootstrap.min.css
vendored
Normal file
7
panelui/res/static/css/bootstrap.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
7
panelui/res/static/js/bootstrap.min.js
vendored
Normal file
7
panelui/res/static/js/bootstrap.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
69
panelui/res/templates/home.html
Normal file
69
panelui/res/templates/home.html
Normal 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
42
panelui/template_utils.go
Normal 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
|
||||
}
|
Loading…
Reference in a new issue