added sections overview

This commit is contained in:
ston1th 2019-01-22 21:45:32 +01:00
commit 799ff0fb2f
16 changed files with 181 additions and 66 deletions

View file

@ -22,6 +22,23 @@ func (p Pages) Len() int { return len(p) }
func (p Pages) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
func (p Pages) Less(i, j int) bool { return p[i].StoreTitle < p[j].StoreTitle }
type UpdatedPages []Page
func (p UpdatedPages) Len() int { return len(p) }
func (p UpdatedPages) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
func (p UpdatedPages) Less(i, j int) bool { return p[i].Updated > p[j].Updated }
type Section struct {
Section string
Pages UpdatedPages
}
type Sections []Section
func (s Sections) Len() int { return len(s) }
func (s Sections) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s Sections) Less(i, j int) bool { return s[i].Section < s[j].Section }
type User struct {
Username string
Password string

View file

@ -8,12 +8,12 @@ import (
)
var reservedUsers = []string{
"all",
"blacklist",
"login",
"logout",
"new",
"search",
"sections",
"user",
"view",
"wiki",

View file

@ -8,6 +8,7 @@ import (
"git.giftfish.de/ston1th/gowiki/pkg/render"
"git.giftfish.de/ston1th/gowiki/pkg/store"
"sort"
"strings"
)
const pagePrefix = "page/"
@ -21,9 +22,42 @@ var (
errDeleteIndexPage = errors.New("db: index page can not be deleted")
)
func (db *DB) GetAllPages(username string) (pages core.Pages) {
func (db *DB) GetAllSections(username string) (sections core.Sections) {
m := make(map[string]core.UpdatedPages)
db.store.ForEach(func(k string, _ []byte) error {
if trim, ok := hasTrimPrefix(k, pagePrefix); ok {
if trim == core.IndexURI {
return nil
}
p, err := db.getPage(trim, username)
if err == nil {
s := trim[:strings.Index(trim, "/")]
if _, ok := m[s]; !ok {
m[s] = core.UpdatedPages{}
}
m[s] = append(m[s], *p)
}
}
return nil
})
for s, p := range m {
sort.Sort(p)
l := len(p)
if l > 5 {
l = 5
}
sections = append(sections, core.Section{s, p[:l]})
}
sort.Sort(sections)
return
}
func (db *DB) GetAllSectionPages(section, username string) (pages core.Pages, err error) {
db.store.ForEach(func(k string, _ []byte) error {
if trim, ok := hasTrimPrefix(k, pagePrefix); ok {
if !strings.HasPrefix(trim, section+"/") {
return nil
}
if trim == core.IndexURI {
return nil
}
@ -34,6 +68,10 @@ func (db *DB) GetAllPages(username string) (pages core.Pages) {
}
return nil
})
if len(pages) == 0 {
err = errPageNotFound
return
}
sort.Sort(pages)
return
}

View file

@ -205,14 +205,31 @@ func searchHandler(ctx *Context) {
}
}
func allHandler(ctx *Context) {
ctx.Template("allHandler")
func sectionsHandler(ctx *Context) {
ctx.Template("sectionsHandler")
ctx.Data = webData{
Title: "All Pages",
BodyTitle: "All Pages",
Title: "All Sections",
BodyTitle: "All Sections",
Admin: ctx.Admin(),
}
ctx.Data.Data = ctx.Srv.DB.GetAllPages(ctx.User())
ctx.Data.Data = ctx.Srv.DB.GetAllSections(ctx.User())
ctx.Exec()
}
func sectionHandler(ctx *Context) {
ctx.Template("sectionHandler")
section := ctx.Var("section")
ctx.Data = webData{
Title: section,
BodyTitle: section,
Admin: ctx.Admin(),
}
var err error
ctx.Data.Data, err = ctx.Srv.DB.GetAllSectionPages(section, ctx.User())
if err != nil {
ctx.NotFound()
return
}
ctx.Exec()
}

View file

@ -24,6 +24,11 @@ var routes = []route{
staticHandler,
[]string{"GET"},
},
{
"/sections",
sectionsHandler,
[]string{"GET"},
},
{
"/search",
searchHandler,
@ -35,11 +40,6 @@ var routes = []route{
pageNewHandler),
[]string{"GET", "POST"},
},
{
"/all",
allHandler,
[]string{"GET"},
},
{
"/login",
loginHandler,
@ -109,6 +109,11 @@ var routes = []route{
pageHandler),
[]string{"GET"},
},
{
"/{section:[a-zA-Z0-9]+}",
sectionHandler,
[]string{"GET"},
},
{
"/{section:[a-zA-Z0-9]+}/{title:[a-zA-Z0-9+-]+}",
pageHandler,

View file

@ -12,37 +12,6 @@ import (
)
const (
all = `{{define "body"}}
<div class="page-header">
<div class="row">
<h2>{{.BodyTitle}}</h2>
</div>
</div>
{{if .Data}}
<div class="row mt-5">
{{$idx0 := index .Data 0}}
{{$owner := $idx0.Owner}}
<strong>{{$owner}}</strong>
</div>
<div class="row">
<ul type="circle">
{{range $item := .Data}}
{{if ne $owner $item.Owner}}
{{$owner = $item.Owner}}
</ul>
</div>
<div class="row">
<strong>{{$owner}}</strong>
</div>
<div class="row">
<ul type="circle">
{{end}}
<li><a href="/{{$item.StoreTitle}}"><b>{{$item.Title}}</b></a></li>
{{end}}
</ul>
</div>
{{end}}
{{end}}`
forbidden = `{{define "body"}}
<div class="page-header">
<div class="row">
@ -65,7 +34,7 @@ const (
<head>
<title>GoWiki | {{.Title}}</title>
<link rel="stylesheet" type="text/css" href="/bootstrap.css" media="screen" integrity="sha256-NeLmQ7cX66J4MdtgGlG3O/TgvsSyP1b9WbaQtxYZUbQ="></link>
<link rel="stylesheet" type="text/css" href="/custom.css" media="screen" integrity="sha256-/SZfW8eVqFuioMg+QXacvK1Zc3XLtT5LGu9tMle65Jc="></link>
<link rel="stylesheet" type="text/css" href="/custom.css" media="screen" integrity="sha256-o0xveJH8qNnWr/39Jnx97yDlYrvjuUnzE4q3p+94Yp4="></link>
<meta name="theme-color" content="#375a7f">
<meta name="description" content="{{.Title}}">
</head>
@ -166,7 +135,7 @@ const (
menu = `{{define "menu"}}
<ul class="navbar-nav">
<li class="nav-item"><a class="nav-link" href="/wiki/Index">Index</a></li>
<li class="nav-item"><a class="nav-link" href="/all">All Pages</a></li>
<li class="nav-item"><a class="nav-link" href="/sections">Sections</a></li>
{{if .Login}}
<li class="nav-item"><a class="nav-link" href="/new">New Page</a></li>
{{end}}
@ -488,6 +457,48 @@ const (
{{end}}
</div>
</div>
{{end}}`
section = `{{define "body"}}
<div class="page-header">
<div class="row">
<h2>{{.BodyTitle}}</h2>
</div>
</div>
{{if .Data}}
<div class="row">
<ul type="circle">
{{range $item := .Data}}
<li><a href="/{{$item.StoreTitle}}"><b>{{$item.Title}}</b></a></li>
{{end}}
</ul>
</div>
{{end}}
{{end}}`
sections = `{{define "body"}}
<div class="page-header">
<div class="row">
<h2>{{.BodyTitle}}</h2>
</div>
</div>
{{if .Data}}
<div class="row">
{{range $index, $item := .Data}}
<div class="col-xs-4 section">
<div class="card border-primary mx-auto">
<div class="card-header">
<strong><a href="/{{$item.Section}}">{{$item.Section}}</a></strong>
</div>
<div class="card-body">
{{range $page := $item.Pages}}
<strong><a href="/{{$page.StoreTitle}}">{{$page.Title}}</a></strong><br>
{{end}}
</div>
</div>
</div>
<div class="offset-1"></div>
{{end}}
</div>
{{end}}
{{end}}`
userDel = `{{define "body"}}
{{if .Data}}
@ -499,7 +510,7 @@ const (
<strong>Delete {{.Data.Username}}?</strong>
</div>
<div class="card-body">
<p>You are about to delete <a href="/user/edit/{{.Data.Username}}">{{.Data.Username}}</a>.<br>This will also remove all private pages of this user.</p>
<p>You are about to delete user <a href="/{{.Data.Username}}">{{.Data.Username}}</a>.<br>This will also remove all private pages of this user.</p>
<form class="form-horizontal" action="/user/del/{{.Data.Username}}" method="post">
<input type="hidden" name="token" value="{{.Token}}">
<button class="btn btn-sm btn-danger" type="submit">Delete</button>
@ -571,6 +582,7 @@ const (
{{end}}
</div>
</div>
</div>
</div>
{{end}}
{{end}}`
@ -660,6 +672,7 @@ const (
</form>
</div>
</div>
</div>
</div>
{{end}}`
userTotp = `{{define "body"}}
@ -696,6 +709,7 @@ const (
</form>
</div>
</div>
</div>
</div>
{{end}}
{{end}}`
@ -838,6 +852,10 @@ html, body, .container, .content {
.proper-content {
padding-top: 40px;
}
.section {
margin-bottom: 20px;
width: 250px;
}
.wrapper {
min-height: 100%;
height: auto !important;
@ -883,7 +901,8 @@ func (s *HTTPServer) loadTemplates() {
s.templ["loginHandler"] = parse(index, menu, login)
s.templ["loginTotpHandler"] = parse(index, menu, loginTotp)
s.templ["searchHandler"] = parse(index, menu, search)
s.templ["allHandler"] = parse(index, menu, all)
s.templ["sectionsHandler"] = parse(index, menu, sections)
s.templ["sectionHandler"] = parse(index, menu, section)
s.templ["pageHandler"] = parse(index, menu, page)
s.templ["pageNewHandler"] = parse(index, menu, pageNew)
s.templ["pageEditHandler"] = parse(index, menu, pageEdit)

View file

@ -74,7 +74,8 @@ func (s *HTTPServer) loadTemplates() {
s.templ["loginHandler"] = parse(index, menu, login)
s.templ["loginTotpHandler"] = parse(index, menu, loginTotp)
s.templ["searchHandler"] = parse(index, menu, search)
s.templ["allHandler"] = parse(index, menu, all)
s.templ["sectionsHandler"] = parse(index, menu, sections)
s.templ["sectionHandler"] = parse(index, menu, section)
s.templ["pageHandler"] = parse(index, menu, page)
s.templ["pageNewHandler"] = parse(index, menu, pageNew)
s.templ["pageEditHandler"] = parse(index, menu, pageEdit)

View file

@ -125,6 +125,10 @@ html, body, .container, .content {
.proper-content {
padding-top: 40px;
}
.section {
margin-bottom: 20px;
width: 250px;
}
.wrapper {
min-height: 100%;
height: auto !important;

View file

@ -3,7 +3,7 @@
<head>
<title>GoWiki | {{.Title}}</title>
<link rel="stylesheet" type="text/css" href="/bootstrap.css" media="screen" integrity="sha256-NeLmQ7cX66J4MdtgGlG3O/TgvsSyP1b9WbaQtxYZUbQ="></link>
<link rel="stylesheet" type="text/css" href="/custom.css" media="screen" integrity="sha256-/SZfW8eVqFuioMg+QXacvK1Zc3XLtT5LGu9tMle65Jc="></link>
<link rel="stylesheet" type="text/css" href="/custom.css" media="screen" integrity="sha256-o0xveJH8qNnWr/39Jnx97yDlYrvjuUnzE4q3p+94Yp4="></link>
<meta name="theme-color" content="#375a7f">
<meta name="description" content="{{.Title}}">
</head>

View file

@ -1,7 +1,7 @@
{{define "menu"}}
<ul class="navbar-nav">
<li class="nav-item"><a class="nav-link" href="/wiki/Index">Index</a></li>
<li class="nav-item"><a class="nav-link" href="/all">All Pages</a></li>
<li class="nav-item"><a class="nav-link" href="/sections">Sections</a></li>
{{if .Login}}
<li class="nav-item"><a class="nav-link" href="/new">New Page</a></li>
{{end}}

View file

@ -5,24 +5,9 @@
</div>
</div>
{{if .Data}}
<div class="row mt-5">
{{$idx0 := index .Data 0}}
{{$owner := $idx0.Owner}}
<strong>{{$owner}}</strong>
</div>
<div class="row">
<ul type="circle">
{{range $item := .Data}}
{{if ne $owner $item.Owner}}
{{$owner = $item.Owner}}
</ul>
</div>
<div class="row">
<strong>{{$owner}}</strong>
</div>
<div class="row">
<ul type="circle">
{{end}}
<li><a href="/{{$item.StoreTitle}}"><b>{{$item.Title}}</b></a></li>
{{end}}
</ul>

26
templates/sections.html Normal file
View file

@ -0,0 +1,26 @@
{{define "body"}}
<div class="page-header">
<div class="row">
<h2>{{.BodyTitle}}</h2>
</div>
</div>
{{if .Data}}
<div class="row">
{{range $index, $item := .Data}}
<div class="col-xs-4 section">
<div class="card border-primary mx-auto">
<div class="card-header">
<strong><a href="/{{$item.Section}}">{{$item.Section}}</a></strong>
</div>
<div class="card-body">
{{range $page := $item.Pages}}
<strong><a href="/{{$page.StoreTitle}}">{{$page.Title}}</a></strong><br>
{{end}}
</div>
</div>
</div>
<div class="offset-1"></div>
{{end}}
</div>
{{end}}
{{end}}

View file

@ -8,7 +8,7 @@
<strong>Delete {{.Data.Username}}?</strong>
</div>
<div class="card-body">
<p>You are about to delete <a href="/user/edit/{{.Data.Username}}">{{.Data.Username}}</a>.<br>This will also remove all private pages of this user.</p>
<p>You are about to delete user <a href="/{{.Data.Username}}">{{.Data.Username}}</a>.<br>This will also remove all private pages of this user.</p>
<form class="form-horizontal" action="/user/del/{{.Data.Username}}" method="post">
<input type="hidden" name="token" value="{{.Token}}">
<button class="btn btn-sm btn-danger" type="submit">Delete</button>

View file

@ -57,6 +57,7 @@
{{end}}
</div>
</div>
</div>
</div>
{{end}}
{{end}}

View file

@ -29,5 +29,6 @@
</form>
</div>
</div>
</div>
</div>
{{end}}

View file

@ -32,6 +32,7 @@
</form>
</div>
</div>
</div>
</div>
{{end}}
{{end}}