diff --git a/controllers/listcontroller.go b/controllers/listcontroller.go
index 2ef1fe8..3f54061 100644
--- a/controllers/listcontroller.go
+++ b/controllers/listcontroller.go
@@ -78,7 +78,6 @@ func listFiltered(category model.PageCategory) wrouter.FunctionHandlerFunc {
}
}
-// story.aiterp.net/Ruins_of_Rakhana
func init() {
ListController.Function("/", listIndex)
diff --git a/controllers/pagecontroller.go b/controllers/pagecontroller.go
new file mode 100644
index 0000000..a5285c7
--- /dev/null
+++ b/controllers/pagecontroller.go
@@ -0,0 +1,120 @@
+package controllers
+
+import (
+ "net/http"
+ "strings"
+ "time"
+
+ "git.aiterp.net/AiteRP/aitestory/model"
+ "git.aiterp.net/AiteRP/aitestory/viewmodel"
+
+ "git.aiterp.net/AiteRP/aitestory/view"
+
+ "git.aiterp.net/gisle/wrouter"
+ "git.aiterp.net/gisle/wrouter/auth"
+)
+
+// PageController serves page creation, viewing, editing and deleting through the website.
+var PageController = wrouter.Router{}
+
+func pageCreate(path string, w http.ResponseWriter, req *http.Request, user *auth.User) bool {
+ if (req.Method != "GET" && req.Method != "POST") || len(req.URL.Path) > len(path) {
+ return false
+ }
+
+ pc := viewmodel.PageForm{}
+ pc.Setup(user)
+ pc.Operation = "Create"
+
+ // Make sure the user is logged in
+ if user == nil {
+ // It's completely safe to eject logged-out users if they're not submitting
+ if req.Method == "GET" {
+ http.Redirect(w, req, "/user/login?form=/page/create", 302)
+ return true
+ }
+
+ // Logged in users would probably want a chance to log in on another form, though.
+ pc.Error = "You are not logged in."
+ }
+
+ // Respect the banhammer's authority
+ if user != nil && user.Level == "restricted" {
+ pc.Error = "Your user account is not permitted to do this"
+ }
+
+ // Handle submissions if nothing has complained yet
+ if req.Method == "POST" && pc.Error == "" {
+ // Validate form
+ req.ParseForm()
+ errs := pc.Page.ParseForm(req.Form)
+ if len(errs) > 0 {
+ pc.Error = "Validation failed: " + errs[0].Error()
+ }
+
+ // Parse the tags textbox
+ pc.TagInput = req.Form.Get("tags")
+ tagLines := strings.Split(pc.TagInput, "\n")
+ for _, line := range tagLines {
+ var tagType, tagName string
+
+ // Skip empty lines, and allow some accidental letters
+ if len(line) < 2 {
+ continue
+ }
+
+ // Parse tokens
+ tokens := strings.SplitN(line, ":", 2)
+ if len(tokens) == 2 {
+ tagType = strings.Trim(tokens[0], " \t\r")
+ tagName = strings.Trim(tokens[1], " \t\r")
+ } else {
+ tagType = "*" // Permit untyped tags if it exists.
+ tagName = strings.Trim(tokens[0], " \t\r")
+ }
+
+ // Grab the tag
+ tag, err := model.EnsureTag(tagType, tagName)
+ if err != nil {
+ pc.Error = "Check your tags: " + err.Error()
+ break
+ }
+
+ // Take a copy of it
+ pc.Page.Tags = append(pc.Page.Tags, *tag)
+ }
+
+ // If everything worked out, fill in the last bits and send it off
+ if len(errs) == 0 && pc.Error == "" {
+ pc.Page.Author = user.FullID()
+ pc.Page.PublishDate = time.Now()
+ pc.Page.EditDate = pc.Page.PublishDate.Add(-time.Hour)
+
+ err := pc.Page.Insert()
+ if err != nil {
+ pc.Error = "Insert failed: " + err.Error()
+ } else {
+ // Let us see what you have wrought upon the world
+ http.Redirect(w, req, "/page/"+pc.Page.ID, 302)
+ return true
+ }
+ }
+ }
+
+ view.Render(w, "create", 200, pc)
+
+ return true
+}
+
+func pageView(path string, w http.ResponseWriter, req *http.Request, user *auth.User) bool {
+ if (req.Method != "GET" && req.Method != "POST") || strings.LastIndex(req.URL.Path, "/") > len(path) {
+ return false
+ }
+
+ return true
+}
+
+func init() {
+ PageController.Function("/create", pageCreate)
+ PageController.Function("/", pageView)
+}
diff --git a/formparser/parsers.go b/formparser/parsers.go
index 9a79f0c..b684229 100644
--- a/formparser/parsers.go
+++ b/formparser/parsers.go
@@ -3,6 +3,7 @@ package formparser
import (
"errors"
"fmt"
+ "log"
"time"
)
@@ -24,12 +25,14 @@ func String(value string, target *string, min, max int) error {
func Select(value string, target *string, allowedValues []string, optional bool) error {
if value == "" {
if !optional {
- return errors.New("not a valid option")
+ return errors.New("no option selected")
}
return nil
}
+ log.Println(value, allowedValues)
+
for _, allowedValue := range allowedValues {
if value == allowedValue {
*target = value
diff --git a/main.go b/main.go
index f309436..bee08d7 100644
--- a/main.go
+++ b/main.go
@@ -9,6 +9,7 @@ func main() {
auth.Register(&controllers.WikiAthenticator{})
router.Mount("/user", &controllers.UserController)
+ router.Mount("/page", &controllers.PageController)
router.Mount("/", &controllers.ListController)
router.Static("/ui/", server.Main.Config.Directories.UI)
diff --git a/model/category.go b/model/category.go
index 459e996..ba9cc5b 100644
--- a/model/category.go
+++ b/model/category.go
@@ -9,6 +9,7 @@ type PageCategory struct {
Key string
Plural string
Icon string
+ Info string
}
// URLRoot is the "folder" used for searching within the category
@@ -20,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"},
- {"Info", "Info", "info"},
- {"News", "News", "news"},
- {"Item", "Items", "item"},
- {"Document", "Documents", "document"},
- {"Background", "Background", "background"},
- {"Story", "Stories", "story"},
+ {"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"},
}
var pageCategories []string
diff --git a/view/renderer.go b/view/renderer.go
index cadd975..21185eb 100644
--- a/view/renderer.go
+++ b/view/renderer.go
@@ -79,4 +79,5 @@ func Run(w io.Writer, name string, viewModel interface{}) error {
func init() {
Register("index", "base/default")
Register("login", "base/default")
+ Register("create", "base/default")
}
diff --git a/view/templates/create.tmpl b/view/templates/create.tmpl
new file mode 100644
index 0000000..6b8440c
--- /dev/null
+++ b/view/templates/create.tmpl
@@ -0,0 +1,50 @@
+{{ define "content" }}
+ Create
+
+ Aite RP
+
+