1
0
Fork 0
mirror of https://github.com/Eggbertx/gochan.git synced 2025-08-02 10:56:25 -07:00

Add template loading to the templates manage action

This commit is contained in:
Eggbertx 2023-12-21 15:55:29 -08:00
parent a8436c5ee4
commit 7e07e24f16
6 changed files with 87 additions and 55 deletions

View file

@ -165,8 +165,6 @@ type Post struct {
DeletedAt time.Time // sql: `deleted_at` DeletedAt time.Time // sql: `deleted_at`
IsDeleted bool // sql: `is_deleted` IsDeleted bool // sql: `is_deleted`
BannedMessage string // sql: `banned_message` BannedMessage string // sql: `banned_message`
sanitized bool
} }
// table: DBPREFIXreports // table: DBPREFIXreports

View file

@ -1,6 +1,9 @@
package gctemplates package gctemplates
import ( import (
"html/template"
"path"
lua "github.com/yuin/gopher-lua" lua "github.com/yuin/gopher-lua"
luar "layeh.com/gopher-luar" luar "layeh.com/gopher-luar"
) )
@ -14,7 +17,7 @@ func PreloadModule(l *lua.LState) int {
for i := 0; i < l.GetTop(); i++ { for i := 0; i < l.GetTop(); i++ {
tmplPaths = append(tmplPaths, l.CheckString(i+1)) tmplPaths = append(tmplPaths, l.CheckString(i+1))
} }
tmpl, err := loadTemplate(tmplPaths...) tmpl, err := template.New(path.Base(tmplPaths[0])).Funcs(funcMap).ParseFiles(tmplPaths...)
l.Push(luar.New(l, tmpl)) l.Push(luar.New(l, tmpl))
l.Push(luar.New(l, err)) l.Push(luar.New(l, err))
return 2 return 2

View file

@ -2,7 +2,6 @@ package gctemplates
import ( import (
"errors" "errors"
"fmt"
"html/template" "html/template"
"os" "os"
"path" "path"
@ -142,12 +141,28 @@ var (
) )
type gochanTemplate struct { type gochanTemplate struct {
files []string files []string
tmpl *template.Template tmpl *template.Template
isOverride bool
filePath string
} }
func (gt *gochanTemplate) Load() (err error) { func (gt *gochanTemplate) Load() (err error) {
gt.tmpl, err = loadTemplate(gt.files...) templateDir := config.GetSystemCriticalConfig().TemplateDir
var filePaths []string
for _, file := range gt.files {
if _, err = os.Stat(path.Join(templateDir, "override", file)); os.IsNotExist(err) {
filePaths = append(filePaths, path.Join(templateDir, file))
} else if err == nil {
filePaths = append(filePaths, path.Join(templateDir, "override", file))
} else {
return err
}
}
gt.filePath = filePaths[0]
gt.tmpl, err = template.New(gt.files[0]).Funcs(funcMap).ParseFiles(filePaths...)
return err return err
} }
@ -155,56 +170,52 @@ func (gt *gochanTemplate) Template() *template.Template {
return gt.tmpl return gt.tmpl
} }
// IsOverride returns true if the base file is overriden (i.e., it exist in the overrides subdirectory
// of the templates directory)
func (gt *gochanTemplate) IsOverride() bool {
return gt.isOverride
}
// TemplatePath returns the path to the base template file
func (gt *gochanTemplate) TemplatePath() string {
return gt.filePath
}
// GetTemplate takes the filename of the template and returns the template if it exists and
// is already loaded, and attempts to load and then return it if it exists but isn't loaded
func GetTemplate(name string) (*template.Template, error) { func GetTemplate(name string) (*template.Template, error) {
gctmpl, ok := templateMap[name] gctmpl, ok := templateMap[name]
if !ok { if !ok {
fmt.Printf("Unrecognized template %q\n", name)
return nil, ErrUnrecognizedTemplate return nil, ErrUnrecognizedTemplate
} }
if gctmpl.tmpl != nil { if gctmpl.tmpl != nil {
return gctmpl.tmpl, nil return gctmpl.tmpl, nil
} }
var err error err := gctmpl.Load()
gctmpl.tmpl, err = loadTemplate(gctmpl.files...)
return gctmpl.tmpl, err return gctmpl.tmpl, err
} }
func loadTemplate(files ...string) (*template.Template, error) { func GetTemplatePath(name string) (string, error) {
var templates []string gctmpl, ok := templateMap[name]
templateDir := config.GetSystemCriticalConfig().TemplateDir if !ok {
var foundFiles []string return "", ErrUnrecognizedTemplate
for i, file := range files {
foundFiles = append(foundFiles, file)
templates = append(templates, file)
tmplPath := path.Join(templateDir, "override", file)
if _, err := os.Stat(tmplPath); err == nil {
foundFiles[i] = tmplPath
} else if os.IsNotExist(err) {
foundFiles[i] = path.Join(templateDir, file)
} else {
return nil, err
}
} }
return gctmpl.filePath, nil
}
tmpl, err := template.New(templates[0]).Funcs(funcMap).ParseFiles(foundFiles...) // GetTemplateList returns a string array of all valid template filenames
return tmpl, templateError(templates[0], err) func GetTemplateList() []string {
var templateList []string
for t := range templateMap {
templateList = append(templateList, t)
}
return templateList
} }
func ParseTemplate(name, tmplStr string) (*template.Template, error) { func ParseTemplate(name, tmplStr string) (*template.Template, error) {
return template.New(name).Funcs(funcMap).Parse(tmplStr) return template.New(name).Funcs(funcMap).Parse(tmplStr)
} }
func templateError(name string, err error) error {
if err == nil {
return nil
}
templateDir := config.GetSystemCriticalConfig().TemplateDir
return fmt.Errorf("failed loading template '%s: %s': %s",
templateDir, name, err.Error())
}
// InitTemplates loads the given templates by name. If no parameters are given, // InitTemplates loads the given templates by name. If no parameters are given,
// all templates are (re)loaded // all templates are (re)loaded
func InitTemplates(which ...string) error { func InitTemplates(which ...string) error {

View file

@ -418,6 +418,38 @@ func registerAdminPages() {
return buffer.String(), nil return buffer.String(), nil
}, },
}, },
Action{
ID: "templates",
Title: "Override templates",
Permissions: AdminPerms,
Callback: func(writer http.ResponseWriter, request *http.Request, staff *gcsql.Staff, wantsJSON bool, infoEv, errEv *zerolog.Event) (output interface{}, err error) {
buf := bytes.NewBufferString("")
selectedTemplate := request.PostFormValue("templateselect")
var templateStr string
if selectedTemplate != "" {
errEv.Str("selectedTemplate", selectedTemplate)
templatePath, err := gctemplates.GetTemplatePath(selectedTemplate)
if err != nil {
errEv.Err(err).Caller().Msg("unable to load selected template")
return "", fmt.Errorf("template %q does not exist", selectedTemplate)
}
ba, err := os.ReadFile(templatePath)
if err != nil {
errEv.Err(err).Caller().Send()
return "", fmt.Errorf("unable to load selected template %q", selectedTemplate)
}
templateStr = string(ba)
}
serverutil.MinifyTemplate(gctemplates.ManageTemplates, map[string]any{
"templates": gctemplates.GetTemplateList(),
"selectedTemplate": selectedTemplate,
"templateText": templateStr,
}, buf, "text/html")
return buf.String(), nil
}},
Action{ Action{
ID: "rebuildfront", ID: "rebuildfront",
Title: "Rebuild front page", Title: "Rebuild front page",
@ -577,19 +609,6 @@ func registerAdminPages() {
outputStr += "Done building boards<hr />" outputStr += "Done building boards<hr />"
return outputStr, nil return outputStr, nil
}}, }},
Action{
ID: "templates",
Title: "Creat/Edit template overrides",
Permissions: AdminPerms,
Callback: func(writer http.ResponseWriter, request *http.Request, staff *gcsql.Staff, wantsJSON bool, infoEv, errEv *zerolog.Event) (output interface{}, err error) {
buf := bytes.NewBufferString("")
serverutil.MinifyTemplate(gctemplates.ManageTemplates, map[string]any{
"template": "manage_stuff.html",
"templateText": "template goes here",
}, buf, "text/html")
return buf.String(), nil
}},
Action{ Action{
ID: "wordfilters", ID: "wordfilters",
Title: "Wordfilters", Title: "Wordfilters",

View file

@ -41,7 +41,7 @@ The following are modules that can be loaded via `require("modulename")`. See [.
## gctemplates ## gctemplates
- **gctemplates.load_template(files...)** - **gctemplates.load_template(files...)**
- Calls [gctemplates.LoadTemplate](https://pkg.go.dev/github.com/gochan-org/gochan/pkg/gctemplates#LoadTemplate) using the given `files` and returns a [Template](https://pkg.go.dev/html/template#Template) and an error object (or nil if there were no errors). - Loads the given file paths into a [Template](https://pkg.go.dev/html/template#Template), using the base filename as the name, and returns the template and an error if one occured.
- **gctemplates.parse_template(template_name string, template_data string)** - **gctemplates.parse_template(template_name string, template_data string)**
- Calls [gctemplates.ParseTemplate](https://pkg.go.dev/github.com/gochan-org/gochan/pkg/gctemplates#ParseTemplate) with the given template name and Go template data, and returns a [Template](https://pkg.go.dev/html/template#Template) and an error object (or nil if there were no errors). - Calls [gctemplates.ParseTemplate](https://pkg.go.dev/github.com/gochan-org/gochan/pkg/gctemplates#ParseTemplate) with the given template name and Go template data, and returns a [Template](https://pkg.go.dev/html/template#Template) and an error object (or nil if there were no errors).

View file

@ -1,16 +1,17 @@
<div style="text-align: center;"> <div style="text-align: center;">
<form action="{{webPath "manage/templates"}}" method="POST" id="template-override"> <form action="{{webPath "manage/templates"}}" method="POST" id="template-override">
{{with $.templateText}} {{with $.templateText}}
<b>Editing: {{$.currentTemplate}}</b> <b>Editing: {{$.selectedTemplate}}</b>
<textarea class="template-text" rows="16" spellcheck="false">{{$.templateText}}</textarea> <textarea name="templatetext" class="template-text" rows="16" spellcheck="false">{{$.templateText}}</textarea>
<input type="submit" name="dooverride" value="Submit" onsubmit="return prompt('Are you sure you want to override the template?')"> <input type="submit" name="dooverride" value="Submit" onsubmit="return prompt('Are you sure you want to override the template?')">
<input type="submit" name="cancel" value="Cancel"/> <input type="submit" name="cancel" value="Cancel"/>
{{else}} {{else}}
Select a template: <select name="templateselect"> Select a template: <select name="templateselect">
{{range $t, $template := .templates}} {{range $t, $template := .templates}}
<option value="$template"></option> <option value="{{$template}}">{{$template}}</option>
{{end}} {{end}}
</select> </select>
<input type="submit" name="dotemplatechoose" value="Select template" />
{{end}} {{end}}
</form> </form>
</div> </div>