create basic frontend
This commit is contained in:
@@ -194,11 +194,14 @@ func main() {
|
|||||||
SELECT 'albums', 500000
|
SELECT 'albums', 500000
|
||||||
WHERE NOT EXISTS (SELECT * FROM sqlite_sequence)
|
WHERE NOT EXISTS (SELECT * FROM sqlite_sequence)
|
||||||
`)
|
`)
|
||||||
orm.Exec(`
|
orm.FirstOrCreate(&db.User{}, db.User{
|
||||||
INSERT INTO users(username, password)
|
Name: "admin",
|
||||||
SELECT 'admin', 'admin'
|
Password: "admin",
|
||||||
WHERE NOT EXISTS (SELECT * FROM users)
|
})
|
||||||
`)
|
orm.FirstOrCreate(&db.User{}, db.User{
|
||||||
|
Name: "senan",
|
||||||
|
Password: "password",
|
||||||
|
})
|
||||||
startTime := time.Now()
|
startTime := time.Now()
|
||||||
tx = orm.Begin()
|
tx = orm.Begin()
|
||||||
err := godirwalk.Walk(os.Args[1], &godirwalk.Options{
|
err := godirwalk.Walk(os.Args[1], &godirwalk.Options{
|
||||||
|
|||||||
@@ -9,6 +9,11 @@ import (
|
|||||||
"github.com/sentriz/gonic/handler"
|
"github.com/sentriz/gonic/handler"
|
||||||
|
|
||||||
_ "github.com/jinzhu/gorm/dialects/sqlite"
|
_ "github.com/jinzhu/gorm/dialects/sqlite"
|
||||||
|
"github.com/wader/gormstore"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
dbCon = db.New()
|
||||||
)
|
)
|
||||||
|
|
||||||
type middleware func(next http.HandlerFunc) http.HandlerFunc
|
type middleware func(next http.HandlerFunc) http.HandlerFunc
|
||||||
@@ -25,17 +30,15 @@ func newChain(wares ...middleware) middleware {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func setSubsonicRoutes(mux *http.ServeMux) {
|
||||||
address := ":5000"
|
|
||||||
cont := handler.Controller{
|
cont := handler.Controller{
|
||||||
DB: db.New(),
|
DB: dbCon,
|
||||||
}
|
}
|
||||||
withWare := newChain(
|
withWare := newChain(
|
||||||
cont.LogConnection,
|
cont.LogConnection,
|
||||||
cont.EnableCORS,
|
cont.EnableCORS,
|
||||||
cont.CheckParameters,
|
cont.CheckParameters,
|
||||||
)
|
)
|
||||||
mux := http.NewServeMux()
|
|
||||||
mux.HandleFunc("/rest/ping", withWare(cont.Ping))
|
mux.HandleFunc("/rest/ping", withWare(cont.Ping))
|
||||||
mux.HandleFunc("/rest/ping.view", withWare(cont.Ping))
|
mux.HandleFunc("/rest/ping.view", withWare(cont.Ping))
|
||||||
mux.HandleFunc("/rest/stream", withWare(cont.Stream))
|
mux.HandleFunc("/rest/stream", withWare(cont.Stream))
|
||||||
@@ -56,11 +59,31 @@ func main() {
|
|||||||
mux.HandleFunc("/rest/getAlbumList2.view", withWare(cont.GetAlbumList))
|
mux.HandleFunc("/rest/getAlbumList2.view", withWare(cont.GetAlbumList))
|
||||||
mux.HandleFunc("/rest/getLicense", withWare(cont.GetLicence))
|
mux.HandleFunc("/rest/getLicense", withWare(cont.GetLicence))
|
||||||
mux.HandleFunc("/rest/getLicense.view", withWare(cont.GetLicence))
|
mux.HandleFunc("/rest/getLicense.view", withWare(cont.GetLicence))
|
||||||
mux.HandleFunc("/", withWare(cont.NotFound))
|
}
|
||||||
// mux.HandleFunc("/rest/getMusicDirectory", withWare(cont.GetMusicDirectory))
|
|
||||||
// mux.HandleFunc("/rest/getMusicDirectory.view", withWare(cont.GetMusicDirectory))
|
func setAdminRoutes(mux *http.ServeMux) {
|
||||||
// mux.HandleFunc("/rest/getIndexes", withWare(cont.GetIndexes))
|
cont := handler.Controller{
|
||||||
// mux.HandleFunc("/rest/getIndexes.view", withWare(cont.GetIndexes))
|
DB: dbCon,
|
||||||
|
SStore: gormstore.New(dbCon, []byte("saynothinboys")),
|
||||||
|
}
|
||||||
|
withWare := newChain(
|
||||||
|
cont.LogConnection,
|
||||||
|
cont.EnableCORS,
|
||||||
|
)
|
||||||
|
server := http.FileServer(http.Dir("static"))
|
||||||
|
mux.Handle("/admin/static/", http.StripPrefix("/admin/static/", server))
|
||||||
|
mux.HandleFunc("/admin/login", withWare(cont.ServeLogin))
|
||||||
|
mux.HandleFunc("/admin/authenticate", withWare(cont.ServeAuthenticate))
|
||||||
|
mux.HandleFunc("/admin/home", withWare(cont.ServeHome))
|
||||||
|
mux.HandleFunc("/admin/create_user", withWare(cont.ServeCreateUser))
|
||||||
|
mux.HandleFunc("/admin/logout", withWare(cont.ServeLogout))
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
address := ":5000"
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
setSubsonicRoutes(mux)
|
||||||
|
setAdminRoutes(mux)
|
||||||
server := &http.Server{
|
server := &http.Server{
|
||||||
Addr: address,
|
Addr: address,
|
||||||
Handler: mux,
|
Handler: mux,
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ type Cover struct {
|
|||||||
|
|
||||||
// User represents the users table
|
// User represents the users table
|
||||||
type User struct {
|
type User struct {
|
||||||
IDBase
|
Base
|
||||||
Username string `gorm:"not null;unique_index"`
|
Name string `gorm:"not null;unique_index"`
|
||||||
Password string
|
Password string
|
||||||
}
|
}
|
||||||
|
|||||||
2
go.mod
2
go.mod
@@ -7,6 +7,7 @@ require (
|
|||||||
github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5 // indirect
|
github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5 // indirect
|
||||||
github.com/go-sql-driver/mysql v1.4.1 // indirect
|
github.com/go-sql-driver/mysql v1.4.1 // indirect
|
||||||
github.com/gofrs/uuid v3.2.0+incompatible // indirect
|
github.com/gofrs/uuid v3.2.0+incompatible // indirect
|
||||||
|
github.com/gorilla/sessions v1.1.3
|
||||||
github.com/jinzhu/gorm v1.9.2
|
github.com/jinzhu/gorm v1.9.2
|
||||||
github.com/jinzhu/inflection v0.0.0-20180308033659-04140366298a // indirect
|
github.com/jinzhu/inflection v0.0.0-20180308033659-04140366298a // indirect
|
||||||
github.com/jinzhu/now v1.0.0 // indirect
|
github.com/jinzhu/now v1.0.0 // indirect
|
||||||
@@ -16,6 +17,7 @@ require (
|
|||||||
github.com/mozillazg/go-unidecode v0.1.1
|
github.com/mozillazg/go-unidecode v0.1.1
|
||||||
github.com/myesui/uuid v1.0.0 // indirect
|
github.com/myesui/uuid v1.0.0 // indirect
|
||||||
github.com/twinj/uuid v1.0.0
|
github.com/twinj/uuid v1.0.0
|
||||||
|
github.com/wader/gormstore v0.0.0-20190302154359-acb787ba3755
|
||||||
golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a // indirect
|
golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a // indirect
|
||||||
google.golang.org/appengine v1.5.0 // indirect
|
google.golang.org/appengine v1.5.0 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
8
go.sum
8
go.sum
@@ -49,6 +49,12 @@ github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57 h1:eqyIo2HjKhKe/mJzTG
|
|||||||
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||||
github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
|
github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
|
||||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||||
|
github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8=
|
||||||
|
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
||||||
|
github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ=
|
||||||
|
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
|
||||||
|
github.com/gorilla/sessions v1.1.3 h1:uXoZdcdA5XdXF3QzuSlheVRUvjl+1rKY7zBXL68L9RU=
|
||||||
|
github.com/gorilla/sessions v1.1.3/go.mod h1:8KCfur6+4Mqcc6S0FEfKuN15Vl5MgXW92AE8ovaJD0w=
|
||||||
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
|
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
|
||||||
github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw=
|
github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw=
|
||||||
github.com/grpc-ecosystem/grpc-gateway v1.6.2/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw=
|
github.com/grpc-ecosystem/grpc-gateway v1.6.2/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw=
|
||||||
@@ -100,6 +106,8 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
|
|||||||
github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA=
|
github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA=
|
||||||
github.com/twinj/uuid v1.0.0 h1:fzz7COZnDrXGTAOHGuUGYd6sG+JMq+AoE7+Jlu0przk=
|
github.com/twinj/uuid v1.0.0 h1:fzz7COZnDrXGTAOHGuUGYd6sG+JMq+AoE7+Jlu0przk=
|
||||||
github.com/twinj/uuid v1.0.0/go.mod h1:mMgcE1RHFUFqe5AfiwlINXisXfDGro23fWdPUfOMjRY=
|
github.com/twinj/uuid v1.0.0/go.mod h1:mMgcE1RHFUFqe5AfiwlINXisXfDGro23fWdPUfOMjRY=
|
||||||
|
github.com/wader/gormstore v0.0.0-20190302154359-acb787ba3755 h1:pNaEDfvqe9W2h4D+xm5f+lnZdao3Rob6O0b8SovpGbE=
|
||||||
|
github.com/wader/gormstore v0.0.0-20190302154359-acb787ba3755/go.mod h1:PbEnTGtqU8NGCALR62gu2+eQYO8zQDEvaMJiPaj5Hic=
|
||||||
go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA=
|
go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA=
|
||||||
go.opencensus.io v0.19.1/go.mod h1:gug0GbSHa8Pafr0d2urOSgoXHZ6x/RUlaiT0d9pqb4A=
|
go.opencensus.io v0.19.1/go.mod h1:gug0GbSHa8Pafr0d2urOSgoXHZ6x/RUlaiT0d9pqb4A=
|
||||||
go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE=
|
go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE=
|
||||||
|
|||||||
77
handler/admin.go
Normal file
77
handler/admin.go
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
package handler
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/sentriz/gonic/db"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (c *Controller) ServeLogin(w http.ResponseWriter, r *http.Request) {
|
||||||
|
session, _ := c.SStore.Get(r, "gonic")
|
||||||
|
renderTemplate(w, r, session, "login", &templateData{})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Controller) ServeAuthenticate(w http.ResponseWriter, r *http.Request) {
|
||||||
|
session, _ := c.SStore.Get(r, "gonic")
|
||||||
|
username := r.FormValue("username")
|
||||||
|
password := r.FormValue("password")
|
||||||
|
if username == "" || password == "" {
|
||||||
|
session.AddFlash("please provide both a username and password")
|
||||||
|
session.Save(r, w)
|
||||||
|
http.Redirect(w, r, "/admin/login", 303)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var user db.User
|
||||||
|
c.DB.Where("name = ?", username).First(&user)
|
||||||
|
if !(username == user.Name && password == user.Password) {
|
||||||
|
session.AddFlash("invalid username / password")
|
||||||
|
session.Save(r, w)
|
||||||
|
http.Redirect(w, r, "/admin/login", 303)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
session.Values["authenticated"] = true
|
||||||
|
session.Values["user"] = user.ID
|
||||||
|
session.Save(r, w)
|
||||||
|
http.Redirect(w, r, "/admin/home", 303)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Controller) ServeHome(w http.ResponseWriter, r *http.Request) {
|
||||||
|
session, _ := c.SStore.Get(r, "gonic")
|
||||||
|
authed, _ := session.Values["authenticated"].(bool)
|
||||||
|
if !authed {
|
||||||
|
session.AddFlash("you are not authenticated")
|
||||||
|
session.Save(r, w)
|
||||||
|
http.Redirect(w, r, "/admin/login", 303)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var data templateData
|
||||||
|
var user db.User
|
||||||
|
c.DB.First(&user, session.Values["user"])
|
||||||
|
data.UserID = user.ID
|
||||||
|
data.Username = user.Name
|
||||||
|
c.DB.Table("album_artists").Count(&data.ArtistCount)
|
||||||
|
c.DB.Table("albums").Count(&data.AlbumCount)
|
||||||
|
c.DB.Table("tracks").Count(&data.TrackCount)
|
||||||
|
c.DB.Find(&data.Users)
|
||||||
|
renderTemplate(w, r, session, "home", &data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Controller) ServeCreateUser(w http.ResponseWriter, r *http.Request) {
|
||||||
|
session, _ := c.SStore.Get(r, "gonic")
|
||||||
|
authed, _ := session.Values["authenticated"].(bool)
|
||||||
|
if !authed {
|
||||||
|
session.AddFlash("you are not authenticated")
|
||||||
|
session.Save(r, w)
|
||||||
|
http.Redirect(w, r, "/admin/login", 303)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
renderTemplate(w, r, session, "create_user", &templateData{})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Controller) ServeLogout(w http.ResponseWriter, r *http.Request) {
|
||||||
|
session, _ := c.SStore.Get(r, "gonic")
|
||||||
|
delete(session.Values, "authenticated")
|
||||||
|
delete(session.Values, "user")
|
||||||
|
session.Save(r, w)
|
||||||
|
http.Redirect(w, r, "/admin/login", 303)
|
||||||
|
}
|
||||||
@@ -4,16 +4,55 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"encoding/xml"
|
"encoding/xml"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"html/template"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/jinzhu/gorm"
|
"github.com/gorilla/sessions"
|
||||||
|
"github.com/sentriz/gonic/db"
|
||||||
"github.com/sentriz/gonic/subsonic"
|
"github.com/sentriz/gonic/subsonic"
|
||||||
|
|
||||||
|
"github.com/jinzhu/gorm"
|
||||||
|
"github.com/wader/gormstore"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
templates = make(map[string]*template.Template)
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
templates["login"] = template.Must(template.ParseFiles(
|
||||||
|
filepath.Join("templates", "layout.tmpl"),
|
||||||
|
filepath.Join("templates", "admin", "login.tmpl"),
|
||||||
|
))
|
||||||
|
templates["home"] = template.Must(template.ParseFiles(
|
||||||
|
filepath.Join("templates", "layout.tmpl"),
|
||||||
|
filepath.Join("templates", "user.tmpl"),
|
||||||
|
filepath.Join("templates", "admin", "home.tmpl"),
|
||||||
|
))
|
||||||
|
templates["create_user"] = template.Must(template.ParseFiles(
|
||||||
|
filepath.Join("templates", "layout.tmpl"),
|
||||||
|
filepath.Join("templates", "user.tmpl"),
|
||||||
|
filepath.Join("templates", "admin", "create_user.tmpl"),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
type Controller struct {
|
type Controller struct {
|
||||||
DB *gorm.DB
|
DB *gorm.DB
|
||||||
|
SStore *gormstore.Store
|
||||||
|
Templates map[string]*template.Template
|
||||||
|
}
|
||||||
|
|
||||||
|
type templateData struct {
|
||||||
|
Flashes []interface{}
|
||||||
|
UserID uint
|
||||||
|
Username string
|
||||||
|
ArtistCount uint
|
||||||
|
AlbumCount uint
|
||||||
|
TrackCount uint
|
||||||
|
Users []*db.User
|
||||||
}
|
}
|
||||||
|
|
||||||
func getStrParam(r *http.Request, key string) string {
|
func getStrParam(r *http.Request, key string) string {
|
||||||
@@ -40,7 +79,8 @@ func getIntParamOr(r *http.Request, key string, or int) int {
|
|||||||
return val
|
return val
|
||||||
}
|
}
|
||||||
|
|
||||||
func respondRaw(w http.ResponseWriter, r *http.Request, code int, sub *subsonic.Response) {
|
func respondRaw(w http.ResponseWriter, r *http.Request,
|
||||||
|
code int, sub *subsonic.Response) {
|
||||||
res := subsonic.MetaResponse{
|
res := subsonic.MetaResponse{
|
||||||
Response: sub,
|
Response: sub,
|
||||||
}
|
}
|
||||||
@@ -73,12 +113,26 @@ func respondRaw(w http.ResponseWriter, r *http.Request, code int, sub *subsonic.
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func respond(w http.ResponseWriter, r *http.Request, sub *subsonic.Response) {
|
func respond(w http.ResponseWriter, r *http.Request,
|
||||||
|
sub *subsonic.Response) {
|
||||||
respondRaw(w, r, http.StatusOK, sub)
|
respondRaw(w, r, http.StatusOK, sub)
|
||||||
}
|
}
|
||||||
|
|
||||||
func respondError(w http.ResponseWriter, r *http.Request, code uint64, message string) {
|
func respondError(w http.ResponseWriter, r *http.Request,
|
||||||
|
code uint64, message string) {
|
||||||
respondRaw(w, r, http.StatusBadRequest, subsonic.NewError(
|
respondRaw(w, r, http.StatusBadRequest, subsonic.NewError(
|
||||||
code, message,
|
code, message,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func renderTemplate(w http.ResponseWriter, r *http.Request,
|
||||||
|
s *sessions.Session, name string, data *templateData) {
|
||||||
|
flashes := s.Flashes()
|
||||||
|
s.Save(r, w)
|
||||||
|
data.Flashes = flashes
|
||||||
|
err := templates[name].ExecuteTemplate(w, "layout", data)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, fmt.Sprintf("500 when executing: %v", err), 500)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ func (c *Controller) CheckParameters(next http.HandlerFunc) http.HandlerFunc {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
user := db.User{
|
user := db.User{
|
||||||
Username: username,
|
Name: username,
|
||||||
}
|
}
|
||||||
err := c.DB.Where(user).First(&user).Error
|
err := c.DB.Where(user).First(&user).Error
|
||||||
if gorm.IsRecordNotFoundError(err) {
|
if gorm.IsRecordNotFoundError(err) {
|
||||||
|
|||||||
BIN
static/images/gonic.png
Normal file
BIN
static/images/gonic.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 236 KiB |
7
static/stylesheets/awsm.css
Normal file
7
static/stylesheets/awsm.css
Normal file
File diff suppressed because one or more lines are too long
77
static/stylesheets/main.css
Normal file
77
static/stylesheets/main.css
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
div {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
max-width: 800px;
|
||||||
|
margin: 0 auto;
|
||||||
|
height: 100vh;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
form {
|
||||||
|
max-width: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
#content > * {
|
||||||
|
margin: 1rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.right {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.light {
|
||||||
|
color: #00000082;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mono {
|
||||||
|
font-family: monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pre {
|
||||||
|
white-space: pre;
|
||||||
|
}
|
||||||
|
|
||||||
|
.box {
|
||||||
|
background-color: #0000000a;
|
||||||
|
}
|
||||||
|
|
||||||
|
.padded {
|
||||||
|
padding: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#header {
|
||||||
|
/* background-color: #fdc71b08; */
|
||||||
|
background-image: linear-gradient(white, #fdad1b0d);
|
||||||
|
border-bottom: 1px solid;
|
||||||
|
padding-top: 3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#header img {
|
||||||
|
max-width: 580px;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
#footer {
|
||||||
|
background-color: #fdad1b0d;
|
||||||
|
border-top: 1px solid;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
#flashes {
|
||||||
|
background-color: #fd1b1b29;
|
||||||
|
}
|
||||||
|
|
||||||
|
#login-form {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
#login-form input[type=submit] {
|
||||||
|
width: 8rem;
|
||||||
|
}
|
||||||
3
static/stylesheets/tacit.css
Normal file
3
static/stylesheets/tacit.css
Normal file
File diff suppressed because one or more lines are too long
12
templates/admin/create_user.tmpl
Normal file
12
templates/admin/create_user.tmpl
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
{{ define "title" }}home{{ end }}
|
||||||
|
|
||||||
|
{{ define "user" }}
|
||||||
|
<div class="padded box mono">
|
||||||
|
<div>
|
||||||
|
<span><u>create new user</u></span>
|
||||||
|
</div>
|
||||||
|
<div class="right">
|
||||||
|
<span class="pre">howdy</span><br/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
||||||
34
templates/admin/home.tmpl
Normal file
34
templates/admin/home.tmpl
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
{{ define "title" }}home{{ end }}
|
||||||
|
|
||||||
|
{{ define "user" }}
|
||||||
|
<div class="padded box mono">
|
||||||
|
<div>
|
||||||
|
<span><u>stats</u></span>
|
||||||
|
</div>
|
||||||
|
<div class="right">
|
||||||
|
<span class="pre">artists: {{ printf "%7v" .ArtistCount }}</span><br/>
|
||||||
|
<span class="pre">albums: {{ printf "%7v" .AlbumCount }}</span><br/>
|
||||||
|
<span class="pre">tracks: {{ printf "%7v" .TrackCount }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="padded box mono">
|
||||||
|
<div>
|
||||||
|
<span><u>last.fm</u></span>
|
||||||
|
</div>
|
||||||
|
<div class="right">
|
||||||
|
<span class="pre">unlinked</span><br/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="padded box mono">
|
||||||
|
<div>
|
||||||
|
<span><u>users</u></span>
|
||||||
|
</div>
|
||||||
|
<div class="right">
|
||||||
|
{{ range $user := .Users }}
|
||||||
|
<span class="pre">{{ $user.Name }} <span class="light">created</span> <u>{{ $user.CreatedAt.Format "Jan 02, 2006" }}</u> <a href="/admin/change_password">change password</a></span><br/>
|
||||||
|
{{ end }}
|
||||||
|
<br>
|
||||||
|
<a href="/admin/create_user" class="button">create new</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
||||||
12
templates/admin/login.tmpl
Normal file
12
templates/admin/login.tmpl
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
{{ define "title" }}gonic{{ end }}
|
||||||
|
|
||||||
|
{{ define "content" }}
|
||||||
|
<div class="light">
|
||||||
|
<span>login</span>
|
||||||
|
</div>
|
||||||
|
<form id="login-form" action="/admin/authenticate" method="post">
|
||||||
|
<input type="text" id="username" name="username" placeholder="username">
|
||||||
|
<input type="password" id="password" name="password" placeholder="password">
|
||||||
|
<input type="submit" value="login">
|
||||||
|
</form>
|
||||||
|
{{ end }}
|
||||||
30
templates/layout.tmpl
Normal file
30
templates/layout.tmpl
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
{{ define "layout" }}
|
||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>{{ template "title" }}</title>
|
||||||
|
<link rel="stylesheet" href="/admin/static/stylesheets/awsm.css">
|
||||||
|
<link rel="stylesheet" href="/admin/static/stylesheets/main.css">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div>
|
||||||
|
<div id="header">
|
||||||
|
<img src="/admin/static/images/gonic.png">
|
||||||
|
</div>
|
||||||
|
<div id="content">
|
||||||
|
{{ if .Flashes }}
|
||||||
|
<div id="flashes">
|
||||||
|
<p><b>warning:</b> {{ index .Flashes 0 }}</p>
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
||||||
|
{{ template "content" . }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="footer" class="padded">
|
||||||
|
<p>senan kelly, 2019 | <a href="https://github.com/sentriz/gonic">github</a></p>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
{{ end }}
|
||||||
8
templates/user.tmpl
Normal file
8
templates/user.tmpl
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
{{ define "title" }}home{{ end }}
|
||||||
|
|
||||||
|
{{ define "content" }}
|
||||||
|
<div class="light right">
|
||||||
|
<span>welcome <u>{{ .Username }}</u> | <a href="/admin/logout">logout</a></span>
|
||||||
|
</div>
|
||||||
|
{{ template "user" . }}
|
||||||
|
{{ end }}
|
||||||
Reference in New Issue
Block a user