Page is done
This commit is contained in:
+7
-7
@@ -21,13 +21,13 @@ func (category *PageCategory) URLRoot() string {
|
||||
// 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", "OoC content is for announcements, scheduling, general information, or anything that is not in-universe"},
|
||||
{"Info", "Info", "info", "Information gained during and between RP sessions"},
|
||||
{"News", "News", "news", "News stories that might be pertinent to ongoing plots"},
|
||||
{"Item", "Items", "item", "Items relevant to plots, that is more than just a document saved on a character's own omni-tool"},
|
||||
{"Document", "Documents", "document", "Data files, shadow broker dossiers, and other data that is not inside an item"},
|
||||
{"Background", "Background", "background", "Rumors, suspicious persons, or inter-RP occurences that may be noticed"},
|
||||
{"Story", "Stories", "story", "Background stories and inter-RP character intearactions"},
|
||||
{"OoC", "OoC", "O", "OoC content is for announcements, scheduling, general information, or anything that is not in-universe"},
|
||||
{"Info", "Info", "i", "Information gained during and between RP sessions"},
|
||||
{"News", "News", "N", "News stories that might be pertinent to ongoing plots"},
|
||||
{"Item", "Items", "I", "Items relevant to plots, that is more than just a document saved on a character's own omni-tool"},
|
||||
{"Document", "Document", "D", "Data files, shadow broker dossiers, and other data that is not inside an item"},
|
||||
{"Background", "Background", "B", "Rumors, suspicious persons, or inter-RP occurences that may be noticed"},
|
||||
{"Story", "Stories", "S", "Background stories and inter-RP character intearactions"},
|
||||
}
|
||||
var pageCategories []string
|
||||
|
||||
|
||||
+20
-5
@@ -23,6 +23,17 @@ type Header struct {
|
||||
PrimaryTag *Tag `json:"primaryTag"`
|
||||
}
|
||||
|
||||
// CategoryInfo gets information about the category
|
||||
func (header *Header) CategoryInfo() PageCategory {
|
||||
for _, category := range PageCategories {
|
||||
if category.Key == header.Category {
|
||||
return category
|
||||
}
|
||||
}
|
||||
|
||||
return PageCategory{"Unknown", "Unknown", "?", ""}
|
||||
}
|
||||
|
||||
// ListHeaders grabs all the general pages from
|
||||
// the database to list them
|
||||
func ListHeaders() ([]Header, error) {
|
||||
@@ -31,7 +42,8 @@ func ListHeaders() ([]Header, error) {
|
||||
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;
|
||||
WHERE page.specific=false AND page.published=true AND page.unlisted=false
|
||||
ORDER BY page.fictional_date DESC
|
||||
`
|
||||
|
||||
db := server.Main.DB
|
||||
@@ -63,7 +75,8 @@ func ListHeadersByCategory(category string) ([]Header, error) {
|
||||
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 = ?;
|
||||
WHERE page.specific=false AND page.published=true AND page.unlisted=false AND page.category = ?
|
||||
ORDER BY page.fictional_date DESC
|
||||
`
|
||||
|
||||
db := server.Main.DB
|
||||
@@ -97,7 +110,8 @@ func ListHeadersByTag(category string, tag *Tag) ([]Header, error) {
|
||||
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=?
|
||||
WHERE page_tag.tag_id=? AND page.unlisted=false AND page.published=true
|
||||
ORDER BY page.fictional_date DESC
|
||||
`
|
||||
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
|
||||
@@ -105,7 +119,8 @@ func ListHeadersByTag(category string, tag *Tag) ([]Header, error) {
|
||||
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=?
|
||||
WHERE page_tag.tag_id=? AND page.category=? AND page.unlisted=false AND page.published=true
|
||||
ORDER BY page.fictional_date DESC
|
||||
`
|
||||
|
||||
if tag == nil {
|
||||
@@ -190,7 +205,7 @@ func parseHeader(header *Header, rows *sql.Rows) error {
|
||||
|
||||
rows.Scan(&header.ID, &header.Name, &header.Author, &header.Category, &fictionalDate, &publishDate, &editDate, &header.Dated, &tagID, &tagType, &tagName)
|
||||
if tagID != "" {
|
||||
header.PrimaryTag = &Tag{tagID, tagName, tagType}
|
||||
header.PrimaryTag = &Tag{tagID, tagType, tagName}
|
||||
}
|
||||
|
||||
header.FictionalDate, err = time.Parse("2006-01-02 15:04:05", fictionalDate)
|
||||
|
||||
+30
-10
@@ -4,6 +4,7 @@ import (
|
||||
"database/sql"
|
||||
"errors"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
@@ -46,6 +47,7 @@ type Page struct {
|
||||
|
||||
prevTags []Tag
|
||||
cachedOutput string
|
||||
primaryTag *Tag
|
||||
}
|
||||
|
||||
// Defaults fills in the default details for a page, suited for populating a form
|
||||
@@ -99,6 +101,10 @@ func (page *Page) Insert() error {
|
||||
}
|
||||
}
|
||||
|
||||
if len(page.Tags) > 0 {
|
||||
page.primaryTag = &page.Tags[0]
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -157,6 +163,9 @@ func (page *Page) Update() error {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if len(page.Tags) > 0 {
|
||||
page.primaryTag = &page.Tags[0]
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -184,29 +193,33 @@ func (page *Page) Delete() error {
|
||||
}
|
||||
|
||||
// Content parses the content of the page
|
||||
func (page *Page) Content() (string, error) {
|
||||
if page.cachedOutput != "" {
|
||||
return page.cachedOutput, nil
|
||||
}
|
||||
|
||||
func (page *Page) Content() (template.HTML, error) {
|
||||
if page.Type == "Markdown" {
|
||||
// TODO: Convert [[Ehanis Tioran]] to [Ehanis Tioran](https://wiki.aiterp.net/index.php?title=Ehanis%20Tioran)
|
||||
|
||||
unsafe := blackfriday.MarkdownCommon([]byte(page.Source))
|
||||
page.cachedOutput = string(bluemonday.UGCPolicy().SanitizeBytes(unsafe))
|
||||
output := string(bluemonday.UGCPolicy().SanitizeBytes(unsafe))
|
||||
|
||||
return page.cachedOutput, nil
|
||||
return template.HTML(output), nil
|
||||
}
|
||||
|
||||
return "", fmt.Errorf("Page type '%s' is not supported", page.Type)
|
||||
}
|
||||
|
||||
// PrimaryTag gets the page's primary tag
|
||||
func (page *Page) PrimaryTag() Tag {
|
||||
if page.primaryTag == nil {
|
||||
return Tag{}
|
||||
}
|
||||
|
||||
return *page.primaryTag
|
||||
}
|
||||
|
||||
// ParseForm validates the values in a form and sets the page's values whenever possible regardless
|
||||
// so that it can be pushed to the viewmodel to allow the user to correct their mistakes without fear
|
||||
// of losing their hard work
|
||||
func (page *Page) ParseForm(form url.Values) []error {
|
||||
errors := make([]error, 0, 4)
|
||||
page.cachedOutput = ""
|
||||
|
||||
err := formparser.String(form.Get("name"), &page.Name, 2, 192)
|
||||
if err != nil {
|
||||
@@ -266,10 +279,11 @@ func FindPage(id string) (*Page, error) {
|
||||
WHERE id=?
|
||||
`
|
||||
const selectPageTags = `
|
||||
SELECT tag.id,tag.type,tag.name
|
||||
SELECT tag.id,tag.type,tag.name,page_tag.primary
|
||||
FROM page_tag
|
||||
RIGHT JOIN tag ON (tag.id = page_tag.tag_id)
|
||||
WHERE page_tag.page_id = ?
|
||||
ORDER BY tag.type DESC, tag.name
|
||||
`
|
||||
|
||||
db := server.Main.DB
|
||||
@@ -297,9 +311,15 @@ func FindPage(id string) (*Page, error) {
|
||||
|
||||
page.Tags = make([]Tag, 0, 64)
|
||||
for rows.Next() {
|
||||
primary := false
|
||||
|
||||
tag := Tag{}
|
||||
rows.Scan(&tag.ID, &tag.Type, &tag.Name)
|
||||
rows.Scan(&tag.ID, &tag.Type, &tag.Name, &primary)
|
||||
page.Tags = append(page.Tags, tag)
|
||||
|
||||
if primary {
|
||||
page.primaryTag = &tag
|
||||
}
|
||||
}
|
||||
|
||||
return page, nil
|
||||
|
||||
+1
-1
@@ -259,7 +259,7 @@ func TestPage(t *testing.T) {
|
||||
t.Errorf("page.Content: %s", err)
|
||||
}
|
||||
|
||||
assertEquals(t, "page.Content()", content, "<h1>Returning Va’ynna’s Omni-Tool</h1>\n\n<p>Additional Content is additional</p>\n")
|
||||
assertEquals(t, "page.Content()", string(content), "<h1>Returning Va’ynna’s Omni-Tool</h1>\n\n<p>Additional Content is additional</p>\n")
|
||||
})
|
||||
|
||||
t.Run("WikiURL", func(t *testing.T) {
|
||||
|
||||
@@ -2,6 +2,7 @@ package model
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"git.aiterp.net/AiteRP/aitestory/server"
|
||||
@@ -24,6 +25,17 @@ type Tag struct {
|
||||
Name string
|
||||
}
|
||||
|
||||
// Icon is the API used to get the icon for the tag.
|
||||
func (tag Tag) Icon() string {
|
||||
return tag.Type[0:1]
|
||||
}
|
||||
|
||||
// CSSCLass gets the CSS class that colors the tag on the
|
||||
// page list
|
||||
func (tag Tag) CSSCLass() string {
|
||||
return fmt.Sprintf("ttype-%s", strings.ToLower(tag.Type))
|
||||
}
|
||||
|
||||
// Insert adds the tag to the database, giving it a new unique ID
|
||||
func (tag *Tag) Insert() error {
|
||||
db := server.Main.DB
|
||||
|
||||
Reference in New Issue
Block a user