mirror of
https://github.com/Eggbertx/gochan.git
synced 2025-08-02 15:06:23 -07:00
Finish browser-based template editor, resolves issue #90
This commit is contained in:
parent
6fbfb731bd
commit
e968dc875a
9 changed files with 134 additions and 20 deletions
2
build.py
2
build.py
|
@ -38,7 +38,7 @@ release_files = (
|
|||
"README.md",
|
||||
)
|
||||
|
||||
GOCHAN_VERSION = "3.8.0"
|
||||
GOCHAN_VERSION = "3.9.0"
|
||||
DATABASE_VERSION = "2" # stored in DBNAME.DBPREFIXdatabase_version
|
||||
|
||||
PATH_NOTHING = -1
|
||||
|
|
|
@ -7,7 +7,7 @@ local url = require("url")
|
|||
local check_key_url = "https://rest.akismet.com/1.1/verify-key"
|
||||
|
||||
local base_headers = {}
|
||||
base_headers["User-Agent"] = "gochan/3.8 | Akismet/0.1"
|
||||
base_headers["User-Agent"] = "gochan/3.9 | Akismet/0.1"
|
||||
base_headers["Content-Type"] = "application/x-www-form-urlencoded"
|
||||
|
||||
local key = "" -- read from akismet_key.txt
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "gochan.js",
|
||||
"version": "3.8.0",
|
||||
"version": "3.9.0",
|
||||
"description": "",
|
||||
"main": "./ts/main.ts",
|
||||
"private": true,
|
||||
|
|
|
@ -7,6 +7,6 @@
|
|||
<h1>404: File not found</h1>
|
||||
<img src="/error/lol 404.gif" border="0" alt="">
|
||||
<p>The requested file could not be found on this server.</p>
|
||||
<hr/>Site powered by <a href="https://github.com/gochan-org/gochan" target="_blank">Gochan</a> v3.8.0
|
||||
<hr/>Site powered by <a href="https://github.com/gochan-org/gochan" target="_blank">Gochan</a> v3.9.0
|
||||
</body>
|
||||
</html>
|
|
@ -7,6 +7,6 @@
|
|||
<h1>Error 500: Internal Server error</h1>
|
||||
<img src="/error/server500.gif" border="0" alt="">
|
||||
<p>The server encountered an error while trying to serve the page, and we apologize for the inconvenience. The <a href="https://en.wikipedia.org/wiki/Idiot">system administrator</a> will try to fix things as soon they get around to it, whenever that is. Hopefully soon.</p>
|
||||
<hr/>Site powered by <a href="https://github.com/gochan-org/gochan" target="_blank">Gochan</a> v3.8.0
|
||||
<hr/>Site powered by <a href="https://github.com/gochan-org/gochan" target="_blank">Gochan</a> v3.9.0
|
||||
</body>
|
||||
</html>
|
|
@ -7,6 +7,6 @@
|
|||
<h1>Error 502: Bad gateway</h1>
|
||||
<img src="/error/server500.gif" border="0" alt="">
|
||||
<p>The server encountered an error while trying to serve the page, and we apologize for the inconvenience. The <a href="https://en.wikipedia.org/wiki/Idiot">system administrator</a> will try to fix things as soon they get around to it, whenever that is. Hopefully soon.</p>
|
||||
<hr/>Site powered by <a href="https://github.com/gochan-org/gochan" target="_blank">Gochan</a> v3.8.0
|
||||
<hr/>Site powered by <a href="https://github.com/gochan-org/gochan" target="_blank">Gochan</a> v3.9.0
|
||||
</body>
|
||||
</html>
|
|
@ -18,6 +18,7 @@ const (
|
|||
Catalog = "catalog.html"
|
||||
JsConsts = "consts.js"
|
||||
ErrorPage = "error.html"
|
||||
FrontIntro = "front_intro.html"
|
||||
FrontPage = "front.html"
|
||||
ManageAnnouncements = "manage_announcements.html"
|
||||
ManageAppeals = "manage_appeals.html"
|
||||
|
@ -66,6 +67,9 @@ var (
|
|||
ErrorPage: {
|
||||
files: []string{"error.html"},
|
||||
},
|
||||
FrontIntro: {
|
||||
files: []string{"front_intro.html"},
|
||||
},
|
||||
FrontPage: {
|
||||
files: []string{"front.html", "topbar.html", "front_intro.html", "page_header.html", "page_footer.html"},
|
||||
},
|
||||
|
|
|
@ -10,6 +10,7 @@ import (
|
|||
"os"
|
||||
"path"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/gochan-org/gochan/pkg/building"
|
||||
"github.com/gochan-org/gochan/pkg/config"
|
||||
|
@ -425,29 +426,125 @@ func registerAdminPages() {
|
|||
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")
|
||||
selectedTemplate := request.FormValue("override")
|
||||
templatesDir := config.GetSystemCriticalConfig().TemplateDir
|
||||
var overriding string
|
||||
var templateStr string
|
||||
var templatePath string
|
||||
var successStr string
|
||||
if selectedTemplate != "" {
|
||||
errEv.Str("selectedTemplate", selectedTemplate)
|
||||
gcutil.LogStr("selectedTemplate", selectedTemplate, infoEv, errEv)
|
||||
|
||||
templatePath, err := gctemplates.GetTemplatePath(selectedTemplate)
|
||||
if err != nil {
|
||||
if templatePath, err = gctemplates.GetTemplatePath(selectedTemplate); err != nil {
|
||||
errEv.Err(err).Caller().Msg("unable to load selected template")
|
||||
return "", fmt.Errorf("template %q does not exist", selectedTemplate)
|
||||
}
|
||||
errEv.Str("templatePath", templatePath)
|
||||
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)
|
||||
} else if overriding = request.PostFormValue("overriding"); overriding != "" {
|
||||
if templateStr = request.PostFormValue("templatetext"); templateStr == "" {
|
||||
writer.WriteHeader(http.StatusBadRequest)
|
||||
errEv.Caller().Int("status", http.StatusBadRequest).
|
||||
Msg("received an empty template string")
|
||||
return "", errors.New("received an empty template string")
|
||||
}
|
||||
if _, err = gctemplates.ParseTemplate(selectedTemplate, templateStr); err != nil {
|
||||
// unable to parse submitted template
|
||||
errEv.Err(err).Caller().Int("status", http.StatusBadRequest).Send()
|
||||
writer.WriteHeader(http.StatusBadRequest)
|
||||
return "", err
|
||||
}
|
||||
overrideDir := path.Join(templatesDir, "override")
|
||||
overridePath := path.Join(overrideDir, overriding)
|
||||
gcutil.LogStr("overridePath", overridePath, infoEv, errEv)
|
||||
|
||||
if _, err = os.Stat(overrideDir); os.IsNotExist(err) {
|
||||
// override dir doesn't exist, create it
|
||||
if err = os.Mkdir(overrideDir, config.GC_DIR_MODE); err != nil {
|
||||
errEv.Err(err).Caller().
|
||||
Int("status", http.StatusInternalServerError).
|
||||
Msg("Unable to create override directory")
|
||||
writer.WriteHeader(http.StatusInternalServerError)
|
||||
return "", err
|
||||
}
|
||||
} else if err != nil {
|
||||
// got an error checking for override dir
|
||||
errEv.Err(err).Caller().
|
||||
Int("status", http.StatusInternalServerError).
|
||||
Msg("Unable to check if override directory exists")
|
||||
writer.WriteHeader(http.StatusInternalServerError)
|
||||
return "", err
|
||||
}
|
||||
|
||||
serverutil.MinifyTemplate(gctemplates.ManageTemplates, map[string]any{
|
||||
// get the original template file, or the latest override if there are any
|
||||
templatePath, err := gctemplates.GetTemplatePath(overriding)
|
||||
if err != nil {
|
||||
errEv.Err(err).Caller().
|
||||
Int("status", http.StatusInternalServerError).
|
||||
Msg("Unable to get original template path")
|
||||
writer.WriteHeader(http.StatusInternalServerError)
|
||||
return "", err
|
||||
}
|
||||
|
||||
// read original template path into []byte to be backed up
|
||||
ba, err := os.ReadFile(templatePath)
|
||||
if err != nil {
|
||||
errEv.Err(err).Caller().
|
||||
Int("status", http.StatusInternalServerError).
|
||||
Msg("Unable to read original template file")
|
||||
writer.WriteHeader(http.StatusInternalServerError)
|
||||
return "", err
|
||||
}
|
||||
|
||||
// back up template to override/<overriding>-<timestamp>.bkp
|
||||
backupPath := path.Join(overrideDir, overriding) + time.Now().Format("-2006-01-02_15-04-05.bkp")
|
||||
gcutil.LogStr("backupPath", backupPath, infoEv, errEv)
|
||||
if err = os.WriteFile(backupPath, ba, config.GC_FILE_MODE); err != nil {
|
||||
errEv.Err(err).Caller().
|
||||
Int("status", http.StatusInternalServerError).
|
||||
Msg("Unable to back up template file")
|
||||
writer.WriteHeader(http.StatusInternalServerError)
|
||||
return "", errors.New("unable to back up original template file")
|
||||
}
|
||||
|
||||
// write changes to disk
|
||||
if err = os.WriteFile(overridePath, []byte(templateStr), config.GC_FILE_MODE); err != nil {
|
||||
errEv.Err(err).Caller().
|
||||
Int("status", http.StatusInternalServerError).
|
||||
Msg("Unable to save changes")
|
||||
writer.WriteHeader(http.StatusInternalServerError)
|
||||
return "", err
|
||||
}
|
||||
|
||||
// reload template
|
||||
if err = gctemplates.InitTemplates(overriding); err != nil {
|
||||
errEv.Err(err).Caller().
|
||||
Int("status", http.StatusInternalServerError).
|
||||
Msg("Unable to reinitialize template")
|
||||
writer.WriteHeader(http.StatusInternalServerError)
|
||||
return "", err
|
||||
}
|
||||
successStr = fmt.Sprintf("%q saved successfully.\n Original backed up to %s",
|
||||
overriding, backupPath)
|
||||
infoEv.Msg("Template successfully saved and reloaded")
|
||||
}
|
||||
|
||||
data := map[string]any{
|
||||
"templates": gctemplates.GetTemplateList(),
|
||||
"templatesDir": templatesDir,
|
||||
"templatePath": templatePath,
|
||||
"selectedTemplate": selectedTemplate,
|
||||
"templateText": templateStr,
|
||||
}, buf, "text/html")
|
||||
"success": successStr,
|
||||
}
|
||||
if templateStr != "" && successStr == "" {
|
||||
data["templateText"] = templateStr
|
||||
}
|
||||
serverutil.MinifyTemplate(gctemplates.ManageTemplates, data, buf, "text/html")
|
||||
return buf.String(), nil
|
||||
}},
|
||||
Action{
|
||||
|
|
|
@ -1,17 +1,30 @@
|
|||
<div style="text-align: center;">
|
||||
<form action="{{webPath "manage/templates"}}" method="POST" id="template-override">
|
||||
<form action="{{webPath "manage/templates"}}" method="{{with $.templateText}}POST{{else}}GET{{end}}" id="template-override">
|
||||
{{with $.templateText}}
|
||||
<b>Editing: {{$.selectedTemplate}}</b>
|
||||
<input type="hidden" name="overriding" value="{{$.selectedTemplate}}">
|
||||
<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="cancel" value="Cancel"/>
|
||||
<input type="submit" name="dooverride" value="Submit" onclick="return confirm('Are you sure you want to override the template?')"/>
|
||||
<input type="submit" name="cancel" value="Cancel"/ onclick="window.history.back()"/>
|
||||
</form>
|
||||
</div>
|
||||
<p>
|
||||
When you submit your changes to a template, the latest change (or the original if there are no changes yet)
|
||||
will be backed up to the "overrides" subdirectory of your configured templates directory, {{$.templatesDir}},
|
||||
with a timestamp appended to the filename.
|
||||
</p>
|
||||
{{else}}
|
||||
Select a template: <select name="templateselect">
|
||||
{{- with .success}}
|
||||
<div style="display:inline-block; outline: 4px solid green">
|
||||
{{$.success}}<br/>
|
||||
You may need to rebuild the respective page(s), or rebuild everything <a href='{{webPath "/manage/rebuildall"}}'>here</a>.
|
||||
</div><br/><br/>{{- end -}}
|
||||
Select a template: <select name="override">
|
||||
{{range $t, $template := .templates}}
|
||||
<option value="{{$template}}">{{$template}}</option>
|
||||
{{end}}
|
||||
</select>
|
||||
<input type="submit" name="dotemplatechoose" value="Select template" />
|
||||
{{end}}
|
||||
<input type="submit" value="Select template" />
|
||||
</form>
|
||||
</div>
|
||||
{{end}}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue