From 660f24acff8ca4af6b561d5302df4a0d6811373d Mon Sep 17 00:00:00 2001 From: Azareal Date: Fri, 22 Mar 2019 08:59:41 +1000 Subject: [PATCH] Experimenting with Nox's Control Panel. Experimenting with better cache busting for static resources. HTTPSRedirect requests are now counted in the route analytics. More scripts are loaded asynchronously now. Upped the default ReadTimeout to eight seconds. Reduce the number of unneccesary NewAcc calls. Added panel_before_head as an injection point for themes. Themes can now declare scripts to be loaded asynchronously. Tweaked the WS resumption algorithm to mae the backoffs a little less aggressive. Fixed an ordering issue in the WS resumption algorithm where backoffs weren't expiring as fast as they should have. Fixed a bug where template logs weren't being written due to a panic. You can now use byte slices in more places in the transpiled templates. Fixed a bug where Cosora's misc.js seemed to be erroring out. Fixed a bug where YT embeds were getting blocked by the CSP. Added the panel_back_to_site phrase. Added the panel_welcome phrase. --- common/counters/langs.go | 7 +- common/counters/routes.go | 3 +- common/counters/systems.go | 3 +- common/files.go | 8 +- common/pages.go | 44 +++- common/routes_common.go | 12 +- common/template_init.go | 5 +- common/templates/templates.go | 32 ++- common/theme.go | 3 +- common/websockets.go | 6 + docs/configuration.md | 2 +- gen_router.go | 14 ++ langs/english.json | 2 + main.go | 11 +- public/analytics.js | 4 +- public/global.js | 28 ++- public/init.js | 3 +- router_gen/main.go | 12 + routes/common.go | 3 +- routes/panel/analytics.go | 2 +- routes/panel/common.go | 1 + routes/stubs.go | 16 +- templates/header.html | 7 +- templates/panel_adminlogs.html | 1 + templates/panel_analytics_agent_views.html | 1 + templates/panel_analytics_agents.html | 1 + templates/panel_analytics_forum_views.html | 1 + templates/panel_analytics_forums.html | 1 + templates/panel_analytics_lang_views.html | 1 + templates/panel_analytics_langs.html | 1 + templates/panel_analytics_posts.html | 1 + templates/panel_analytics_referrer_views.html | 1 + templates/panel_analytics_referrers.html | 1 + templates/panel_analytics_route_views.html | 1 + templates/panel_analytics_routes.html | 1 + templates/panel_analytics_script.html | 6 +- templates/panel_analytics_system_views.html | 1 + templates/panel_analytics_systems.html | 1 + templates/panel_analytics_topics.html | 1 + templates/panel_analytics_views.html | 1 + templates/panel_are_you_sure.html | 1 + templates/panel_backups.html | 1 + templates/panel_before_head.html | 0 templates/panel_dashboard.html | 1 + templates/panel_debug.html | 1 + templates/panel_forum_edit.html | 1 + templates/panel_forum_edit_perms.html | 1 + templates/panel_forums.html | 1 + templates/panel_group_edit.html | 1 + templates/panel_group_edit_perms.html | 1 + templates/panel_groups.html | 1 + templates/panel_modlogs.html | 1 + templates/panel_pages.html | 1 + templates/panel_pages_edit.html | 1 + templates/panel_plugins.html | 1 + templates/panel_reglogs.html | 1 + templates/panel_setting.html | 1 + templates/panel_settings.html | 1 + templates/panel_themes.html | 1 + templates/panel_themes_menus.html | 1 + templates/panel_themes_menus_item_edit.html | 1 + templates/panel_themes_menus_items.html | 1 + templates/panel_themes_widgets.html | 1 + templates/panel_user_edit.html | 1 + templates/panel_users.html | 1 + templates/panel_word_filters.html | 1 + themes/cosora/public/misc.js | 207 +++++++++--------- themes/cosora/theme.json | 3 +- themes/nox/overrides/panel_before_head.html | 6 + themes/nox/overrides/panel_group_menu.html | 4 +- themes/nox/overrides/panel_menu.html | 4 +- themes/nox/public/misc.js | 43 ++-- themes/nox/public/panel.css | 31 ++- themes/nox/theme.json | 3 +- 74 files changed, 375 insertions(+), 201 deletions(-) create mode 100644 templates/panel_before_head.html create mode 100644 themes/nox/overrides/panel_before_head.html diff --git a/common/counters/langs.go b/common/counters/langs.go index 9f78ccbc..d2f6a384 100644 --- a/common/counters/langs.go +++ b/common/counters/langs.go @@ -96,12 +96,11 @@ var langCodes = []string{ type DefaultLangViewCounter struct { buckets []*RWMutexCounterBucket //[OSID]count codesToIndices map[string]int - insert *sql.Stmt + + insert *sql.Stmt } -func NewDefaultLangViewCounter() (*DefaultLangViewCounter, error) { - acc := qgen.NewAcc() - +func NewDefaultLangViewCounter(acc *qgen.Accumulator) (*DefaultLangViewCounter, error) { var langBuckets = make([]*RWMutexCounterBucket, len(langCodes)) for bucketID, _ := range langBuckets { langBuckets[bucketID] = &RWMutexCounterBucket{counter: 0} diff --git a/common/counters/routes.go b/common/counters/routes.go index d60d2764..ac55aff8 100644 --- a/common/counters/routes.go +++ b/common/counters/routes.go @@ -12,8 +12,7 @@ type DefaultRouteViewCounter struct { insert *sql.Stmt } -func NewDefaultRouteViewCounter() (*DefaultRouteViewCounter, error) { - acc := qgen.NewAcc() +func NewDefaultRouteViewCounter(acc *qgen.Accumulator) (*DefaultRouteViewCounter, error) { var routeBuckets = make([]*RWMutexCounterBucket, len(routeMapEnum)) for bucketID, _ := range routeBuckets { routeBuckets[bucketID] = &RWMutexCounterBucket{counter: 0} diff --git a/common/counters/systems.go b/common/counters/systems.go index 3f24367a..163dc0e9 100644 --- a/common/counters/systems.go +++ b/common/counters/systems.go @@ -14,8 +14,7 @@ type DefaultOSViewCounter struct { insert *sql.Stmt } -func NewDefaultOSViewCounter() (*DefaultOSViewCounter, error) { - acc := qgen.NewAcc() +func NewDefaultOSViewCounter(acc *qgen.Accumulator) (*DefaultOSViewCounter, error) { var osBuckets = make([]*RWMutexCounterBucket, len(osMapEnum)) for bucketID, _ := range osBuckets { osBuckets[bucketID] = &RWMutexCounterBucket{counter: 0} diff --git a/common/files.go b/common/files.go index 468945ed..a8ca909a 100644 --- a/common/files.go +++ b/common/files.go @@ -27,7 +27,7 @@ var staticFileMutex sync.RWMutex type SFile struct { Data []byte GzipData []byte - Sha256 []byte + Sha256 string Pos int64 Length int64 GzipLength int64 @@ -240,7 +240,7 @@ func (list SFileList) JSTmplInit() error { // Get a checksum for CSPs and cache busting hasher := sha256.New() hasher.Write(data) - checksum := []byte(hex.EncodeToString(hasher.Sum(nil))) + checksum := hex.EncodeToString(hasher.Sum(nil)) list.Set("/static/"+path, SFile{data, gzipData, checksum, 0, int64(len(data)), int64(len(gzipData)), mime.TypeByExtension(ext), f, f.ModTime().UTC().Format(http.TimeFormat)}) @@ -267,7 +267,7 @@ func (list SFileList) Init() error { // Get a checksum for CSPs and cache busting hasher := sha256.New() hasher.Write(data) - checksum := []byte(hex.EncodeToString(hasher.Sum(nil))) + checksum := hex.EncodeToString(hasher.Sum(nil)) // Avoid double-compressing images var gzipData []byte @@ -318,7 +318,7 @@ func (list SFileList) Add(path string, prefix string) error { // Get a checksum for CSPs and cache busting hasher := sha256.New() hasher.Write(data) - checksum := []byte(hex.EncodeToString(hasher.Sum(nil))) + checksum := hex.EncodeToString(hasher.Sum(nil)) list.Set("/static"+path, SFile{data, gzipData, checksum, 0, int64(len(data)), int64(len(gzipData)), mime.TypeByExtension(ext), f, f.ModTime().UTC().Format(http.TimeFormat)}) diff --git a/common/pages.go b/common/pages.go index 8303bd32..fe70a062 100644 --- a/common/pages.go +++ b/common/pages.go @@ -10,14 +10,20 @@ import ( "github.com/Azareal/Gosora/common/phrases" ) +type HResource struct { + Name string + Hash string +} + // TODO: Allow resources in spots other than /static/ and possibly even external domains (e.g. CDNs) // TODO: Preload Trumboyg on Cosora on the forum list type Header struct { Title string //Title []byte // Experimenting with []byte for increased efficiency, let's avoid converting too many things to []byte, as it involves a lot of extra boilerplate NoticeList []string - Scripts []string - PreScriptsAsync []string + Scripts []HResource + PreScriptsAsync []HResource + ScriptsAsync []HResource //Preload []string Stylesheets []string Widgets PageWidgets @@ -44,11 +50,41 @@ type Header struct { } func (header *Header) AddScript(name string) { - header.Scripts = append(header.Scripts, name) + fname := "/static/" + name + var hash string + if fname[0] == '/' && fname[1] != '/' { + file, ok := StaticFiles.Get(fname) + if ok { + hash = file.Sha256 + } + } + //log.Print("name:", name) + //log.Print("hash:", hash) + header.Scripts = append(header.Scripts, HResource{name, hash}) } func (header *Header) AddPreScriptAsync(name string) { - header.PreScriptsAsync = append(header.PreScriptsAsync, name) + fname := "/static/" + name + var hash string + if fname[0] == '/' && fname[1] != '/' { + file, ok := StaticFiles.Get(fname) + if ok { + hash = file.Sha256 + } + } + header.PreScriptsAsync = append(header.PreScriptsAsync, HResource{name, hash}) +} + +func (header *Header) AddScriptAsync(name string) { + fname := "/static/" + name + var hash string + if fname[0] == '/' && fname[1] != '/' { + file, ok := StaticFiles.Get(fname) + if ok { + hash = file.Sha256 + } + } + header.ScriptsAsync = append(header.ScriptsAsync, HResource{name, hash}) } /*func (header *Header) Preload(name string) { diff --git a/common/routes_common.go b/common/routes_common.go index f2946076..ca15db58 100644 --- a/common/routes_common.go +++ b/common/routes_common.go @@ -131,7 +131,11 @@ func panelUserCheck(w http.ResponseWriter, r *http.Request, user *User) (header if ext == "css" { header.AddSheet(resource.Name) } else if ext == "js" { - header.AddScript(resource.Name) + if resource.Async { + header.AddScriptAsync(resource.Name) + } else { + header.AddScript(resource.Name) + } } } } @@ -229,7 +233,11 @@ func userCheck(w http.ResponseWriter, r *http.Request, user *User) (header *Head if ext == "css" { header.AddSheet(resource.Name) } else if ext == "js" { - header.AddScript(resource.Name) + if resource.Async { + header.AddScriptAsync(resource.Name) + } else { + header.AddScript(resource.Name) + } } } } diff --git a/common/template_init.go b/common/template_init.go index 86a1e3d1..a99b0a12 100644 --- a/common/template_init.go +++ b/common/template_init.go @@ -109,8 +109,9 @@ func tmplInitHeaders(user User, user2 User, user3 User) (*Header, *Header, *Head CurrentUser: user, NoticeList: []string{"test"}, Stylesheets: []string{"panel.css"}, - Scripts: []string{"whatever.js"}, - PreScriptsAsync: []string{"whatever.js"}, + Scripts: []HResource{HResource{"whatever.js", "d"}}, + PreScriptsAsync: []HResource{HResource{"whatever.js", "d"}}, + ScriptsAsync: []HResource{HResource{"whatever.js", "d"}}, Widgets: PageWidgets{ LeftSidebar: template.HTML("lalala"), }, diff --git a/common/templates/templates.go b/common/templates/templates.go index c183e354..87fdc6c8 100644 --- a/common/templates/templates.go +++ b/common/templates/templates.go @@ -2,11 +2,13 @@ package tmpl import ( "bytes" + "fmt" "io/ioutil" "log" "os" "path/filepath" "reflect" + "runtime/debug" "strconv" "strings" "text/template/parse" @@ -70,7 +72,8 @@ type CTemplateSet struct { themeName string perThemeTmpls map[string]bool - logger *log.Logger + logger *log.Logger + loggerf *os.File } func NewCTemplateSet(in string) *CTemplateSet { @@ -110,7 +113,8 @@ func NewCTemplateSet(in string) *CTemplateSet { "dyntmpl": true, "index": true, }, - logger: log.New(f, "", log.LstdFlags), + logger: log.New(f, "", log.LstdFlags), + loggerf: f, } } @@ -155,6 +159,7 @@ func (c *CTemplateSet) ResetLogs(in string) { panic(err) } c.logger = log.New(f, "", log.LstdFlags) + c.loggerf = f } type SkipBlock struct { @@ -268,6 +273,19 @@ func (c *CTemplateSet) Compile(name string, fileDir string, expects string, expe } func (c *CTemplateSet) compile(name string, content string, expects string, expectsInt interface{}, varList map[string]VarItem, imports ...string) (out string, err error) { + defer func() { + r := recover() + if r != nil { + fmt.Println(r) + debug.PrintStack() + err := c.loggerf.Sync() + if err != nil { + fmt.Println(err) + } + log.Fatal("") + return + } + }() //c.dumpCall("compile", name, content, expects, expectsInt, varList, imports) //c.detailf("c: %+v\n", c) c.importMap = map[string]string{} @@ -1460,6 +1478,16 @@ func (c *CTemplateSet) compileVarSub(con CContext, varname string, val reflect.V c.addText(con, []byte("false")) con.Push("endelse", "}\n") return + case reflect.Slice: + if val.Len() == 0 { + c.critical("varname:", varname) + panic("The sample data needs at-least one or more elements for the slices. We're looking into removing this requirement at some point!") + } + item := val.Index(0) + if item.Type().Name() != "uint8" { // uint8 == byte, complicated because it's a type alias + panic("unable to format " + item.Type().Name() + " as text") + } + base = varname case reflect.String: if val.Type().Name() != "string" && !strings.HasPrefix(varname, "string(") { varname = "string(" + varname + ")" diff --git a/common/theme.go b/common/theme.go index 2e2cecba..626feeab 100644 --- a/common/theme.go +++ b/common/theme.go @@ -77,6 +77,7 @@ type ThemeResource struct { Name string Location string Loggedin bool // Only serve this resource to logged in users + Async bool } type ThemeMapTmplToDock struct { @@ -162,7 +163,7 @@ func (theme *Theme) AddThemeStaticFiles() error { // Get a checksum for CSPs and cache busting hasher := sha256.New() hasher.Write(data) - checksum := []byte(hex.EncodeToString(hasher.Sum(nil))) + checksum := hex.EncodeToString(hasher.Sum(nil)) StaticFiles.Set("/static/"+theme.Name+path, SFile{data, gzipData, checksum, 0, int64(len(data)), int64(len(gzipData)), mime.TypeByExtension(ext), f, f.ModTime().UTC().Format(http.TimeFormat)}) diff --git a/common/websockets.go b/common/websockets.go index 38adec05..1797941f 100644 --- a/common/websockets.go +++ b/common/websockets.go @@ -92,6 +92,12 @@ func RouteWebsockets(w http.ResponseWriter, r *http.Request, user User) RouteErr currentPage = string(msgblocks[1]) wsPageResponses(wsUser, conn, currentPage) } + } else if bytes.HasPrefix(msg, []byte("resume ")) { + msgblocks := bytes.SplitN(msg, []byte(" "), 2) + if len(msgblocks) < 2 { + continue + } + //log.Print("resuming on " + string(msgblocks[1])) } /*if bytes.Equal(message,[]byte(`start-view`)) { } else if bytes.Equal(message,[]byte(`end-view`)) { diff --git a/docs/configuration.md b/docs/configuration.md index cfbad8b4..bce91e23 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -84,7 +84,7 @@ MaxTopicTitleLength - The maximum length that a topic can be. Please note that t MaxUsernameLength - The maximum length that a user's name can be. Please note that this measures the number of bytes and may differ from language to language with it being equal to a letter in English and being two bytes in others. -ReadTimeout - The number of seconds that we are allowed to take to fully read a request. Defaults to 5. +ReadTimeout - The number of seconds that we are allowed to take to fully read a request. Defaults to 8. WriteTimeout - The number of seconds that a route is allowed to run for before the request is automatically terminated. Defaults to 10. diff --git a/gen_router.go b/gen_router.go index 231448fd..efd5b96e 100644 --- a/gen_router.go +++ b/gen_router.go @@ -164,6 +164,7 @@ var RouteMap = map[string]interface{}{ "routes.RobotsTxt": routes.RobotsTxt, "routes.SitemapXml": routes.SitemapXml, "routes.BadRoute": routes.BadRoute, + "routes.HTTPSRedirect": routes.HTTPSRedirect, } // ! NEVER RELY ON THESE REMAINING THE SAME BETWEEN COMMITS @@ -309,6 +310,7 @@ var routeMapEnum = map[string]int{ "routes.RobotsTxt": 138, "routes.SitemapXml": 139, "routes.BadRoute": 140, + "routes.HTTPSRedirect": 141, } var reverseRouteMapEnum = map[int]string{ 0: "routes.Overview", @@ -452,6 +454,7 @@ var reverseRouteMapEnum = map[int]string{ 138: "routes.RobotsTxt", 139: "routes.SitemapXml", 140: "routes.BadRoute", + 141: "routes.HTTPSRedirect", } var osMapEnum = map[string]int{ "unknown": 0, @@ -600,6 +603,17 @@ func (writ *WriterIntercept) WriteHeader(code int) { writ.ResponseWriter.WriteHeader(code) } +// HTTPSRedirect is a connection handler which redirects all HTTP requests to HTTPS +type HTTPSRedirect struct { +} + +func (red *HTTPSRedirect) ServeHTTP(w http.ResponseWriter, req *http.Request) { + w.Header().Set("Connection", "close") + counters.RouteViewCounter.Bump(141) + dest := "https://" + req.Host + req.URL.String() + http.Redirect(w, req, dest, http.StatusTemporaryRedirect) +} + type GenRouter struct { UploadHandler func(http.ResponseWriter, *http.Request) extraRoutes map[string]func(http.ResponseWriter, *http.Request, common.User) common.RouteError diff --git a/langs/english.json b/langs/english.json index 09f11142..941ce2d8 100644 --- a/langs/english.json +++ b/langs/english.json @@ -708,6 +708,8 @@ "option_yes":"Yes", "option_no":"No", + "panel_back_to_site":"Back to Site", + "panel_welcome":"Welcome ", "panel_menu_head":"Control Panel", "panel_menu_aria":"The control panel menu", "panel_menu_users":"Users", diff --git a/main.go b/main.go index e9047aad..de7e75ae 100644 --- a/main.go +++ b/main.go @@ -28,7 +28,6 @@ import ( "github.com/Azareal/Gosora/common/counters" "github.com/Azareal/Gosora/common/phrases" "github.com/Azareal/Gosora/query_gen" - "github.com/Azareal/Gosora/routes" "github.com/fsnotify/fsnotify" "github.com/pkg/errors" ) @@ -181,15 +180,15 @@ func afterDBInit() (err error) { if err != nil { return errors.WithStack(err) } - counters.OSViewCounter, err = counters.NewDefaultOSViewCounter() + counters.OSViewCounter, err = counters.NewDefaultOSViewCounter(acc) if err != nil { return errors.WithStack(err) } - counters.LangViewCounter, err = counters.NewDefaultLangViewCounter() + counters.LangViewCounter, err = counters.NewDefaultLangViewCounter(acc) if err != nil { return errors.WithStack(err) } - counters.RouteViewCounter, err = counters.NewDefaultRouteViewCounter() + counters.RouteViewCounter, err = counters.NewDefaultRouteViewCounter(acc) if err != nil { return errors.WithStack(err) } @@ -472,7 +471,7 @@ func startServer() { var newServer = func(addr string, handler http.Handler) *http.Server { rtime := common.Config.ReadTimeout if rtime == 0 { - rtime = 5 + rtime = 8 } else if rtime == -1 { rtime = 0 } @@ -527,7 +526,7 @@ func startServer() { // TODO: Redirect to port 443 go func() { log.Print("Listening on port 80") - common.StoppedServer(newServer(":80", &routes.HTTPSRedirect{}).ListenAndServe()) + common.StoppedServer(newServer(":80", &HTTPSRedirect{}).ListenAndServe()) }() } log.Printf("Listening on port %s", common.Site.Port) diff --git a/public/analytics.js b/public/analytics.js index cf738f72..a47a8a1a 100644 --- a/public/analytics.js +++ b/public/analytics.js @@ -59,4 +59,6 @@ function buildStatsChart(rawLabels, seriesData, timeRange, legendNames) { labels: labels, series: seriesData, }, config); -} \ No newline at end of file +} + +runInitHook("analytics_loaded"); \ No newline at end of file diff --git a/public/global.js b/public/global.js index c3f54a22..55ddb348 100644 --- a/public/global.js +++ b/public/global.js @@ -193,7 +193,7 @@ function wsAlertEvent(data) { updateAlertList(generalAlerts/*, alist*/); } -function runWebSockets() { +function runWebSockets(resume = false) { if(window.location.protocol == "https:") { conn = new WebSocket("wss://" + document.location.host + "/ws/"); } else conn = new WebSocket("ws://" + document.location.host + "/ws/"); @@ -206,6 +206,7 @@ function runWebSockets() { conn.onopen = () => { console.log("The WebSockets connection was opened"); conn.send("page " + document.location.pathname + '\r'); + if(resume) conn.send("resume " + Math.round((new Date()).getTime() / 1000) + '\r'); // TODO: Don't ask again, if it's denied. We could have a setting in the UCP which automatically requests this when someone flips desktop notifications on if(me.User.ID > 0) Notification.requestPermission(); } @@ -213,23 +214,22 @@ function runWebSockets() { conn.onclose = () => { conn = false; console.log("The WebSockets connection was closed"); - let backoff = 1000; + let backoff = 0.8; if(wsBackoff < 0) wsBackoff = 0; - else if(wsBackoff > 12) backoff = 13000; - else if(wsBackoff > 5) backoff = 7000; + else if(wsBackoff > 12) backoff = 11; + else if(wsBackoff > 5) backoff = 5; wsBackoff++; setTimeout(() => { var alertMenuList = document.getElementsByClassName("menu_alerts"); - for(var i = 0; i < alertMenuList.length; i++) { - loadAlerts(alertMenuList[i]); - } - runWebSockets(); - }, 60 * backoff); + for(var i = 0; i < alertMenuList.length; i++) loadAlerts(alertMenuList[i]); + runWebSockets(true); + }, backoff * 60 * 1000); if(wsBackoff > 0) { - if(wsBackoff <= 5) setTimeout(() => wsBackoff--, 60 * 4000); - else if(wsBackoff <= 12) setTimeout(() => wsBackoff--, 60 * 20000); + if(wsBackoff <= 5) setTimeout(() => wsBackoff--, 5.5 * 60 * 1000); + else if(wsBackoff <= 12) setTimeout(() => wsBackoff--, 11.5 * 60 * 1000); + else setTimeout(() => wsBackoff--, 20 * 60 * 1000); } } @@ -333,16 +333,14 @@ function runWebSockets() { notifyOnScriptW("template_alert", (e) => { if(e!=undefined) console.log("failed alert? why?", e) }, () => { - console.log("ha") + //console.log("ha") if(!Template_alert) throw("template function not found"); addInitHook("after_phrases", () => { // TODO: The load part of loadAlerts could be done asynchronously while the update of the DOM could be deferred $(document).ready(() => { alertsInitted = true; var alertMenuList = document.getElementsByClassName("menu_alerts"); - for(var i = 0; i < alertMenuList.length; i++) { - loadAlerts(alertMenuList[i]); - } + for(var i = 0; i < alertMenuList.length; i++) loadAlerts(alertMenuList[i]); if(window["WebSocket"]) runWebSockets(); }); }); diff --git a/public/init.js b/public/init.js index 2e983d2c..4639886a 100644 --- a/public/init.js +++ b/public/init.js @@ -4,7 +4,7 @@ var me = {}; var phraseBox = {}; if(tmplInits===undefined) var tmplInits = {}; var tmplPhrases = []; // [key] array of phrases indexed by order of use -var hooks = { +var hooks = { // Shorten this list by binding the hooks just in time? "pre_iffe": [], "pre_init": [], "start_init": [], @@ -15,6 +15,7 @@ var hooks = { "open_edit":[], "close_edit":[], "edit_item_pre_bind":[], + "analytics_loaded":[], }; var ranInitHooks = {} diff --git a/router_gen/main.go b/router_gen/main.go index af528789..7cbabc11 100644 --- a/router_gen/main.go +++ b/router_gen/main.go @@ -174,6 +174,7 @@ func main() { mapIt("routes.RobotsTxt") mapIt("routes.SitemapXml") mapIt("routes.BadRoute") + mapIt("routes.HTTPSRedirect") tmplVars.AllRouteNames = allRouteNames tmplVars.AllRouteMap = allRouteMap @@ -381,6 +382,17 @@ func (writ *WriterIntercept) WriteHeader(code int) { writ.ResponseWriter.WriteHeader(code) } +// HTTPSRedirect is a connection handler which redirects all HTTP requests to HTTPS +type HTTPSRedirect struct { +} + +func (red *HTTPSRedirect) ServeHTTP(w http.ResponseWriter, req *http.Request) { + w.Header().Set("Connection", "close") + counters.RouteViewCounter.Bump({{ index .AllRouteMap "routes.HTTPSRedirect" }}) + dest := "https://" + req.Host + req.URL.String() + http.Redirect(w, req, dest, http.StatusTemporaryRedirect) +} + type GenRouter struct { UploadHandler func(http.ResponseWriter, *http.Request) extraRoutes map[string]func(http.ResponseWriter, *http.Request, common.User) common.RouteError diff --git a/routes/common.go b/routes/common.go index 42b04239..7e0e0fab 100644 --- a/routes/common.go +++ b/routes/common.go @@ -29,8 +29,9 @@ func renderTemplate(tmplName string, w http.ResponseWriter, r *http.Request, hea } // TODO: Expand this to non-HTTPS requests too if !header.LooseCSP && common.Site.EnableSsl { - w.Header().Set("Content-Security-Policy", "default-src 'self' 'unsafe-eval'; style-src 'self' 'unsafe-eval' 'unsafe-inline'; img-src * data: 'unsafe-eval' 'unsafe-inline'; connect-src * 'unsafe-eval' 'unsafe-inline'; upgrade-insecure-requests") + w.Header().Set("Content-Security-Policy", "default-src 'self' 'unsafe-eval'; style-src 'self' 'unsafe-eval' 'unsafe-inline'; img-src * data: 'unsafe-eval' 'unsafe-inline'; connect-src * 'unsafe-eval' 'unsafe-inline'; frame-src 'self' www.youtube-nocookie.com;upgrade-insecure-requests") } + header.AddScript("global.js") if header.CurrentUser.IsAdmin { header.Elapsed1 = time.Since(header.StartedAt).String() } diff --git a/routes/panel/analytics.go b/routes/panel/analytics.go index 49282721..83d9299c 100644 --- a/routes/panel/analytics.go +++ b/routes/panel/analytics.go @@ -125,7 +125,7 @@ func PreAnalyticsDetail(w http.ResponseWriter, r *http.Request, user *common.Use } basePage.AddSheet("chartist/chartist.min.css") basePage.AddScript("chartist/chartist.min.js") - basePage.AddScript("analytics.js") + basePage.AddScriptAsync("analytics.js") return basePage, nil } diff --git a/routes/panel/common.go b/routes/panel/common.go index 4d6874d7..e57b77ef 100644 --- a/routes/panel/common.go +++ b/routes/panel/common.go @@ -22,6 +22,7 @@ func successRedirect(dest string, w http.ResponseWriter, r *http.Request, isJs b } func renderTemplate(tmplName string, w http.ResponseWriter, r *http.Request, header *common.Header, pi interface{}) common.RouteError { + header.AddScript("global.js") if common.RunPreRenderHook("pre_render_"+tmplName, w, r, &header.CurrentUser, pi) { return nil } diff --git a/routes/stubs.go b/routes/stubs.go index 66801d85..f673f0d6 100644 --- a/routes/stubs.go +++ b/routes/stubs.go @@ -1,17 +1,5 @@ package routes -import "net/http" - -// HTTPSRedirect is a connection handler which redirects all HTTP requests to HTTPS -type HTTPSRedirect struct { -} - -func (red *HTTPSRedirect) ServeHTTP(w http.ResponseWriter, req *http.Request) { - w.Header().Set("Connection", "close") - dest := "https://" + req.Host + req.URL.String() - http.Redirect(w, req, dest, http.StatusTemporaryRedirect) -} - // Temporary stubs for view tracking func DynamicRoute() { } @@ -19,3 +7,7 @@ func UploadedFile() { } func BadRoute() { } + +// Real implementation is in router_gen/main.go, this is just a stub to map the analytics onto +func HTTPSRedirect() { +} diff --git a/templates/header.html b/templates/header.html index cb39c6e6..5d132488 100644 --- a/templates/header.html +++ b/templates/header.html @@ -6,13 +6,14 @@ {{range .Header.Stylesheets}} {{end}} {{range .Header.PreScriptsAsync}} - {{end}} + {{end}} + {{range .Header.ScriptsAsync}} + {{end}} {{range .Header.Scripts}} - {{end}} - + {{end}} {{if .Header.MetaDesc}}{{end}} {{/** TODO: Have page / forum / topic level tags and descriptions below as-well **/}} diff --git a/templates/panel_adminlogs.html b/templates/panel_adminlogs.html index ddd6e7a3..c9fbc462 100644 --- a/templates/panel_adminlogs.html +++ b/templates/panel_adminlogs.html @@ -2,6 +2,7 @@
{{template "panel_menu.html" . }}
+{{template "panel_before_head.html" . }}

{{lang "panel_logs_administration_head"}}

diff --git a/templates/panel_analytics_agent_views.html b/templates/panel_analytics_agent_views.html index 1751d531..ad644839 100644 --- a/templates/panel_analytics_agent_views.html +++ b/templates/panel_analytics_agent_views.html @@ -2,6 +2,7 @@
{{template "panel_menu.html" . }}
+{{template "panel_before_head.html" . }}
diff --git a/templates/panel_analytics_agents.html b/templates/panel_analytics_agents.html index 22fad81a..9f206422 100644 --- a/templates/panel_analytics_agents.html +++ b/templates/panel_analytics_agents.html @@ -2,6 +2,7 @@
{{template "panel_menu.html" . }}
+{{template "panel_before_head.html" . }}
diff --git a/templates/panel_analytics_forum_views.html b/templates/panel_analytics_forum_views.html index ec11212a..1f2ad5ce 100644 --- a/templates/panel_analytics_forum_views.html +++ b/templates/panel_analytics_forum_views.html @@ -2,6 +2,7 @@
{{template "panel_menu.html" . }}
+{{template "panel_before_head.html" . }}
diff --git a/templates/panel_analytics_forums.html b/templates/panel_analytics_forums.html index dc0ddf25..f2eb606e 100644 --- a/templates/panel_analytics_forums.html +++ b/templates/panel_analytics_forums.html @@ -2,6 +2,7 @@
{{template "panel_menu.html" . }}
+{{template "panel_before_head.html" . }}
diff --git a/templates/panel_analytics_lang_views.html b/templates/panel_analytics_lang_views.html index b2e26542..9073ce17 100644 --- a/templates/panel_analytics_lang_views.html +++ b/templates/panel_analytics_lang_views.html @@ -2,6 +2,7 @@
{{template "panel_menu.html" . }}
+{{template "panel_before_head.html" . }}
diff --git a/templates/panel_analytics_langs.html b/templates/panel_analytics_langs.html index 6fe220ab..df3ec502 100644 --- a/templates/panel_analytics_langs.html +++ b/templates/panel_analytics_langs.html @@ -2,6 +2,7 @@
{{template "panel_menu.html" . }}
+{{template "panel_before_head.html" . }}
diff --git a/templates/panel_analytics_posts.html b/templates/panel_analytics_posts.html index 03f1e3fd..27b84d35 100644 --- a/templates/panel_analytics_posts.html +++ b/templates/panel_analytics_posts.html @@ -2,6 +2,7 @@
{{template "panel_menu.html" . }}
+{{template "panel_before_head.html" . }}
diff --git a/templates/panel_analytics_referrer_views.html b/templates/panel_analytics_referrer_views.html index 941b3820..edb41d08 100644 --- a/templates/panel_analytics_referrer_views.html +++ b/templates/panel_analytics_referrer_views.html @@ -2,6 +2,7 @@
{{template "panel_menu.html" . }}
+{{template "panel_before_head.html" . }}
diff --git a/templates/panel_analytics_referrers.html b/templates/panel_analytics_referrers.html index bc10af6e..63b826fa 100644 --- a/templates/panel_analytics_referrers.html +++ b/templates/panel_analytics_referrers.html @@ -2,6 +2,7 @@
{{template "panel_menu.html" . }}
+{{template "panel_before_head.html" . }}
diff --git a/templates/panel_analytics_route_views.html b/templates/panel_analytics_route_views.html index 549df9ee..9e284d09 100644 --- a/templates/panel_analytics_route_views.html +++ b/templates/panel_analytics_route_views.html @@ -2,6 +2,7 @@
{{template "panel_menu.html" . }}
+{{template "panel_before_head.html" . }}
diff --git a/templates/panel_analytics_routes.html b/templates/panel_analytics_routes.html index 5dae4e5a..35d9f6cb 100644 --- a/templates/panel_analytics_routes.html +++ b/templates/panel_analytics_routes.html @@ -2,6 +2,7 @@
{{template "panel_menu.html" . }}
+{{template "panel_before_head.html" . }}
diff --git a/templates/panel_analytics_script.html b/templates/panel_analytics_script.html index b63cbc2b..f7afc5fc 100644 --- a/templates/panel_analytics_script.html +++ b/templates/panel_analytics_script.html @@ -11,6 +11,10 @@ let legendNames = [{{range .Graph.Legends}} {{.}},{{end}} ]; addInitHook("after_phrases", () => { - buildStatsChart(rawLabels, seriesData, "{{.TimeRange}}",legendNames); + addInitHook("end_init", () => { + addInitHook("analytics_loaded", () => { + buildStatsChart(rawLabels, seriesData, "{{.TimeRange}}",legendNames); + }); + }); }); \ No newline at end of file diff --git a/templates/panel_analytics_system_views.html b/templates/panel_analytics_system_views.html index ecdcb33c..7847946c 100644 --- a/templates/panel_analytics_system_views.html +++ b/templates/panel_analytics_system_views.html @@ -2,6 +2,7 @@
{{template "panel_menu.html" . }}
+{{template "panel_before_head.html" . }}
diff --git a/templates/panel_analytics_systems.html b/templates/panel_analytics_systems.html index 12c72856..03c2db43 100644 --- a/templates/panel_analytics_systems.html +++ b/templates/panel_analytics_systems.html @@ -2,6 +2,7 @@
{{template "panel_menu.html" . }}
+{{template "panel_before_head.html" . }}
diff --git a/templates/panel_analytics_topics.html b/templates/panel_analytics_topics.html index 2d167598..48c057e9 100644 --- a/templates/panel_analytics_topics.html +++ b/templates/panel_analytics_topics.html @@ -2,6 +2,7 @@
{{template "panel_menu.html" . }}
+{{template "panel_before_head.html" . }}
diff --git a/templates/panel_analytics_views.html b/templates/panel_analytics_views.html index 2937d357..e01f8f27 100644 --- a/templates/panel_analytics_views.html +++ b/templates/panel_analytics_views.html @@ -2,6 +2,7 @@
{{template "panel_menu.html" . }}
+{{template "panel_before_head.html" . }}
diff --git a/templates/panel_are_you_sure.html b/templates/panel_are_you_sure.html index 19da61e4..d7773ae8 100644 --- a/templates/panel_are_you_sure.html +++ b/templates/panel_are_you_sure.html @@ -2,6 +2,7 @@
{{template "panel_menu.html" . }}
+{{template "panel_before_head.html" . }}

{{lang "areyousure_head"}}

diff --git a/templates/panel_backups.html b/templates/panel_backups.html index 4e20132b..beeffe1b 100644 --- a/templates/panel_backups.html +++ b/templates/panel_backups.html @@ -2,6 +2,7 @@
{{template "panel_menu.html" . }}
+{{template "panel_before_head.html" . }}

{{lang "panel_backups_head"}}

diff --git a/templates/panel_before_head.html b/templates/panel_before_head.html new file mode 100644 index 00000000..e69de29b diff --git a/templates/panel_dashboard.html b/templates/panel_dashboard.html index aa3cca01..c0568df5 100644 --- a/templates/panel_dashboard.html +++ b/templates/panel_dashboard.html @@ -2,6 +2,7 @@
{{template "panel_menu.html" . }}
+{{template "panel_before_head.html" . }}

{{lang "panel_dashboard_head"}}

diff --git a/templates/panel_debug.html b/templates/panel_debug.html index 2d1a825d..137a8fa6 100644 --- a/templates/panel_debug.html +++ b/templates/panel_debug.html @@ -2,6 +2,7 @@
{{template "panel_menu.html" . }}
+{{template "panel_before_head.html" . }}

{{lang "panel_debug_head"}}

diff --git a/templates/panel_forum_edit.html b/templates/panel_forum_edit.html index 16428fa8..b8671c5c 100644 --- a/templates/panel_forum_edit.html +++ b/templates/panel_forum_edit.html @@ -7,6 +7,7 @@ var formVars = {'perm_preset': ['can_moderate','can_post','read_only','no_access
+{{template "panel_before_head.html" . }}

{{.Name}}{{lang "panel_forum_head_suffix"}}

diff --git a/templates/panel_forum_edit_perms.html b/templates/panel_forum_edit_perms.html index 1f85e898..f4e479df 100644 --- a/templates/panel_forum_edit_perms.html +++ b/templates/panel_forum_edit_perms.html @@ -3,6 +3,7 @@ {{template "panel_menu.html" . }}
+{{template "panel_before_head.html" . }}

{{.Name}}{{lang "panel_forum_head_suffix"}}

diff --git a/templates/panel_forums.html b/templates/panel_forums.html index 2e8e89c2..8580a61f 100644 --- a/templates/panel_forums.html +++ b/templates/panel_forums.html @@ -8,6 +8,7 @@
+{{template "panel_before_head.html" . }}

{{lang "panel_forums_head"}}

diff --git a/templates/panel_group_edit.html b/templates/panel_group_edit.html index 205f50b9..a234e191 100644 --- a/templates/panel_group_edit.html +++ b/templates/panel_group_edit.html @@ -2,6 +2,7 @@
{{template "panel_group_menu.html" . }}
+{{template "panel_before_head.html" . }}

{{.Name}}{{lang "panel_group_head_suffix"}}

diff --git a/templates/panel_group_edit_perms.html b/templates/panel_group_edit_perms.html index c479d0e3..3f552f9e 100644 --- a/templates/panel_group_edit_perms.html +++ b/templates/panel_group_edit_perms.html @@ -2,6 +2,7 @@
{{template "panel_group_menu.html" . }}
+{{template "panel_before_head.html" . }}

{{.Name}}{{lang "panel_group_head_suffix"}}

diff --git a/templates/panel_groups.html b/templates/panel_groups.html index 4983e4e5..012dd347 100644 --- a/templates/panel_groups.html +++ b/templates/panel_groups.html @@ -3,6 +3,7 @@ {{template "panel_menu.html" . }}
+{{template "panel_before_head.html" . }}

{{lang "panel_groups_head"}}

diff --git a/templates/panel_modlogs.html b/templates/panel_modlogs.html index 39de8a90..41152c3c 100644 --- a/templates/panel_modlogs.html +++ b/templates/panel_modlogs.html @@ -2,6 +2,7 @@
{{template "panel_menu.html" . }}
+{{template "panel_before_head.html" . }}

{{lang "panel_logs_moderation_head"}}

diff --git a/templates/panel_pages.html b/templates/panel_pages.html index 1f55b10e..ff3d2b8b 100644 --- a/templates/panel_pages.html +++ b/templates/panel_pages.html @@ -2,6 +2,7 @@
{{template "panel_menu.html" . }}
+{{template "panel_before_head.html" . }}

{{lang "panel_pages_head"}}

diff --git a/templates/panel_pages_edit.html b/templates/panel_pages_edit.html index 27a08231..43e3b9f2 100644 --- a/templates/panel_pages_edit.html +++ b/templates/panel_pages_edit.html @@ -2,6 +2,7 @@
{{template "panel_menu.html" . }}
+{{template "panel_before_head.html" . }}

{{lang "panel_pages_edit_head"}}

diff --git a/templates/panel_plugins.html b/templates/panel_plugins.html index ba682d25..e35717f1 100644 --- a/templates/panel_plugins.html +++ b/templates/panel_plugins.html @@ -3,6 +3,7 @@ {{template "panel_menu.html" . }}
+{{template "panel_before_head.html" . }}

{{lang "panel_plugins_head"}}

diff --git a/templates/panel_reglogs.html b/templates/panel_reglogs.html index b53032ea..e2313739 100644 --- a/templates/panel_reglogs.html +++ b/templates/panel_reglogs.html @@ -2,6 +2,7 @@
{{template "panel_menu.html" . }}
+{{template "panel_before_head.html" . }}

{{lang "panel_logs_registration_head"}}

diff --git a/templates/panel_setting.html b/templates/panel_setting.html index 29d1d53d..ba790936 100644 --- a/templates/panel_setting.html +++ b/templates/panel_setting.html @@ -3,6 +3,7 @@ {{template "panel_menu.html" . }}
+{{template "panel_before_head.html" . }}

{{.Setting.FriendlyName}}

diff --git a/templates/panel_settings.html b/templates/panel_settings.html index 4f6acddc..1a52f67c 100644 --- a/templates/panel_settings.html +++ b/templates/panel_settings.html @@ -2,6 +2,7 @@
{{template "panel_menu.html" . }}
+{{template "panel_before_head.html" . }}

{{lang "panel_settings_head"}}

diff --git a/templates/panel_themes.html b/templates/panel_themes.html index 42910d07..d8e6c51b 100644 --- a/templates/panel_themes.html +++ b/templates/panel_themes.html @@ -11,6 +11,7 @@
+{{template "panel_before_head.html" . }}

{{lang "panel_themes_primary_themes"}}

diff --git a/templates/panel_themes_menus.html b/templates/panel_themes_menus.html index 65ac2c0f..2ce4bf5a 100644 --- a/templates/panel_themes_menus.html +++ b/templates/panel_themes_menus.html @@ -2,6 +2,7 @@
{{template "panel_menu.html" . }}
+{{template "panel_before_head.html" . }}

{{lang "panel_themes_menus_head"}}

diff --git a/templates/panel_themes_menus_item_edit.html b/templates/panel_themes_menus_item_edit.html index 877be147..aec7329a 100644 --- a/templates/panel_themes_menus_item_edit.html +++ b/templates/panel_themes_menus_item_edit.html @@ -4,6 +4,7 @@ {{/** TODO: Write the backend code and JS code for saving this menu **/}} {{template "panel_menu.html" . }}
+{{template "panel_before_head.html" . }}

{{lang "panel_themes_menus_edit_head"}}

diff --git a/templates/panel_themes_menus_items.html b/templates/panel_themes_menus_items.html index a9844b4e..fc368118 100644 --- a/templates/panel_themes_menus_items.html +++ b/templates/panel_themes_menus_items.html @@ -2,6 +2,7 @@
{{template "panel_menu.html" . }}
+{{template "panel_before_head.html" . }}

{{lang "panel_themes_menus_items_head"}}

diff --git a/templates/panel_themes_widgets.html b/templates/panel_themes_widgets.html index d626f253..b437d396 100644 --- a/templates/panel_themes_widgets.html +++ b/templates/panel_themes_widgets.html @@ -13,6 +13,7 @@ type Widget struct {
{{template "panel_menu.html" . }}
+{{template "panel_before_head.html" . }}

{{lang "panel_themes_widgets_head"}}

diff --git a/templates/panel_user_edit.html b/templates/panel_user_edit.html index 77cc3bdf..206c6c6d 100644 --- a/templates/panel_user_edit.html +++ b/templates/panel_user_edit.html @@ -3,6 +3,7 @@ {{template "panel_menu.html" . }}
+{{template "panel_before_head.html" . }}

{{lang "panel_user_head"}}

diff --git a/templates/panel_users.html b/templates/panel_users.html index 7445086b..d7529374 100644 --- a/templates/panel_users.html +++ b/templates/panel_users.html @@ -3,6 +3,7 @@ {{template "panel_menu.html" . }}
+{{template "panel_before_head.html" . }}

{{lang "panel_users_head"}}

diff --git a/templates/panel_word_filters.html b/templates/panel_word_filters.html index 5fdf3b42..66d3d0a5 100644 --- a/templates/panel_word_filters.html +++ b/templates/panel_word_filters.html @@ -3,6 +3,7 @@ {{template "panel_menu.html" . }}
+{{template "panel_before_head.html" . }}

{{lang "panel_word_filters_head"}}

diff --git a/themes/cosora/public/misc.js b/themes/cosora/public/misc.js index 750ac848..2b98f134 100644 --- a/themes/cosora/public/misc.js +++ b/themes/cosora/public/misc.js @@ -1,116 +1,113 @@ -"use strict" +"use strict"; -$(document).ready(function(){ - let loggedIn = document.head.querySelector("[property='x-loggedin']").content; - if(loggedIn) { - // Is there we way we can append instead? Maybe, an editor plugin? - attachItemCallback = function(attachItem) { - let currentContent = $('#input_content').trumbowyg('html'); - $('#input_content').trumbowyg('html', currentContent); - } - - $(".topic_name_row").click(function(){ - $(".topic_create_form").addClass("selectedInput"); - }); - //$.trumbowyg.svgPath = false; +(() => { + console.log("bf") + addInitHook("end_init", () => { + console.log("af") + let loggedIn = document.head.querySelector("[property='x-loggedin']").content; + if(loggedIn) { + // Is there we way we can append instead? Maybe, an editor plugin? + attachItemCallback = function(attachItem) { + let currentContent = $('#input_content').trumbowyg('html'); + $('#input_content').trumbowyg('html', currentContent); + } + + $(".topic_name_row").click(function(){ + $(".topic_create_form").addClass("selectedInput"); + }); + //$.trumbowyg.svgPath = false; - // TODO: Bind this to the viewport resize event - var btnlist = []; - if(document.documentElement.clientWidth > 550) { - btnlist = [['viewHTML'],['undo','redo'],['formatting'],['strong','em','del'],['link'],['insertImage'],['unorderedList','orderedList'],['removeformat']]; - } else { - btnlist = [['viewHTML'],['strong','em','del'],['link'],['insertImage'],['unorderedList','orderedList'],['removeformat']]; - } - - $('.topic_create_form #input_content').trumbowyg({ - btns: btnlist, - }); - $('.topic_reply_form #input_content').trumbowyg({ - btns: btnlist, - autogrow: true, - }); - $('#profile_comments_form .topic_reply_form .input_content').trumbowyg({ - btns: [['viewHTML'],['strong','em','del'],['link'],['insertImage'],['removeformat']], - autogrow: true, - }); - addHook("edit_item_pre_bind", () => { - $('.user_content textarea').trumbowyg({ + // TODO: Bind this to the viewport resize event + var btnlist = []; + if(document.documentElement.clientWidth > 550) { + btnlist = [['viewHTML'],['undo','redo'],['formatting'],['strong','em','del'],['link'],['insertImage'],['unorderedList','orderedList'],['removeformat']]; + } else { + btnlist = [['viewHTML'],['strong','em','del'],['link'],['insertImage'],['unorderedList','orderedList'],['removeformat']]; + } + + $('.topic_create_form #input_content').trumbowyg({ + btns: btnlist, + }); + $('.topic_reply_form #input_content').trumbowyg({ btns: btnlist, autogrow: true, }); - }); - } - - // TODO: Refactor this to use `each` less - $('.button_menu').click(function(){ - console.log(".button_menu"); - // The outer container - let buttonPane = newElement("div","button_menu_pane"); - let postItem = $(this).parents('.post_item'); - - // Create the userinfo row in the pane - let userInfo = newElement("div","userinfo"); - postItem.find('.avatar_item').each(function(){ - userInfo.appendChild(this); - }); - - let userText = newElement("div","userText"); - postItem.find('.userinfo:not(.avatar_item)').children().each(function(){ - userText.appendChild(this); - }); - userInfo.appendChild(userText); - buttonPane.appendChild(userInfo); - - // Copy a short preview of the post contents into the pane - postItem.find('.user_content').each(function(){ - // TODO: Truncate an excessive number of lines to 5 or so - let contents = this.innerHTML; - if(contents.length > 45) { - this.innerHTML = contents.substring(0,45) + "..."; - } - buttonPane.appendChild(this); - }); - - // Copy the buttons from the post to the pane - let buttonGrid = newElement("div","buttonGrid"); - let gridElementCount = 0; - $(this).parent().children('a:not(.button_menu)').each(function(){ - buttonGrid.appendChild(this); - gridElementCount++; - }); - - - // Fill in the placeholder grid nodes - let rowCount = 4; - console.log("rowCount: ",rowCount); - console.log("gridElementCount: ",gridElementCount); - if(gridElementCount%rowCount != 0) { - let fillerNodes = (rowCount - (gridElementCount%rowCount)); - console.log("fillerNodes: ",fillerNodes); - for(let i = 0; i < fillerNodes;i++ ) { - console.log("added a gridFiller"); - buttonGrid.appendChild(newElement("div","gridFiller")); - } + $('#profile_comments_form .topic_reply_form .input_content').trumbowyg({ + btns: [['viewHTML'],['strong','em','del'],['link'],['insertImage'],['removeformat']], + autogrow: true, + }); + addHook("edit_item_pre_bind", () => { + $('.user_content textarea').trumbowyg({ + btns: btnlist, + autogrow: true, + }); + }); } - buttonPane.appendChild(buttonGrid); - document.getElementById("back").appendChild(buttonPane); + // TODO: Refactor this to use `each` less + $('.button_menu').click(function(){ + console.log(".button_menu"); + // The outer container + let buttonPane = newElement("div","button_menu_pane"); + let postItem = $(this).parents('.post_item'); + + // Create the userinfo row in the pane + let userInfo = newElement("div","userinfo"); + postItem.find('.avatar_item').each(function(){ + userInfo.appendChild(this); + }); + + let userText = newElement("div","userText"); + postItem.find('.userinfo:not(.avatar_item)').children().each(function(){ + userText.appendChild(this); + }); + userInfo.appendChild(userText); + buttonPane.appendChild(userInfo); + + // Copy a short preview of the post contents into the pane + postItem.find('.user_content').each(function(){ + // TODO: Truncate an excessive number of lines to 5 or so + let contents = this.innerHTML; + if(contents.length > 45) this.innerHTML = contents.substring(0,45) + "..."; + buttonPane.appendChild(this); + }); + + // Copy the buttons from the post to the pane + let buttonGrid = newElement("div","buttonGrid"); + let gridElementCount = 0; + $(this).parent().children('a:not(.button_menu)').each(function(){ + buttonGrid.appendChild(this); + gridElementCount++; + }); + + + // Fill in the placeholder grid nodes + let rowCount = 4; + console.log("rowCount: ",rowCount); + console.log("gridElementCount: ",gridElementCount); + if(gridElementCount%rowCount != 0) { + let fillerNodes = (rowCount - (gridElementCount%rowCount)); + console.log("fillerNodes: ",fillerNodes); + for(let i = 0; i < fillerNodes;i++ ) { + console.log("added a gridFiller"); + buttonGrid.appendChild(newElement("div","gridFiller")); + } + } + buttonPane.appendChild(buttonGrid); + + document.getElementById("back").appendChild(buttonPane); + }); + + // Move the alerts under the first header + let colSel = $(".colstack_right .colstack_head:first"); + let colSelAlt = $(".colstack_right .colstack_item:first"); + let colSelAltAlt = $(".colstack_right .coldyn_block:first"); + if(colSel.length > 0) $('.alert').insertAfter(colSel); + else if (colSelAlt.length > 0) $('.alert').insertBefore(colSelAlt); + else if (colSelAltAlt.length > 0) $('.alert').insertBefore(colSelAltAlt); + else $('.alert').insertAfter(".rowhead:first"); }); - - // Move the alerts under the first header - let colSel = $(".colstack_right .colstack_head:first"); - let colSelAlt = $(".colstack_right .colstack_item:first"); - let colSelAltAlt = $(".colstack_right .coldyn_block:first"); - if(colSel.length > 0) { - $('.alert').insertAfter(colSel); - } else if (colSelAlt.length > 0) { - $('.alert').insertBefore(colSelAlt); - } else if (colSelAltAlt.length > 0) { - $('.alert').insertBefore(colSelAltAlt); - } else { - $('.alert').insertAfter(".rowhead:first"); - } -}); +})(); function newElement(etype, eclass) { let element = document.createElement(etype); diff --git a/themes/cosora/theme.json b/themes/cosora/theme.json index 5a26f874..adb7af87 100644 --- a/themes/cosora/theme.json +++ b/themes/cosora/theme.json @@ -29,7 +29,8 @@ }, { "Name":"cosora/misc.js", - "Location":"global" + "Location":"global", + "Async":true } ] } diff --git a/themes/nox/overrides/panel_before_head.html b/themes/nox/overrides/panel_before_head.html new file mode 100644 index 00000000..cb7af928 --- /dev/null +++ b/themes/nox/overrides/panel_before_head.html @@ -0,0 +1,6 @@ +
+
{{lang "panel_back_to_site"}}
+
+ + {{lang "panel_welcome"}}{{.CurrentUser.Name}}
+
\ No newline at end of file diff --git a/themes/nox/overrides/panel_group_menu.html b/themes/nox/overrides/panel_group_menu.html index 3fae9bb4..491bad4e 100644 --- a/themes/nox/overrides/panel_group_menu.html +++ b/themes/nox/overrides/panel_group_menu.html @@ -1,7 +1,7 @@