Completed template system, added login/logout

This commit is contained in:
2017-10-06 21:32:26 +02:00
parent 8c8aad3312
commit 2d8bdf9643
19 changed files with 399 additions and 51 deletions
+39
View File
@@ -0,0 +1,39 @@
package model
import (
"strings"
)
// PageCategory represents a page category
type PageCategory struct {
Key string
Plural string
Icon string
}
// URLRoot is the "folder" used for searching within the category
func (category *PageCategory) URLRoot() string {
return strings.ToLower(category.Plural)
}
// PageCategories are used by the view model and page to enforce
// a limited selection of categories. I may move it to a configuration
// or the database, but for now I think this list is pretty fixed
var PageCategories = []PageCategory{
{"OoC", "OoC", "ooc"},
{"Info", "Info", "info"},
{"News", "News", "news"},
{"Item", "Items", "item"},
{"Document", "Documents", "document"},
{"Background", "Background", "background"},
{"Story", "Stories", "story"},
}
var pageCategories []string
// init setups pageCategories
func init() {
pageCategories := make([]string, len(PageCategories))
for i, category := range PageCategories {
pageCategories[i] = category.Key
}
}
+92 -2
View File
@@ -56,9 +56,42 @@ func ListHeaders() ([]Header, error) {
return results, nil
}
// ListHeadersByTag lists all headers that has the tag
func ListHeadersByTag(tag *Tag) ([]Header, error) {
// ListHeadersByCategory grabs all the pages in the given category
func ListHeadersByCategory(category string) ([]Header, error) {
const query = `
SELECT page.id,page.name,author,category,fictional_date,publish_date,edit_date,dated,tag.id,tag.type,tag.name
FROM page
LEFT JOIN page_tag ON (page.id = page_tag.page_id AND page_tag.primary = true)
LEFT JOIN tag ON (tag.id = page_tag.tag_id)
WHERE page.specific=false AND page.published=true AND page.unlisted=false AND page.category = ?;
`
db := server.Main.DB
rows, err := db.Query(query, category)
if err != nil {
return nil, err
}
defer rows.Close()
results := make([]Header, 0, 64)
header := Header{}
for rows.Next() {
err := parseHeader(&header, rows)
if err != nil {
return nil, err
}
results = append(results, header)
}
return results, nil
}
// ListHeadersByTag lists all headers that has the tag. Leave the category empty
// to not filter by it
func ListHeadersByTag(category string, tag *Tag) ([]Header, error) {
const query1 = `
SELECT page.id,page.name,page.author,page.category,page.fictional_date,page.publish_date,page.edit_date,page.dated,tag.id,tag.type,tag.name
FROM page_tag
RIGHT JOIN page ON page.id = page_tag.page_id
@@ -66,6 +99,14 @@ func ListHeadersByTag(tag *Tag) ([]Header, error) {
LEFT JOIN (tag AS tag) ON (tag.id = pt2.tag_id)
WHERE page_tag.tag_id=?
`
const query2 = `
SELECT page.id,page.name,page.author,page.category,page.fictional_date,page.publish_date,page.edit_date,page.dated,tag.id,tag.type,tag.name
FROM page_tag
RIGHT JOIN page ON page.id = page_tag.page_id
LEFT JOIN (page_tag AS pt2) ON (page.id = pt2.page_id AND pt2.primary = true)
LEFT JOIN (tag AS tag) ON (tag.id = pt2.tag_id)
WHERE page_tag.tag_id=? AND page.category=?
`
if tag == nil {
return nil, errors.New("no tag")
@@ -73,6 +114,11 @@ func ListHeadersByTag(tag *Tag) ([]Header, error) {
db := server.Main.DB
query := query1
if category != "" {
query = query2
}
rows, err := db.Query(query, tag.ID)
if err != nil {
return nil, err
@@ -93,6 +139,50 @@ func ListHeadersByTag(tag *Tag) ([]Header, error) {
return results, nil
}
// ListHeadersByTags searches for the first tag, then filters the result based on the
// others. There is room for improvement in this function, but I'll have to judge whether
// there will be a need for that.
func ListHeadersByTags(category string, tags []Tag) ([]Header, error) {
if len(tags) == 0 {
return nil, errors.New("no tags")
}
headers, err := ListHeadersByTag(category, &tags[0])
if err != nil {
return nil, err
}
if len(headers) == 0 {
return headers, nil
}
for _, tag := range tags[1:] {
headers2, err := ListHeadersByTag(category, &tag)
if err != nil {
return nil, err
}
results := make([]Header, 0, len(headers))
for _, header := range headers {
found := false
for _, header2 := range headers2 {
if header.ID == header2.ID {
found = true
break
}
}
if found {
results = append(results, header)
}
}
headers = results
}
return headers, nil
}
func parseHeader(header *Header, rows *sql.Rows) error {
var tagID, tagName, tagType string
var fictionalDate, publishDate, editDate string
+2 -14
View File
@@ -14,18 +14,6 @@ import (
"github.com/russross/blackfriday"
)
// PageCategories are used by the view model and page to enforce
// a limited selection of categories. I may move it to a configuration
var PageCategories = []string{
"OoC",
"Story",
"Background",
"Document",
"News",
"Item",
"Info",
}
// PageTypes describes how the source is rendered. For now it's only markdown,
// but who knows what the future holds.
var PageTypes = []string{
@@ -62,7 +50,7 @@ type Page struct {
// Defaults fills in the default details for a page, suited for populating a form
func (page *Page) Defaults() {
page.Category = PageCategories[0]
page.Category = PageCategories[0].Key
page.Dated = true
page.Published = true
@@ -220,7 +208,7 @@ func (page *Page) ParseForm(form url.Values) []error {
errors := make([]error, 0, 4)
page.cachedOutput = ""
err := formparser.Select(form.Get("category"), &page.Category, PageCategories, page.Category != "")
err := formparser.Select(form.Get("category"), &page.Category, pageCategories, page.Category != "")
if err != nil {
errors = append(errors, fmt.Errorf("Category: %s", err))
}
+2 -2
View File
@@ -131,7 +131,7 @@ func TestPage(t *testing.T) {
})
t.Run("ListHeadersByTag", func(t *testing.T) {
headers, err := ListHeadersByTag(testPageTags[1])
headers, err := ListHeadersByTag("", testPageTags[1])
if err != nil {
t.Error(err)
}
@@ -160,7 +160,7 @@ func TestPage(t *testing.T) {
}
// Make a fake tag and make sure that doesn't return stuff
headers, err = ListHeadersByTag(&Tag{ID: generate.ID()})
headers, err = ListHeadersByTag("", &Tag{ID: generate.ID()})
if err != nil {
t.Error(err)
}
+7
View File
@@ -2,6 +2,7 @@ package model
import (
"errors"
"strings"
"git.aiterp.net/AiteRP/aitestory/server"
"git.aiterp.net/gisle/wrouter/generate"
@@ -108,6 +109,12 @@ func (tag *Tag) Validate() error {
return nil
}
// Hook returns the url friendly name, which is pretty much just
// adding underscores to it.
func (tag Tag) Hook() string {
return strings.Replace(tag.Name, " ", "_", -1)
}
// FindTag finds a tag by ID
func FindTag(key string, id string) (*Tag, error) {
db := server.Main.DB
+23 -1
View File
@@ -96,7 +96,29 @@ func TestTag(t *testing.T) {
t.Run("FindByID", func(t *testing.T) {
tag, err := FindTag("id", id)
if err != nil {
t.Log("Failed to get tags:", err)
t.Log("Failed to find tag:", err)
t.Fail()
}
if tag == nil {
t.Log("No tag found")
t.Fail()
return
}
t.Logf("Tag found: %+v", tag)
if tag.Name != name || tag.ID != id {
t.Error("Incorrect tag")
t.Fail()
}
testTag = tag
})
t.Run("FindByName", func(t *testing.T) {
tag, err := FindTag("name", name)
if err != nil {
t.Log("Failed to find tag:", err)
t.Fail()
}
if tag == nil {