Completed template system, added login/logout
This commit is contained in:
@@ -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
@@ -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
@@ -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
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user