From a1161e20f3d3366b4852f271e2a310ac215cc70f Mon Sep 17 00:00:00 2001 From: Azareal Date: Fri, 3 May 2019 18:34:18 +1000 Subject: [PATCH] The rest of the Control Panel (exc. the Group Editor) now uses dyntmpl. Improved the noavatar cacheability by constraining them in a range. Improved the noavatar cacheability by serving a small subset from Gosora. Improved the formatting of bytes in the memory analytics pane. Static resources with checksums will now have their caches expire in a week rather than a day. Tweaked the padding on the sub_heads on Nox. Moved a block of CSS out of a template and into panel.css in Tempra Simple and Shadow. Added the panel_themes_menus_items_suffix phrase. Added the DisableNoavatarRange config setting. Added the DisableDefaultNoavatar config setting. --- common/alerts.go | 2 +- common/site.go | 2 + common/user.go | 44 ++++++++++++++------ docs/configuration.md | 4 ++ langs/english.json | 1 + public/analytics.js | 21 ++++++---- public/n1-200.png | Bin 0 -> 16937 bytes public/n1-48.png | Bin 0 -> 2585 bytes public/n2-200.png | Bin 0 -> 12906 bytes public/n2-48.png | Bin 0 -> 2163 bytes public/n3-200.png | Bin 0 -> 9993 bytes public/n3-48.png | Bin 0 -> 1599 bytes public/n4-200.png | Bin 0 -> 12467 bytes public/n4-48.png | Bin 0 -> 1994 bytes routes/misc.go | 7 +++- routes/panel/backups.go | 3 +- routes/panel/debug.go | 2 +- routes/panel/logs.go | 6 +-- routes/panel/plugins.go | 3 +- routes/panel/themes.go | 13 +++--- templates/panel_adminlogs.html | 10 +---- templates/panel_analytics_memory.html | 36 ++++++++++++---- templates/panel_analytics_posts.html | 2 +- templates/panel_analytics_topics.html | 2 +- templates/panel_analytics_views.html | 2 +- templates/panel_backups.html | 10 +---- templates/panel_debug.html | 10 +---- templates/panel_modlogs.html | 10 +---- templates/panel_plugins.html | 12 +----- templates/panel_reglogs.html | 12 +----- templates/panel_themes.html | 20 +-------- templates/panel_themes_menus.html | 12 +----- templates/panel_themes_menus_item_edit.html | 15 ++----- templates/panel_themes_menus_items.html | 10 +---- templates/panel_themes_widgets.html | 10 +---- themes/nox/public/panel.css | 2 +- themes/shadow/public/panel.css | 6 +++ themes/tempra_simple/public/panel.css | 6 +++ 38 files changed, 129 insertions(+), 166 deletions(-) create mode 100644 public/n1-200.png create mode 100644 public/n1-48.png create mode 100644 public/n2-200.png create mode 100644 public/n2-48.png create mode 100644 public/n3-200.png create mode 100644 public/n3-48.png create mode 100644 public/n4-200.png create mode 100644 public/n4-48.png diff --git a/common/alerts.go b/common/alerts.go index 417c8f3a..d4406d6b 100644 --- a/common/alerts.go +++ b/common/alerts.go @@ -1,7 +1,7 @@ /* * * Gosora Alerts System -* Copyright Azareal 2017 - 2019 +* Copyright Azareal 2017 - 2020 * */ package common diff --git a/common/site.go b/common/site.go index 5d6d15e7..6431a37b 100644 --- a/common/site.go +++ b/common/site.go @@ -96,6 +96,8 @@ type config struct { LoosePort bool DisableServerPush bool EnableCDNPush bool + DisableNoavatarRange bool + DisableDefaultNoavatar bool Noavatar string // ? - Move this into the settings table? ItemsPerPage int // ? - Move this into the settings table? diff --git a/common/user.go b/common/user.go index 36607e3e..f6997b9c 100644 --- a/common/user.go +++ b/common/user.go @@ -1,7 +1,7 @@ /* * * Gosora User File -* Copyright Azareal 2017 - 2019 +* Copyright Azareal 2017 - 2020 * */ package common @@ -456,27 +456,45 @@ type GuestAvatar struct { } func buildNoavatar(uid int, width int) string { + if !Config.DisableNoavatarRange { + // TODO: Find a faster algorithm + if uid > 50000 { + uid -= 50000 + } + if uid > 5000 { + uid -= 5000 + } + if uid > 500 { + uid -= 500 + } + for uid > 50 { + uid -= 50 + } + } + if !Config.DisableDefaultNoavatar && uid < 5 { + return "/static/n"+strconv.Itoa(uid)+"-"+strconv.Itoa(width)+".png?i=0" + } return strings.Replace(strings.Replace(Config.Noavatar, "{id}", strconv.Itoa(uid), 1), "{width}", strconv.Itoa(width), 1) } // ? Make this part of *User? // TODO: Write tests for this func BuildAvatar(uid int, avatar string) (normalAvatar string, microAvatar string) { - if avatar != "" { - if avatar[0] == '.' { - if avatar[1] == '.' { - normalAvatar = "/uploads/avatar_" + strconv.Itoa(uid) + "_tmp" + avatar[1:] - return normalAvatar, normalAvatar - } - normalAvatar = "/uploads/avatar_" + strconv.Itoa(uid) + avatar + if avatar == "" { + if uid == 0 { + return guestAvatar.Normal, guestAvatar.Micro + } + return buildNoavatar(uid, 200), buildNoavatar(uid, 48) + } + if avatar[0] == '.' { + if avatar[1] == '.' { + normalAvatar = "/uploads/avatar_" + strconv.Itoa(uid) + "_tmp" + avatar[1:] return normalAvatar, normalAvatar } - return avatar, avatar + normalAvatar = "/uploads/avatar_" + strconv.Itoa(uid) + avatar + return normalAvatar, normalAvatar } - if uid == 0 { - return guestAvatar.Normal, guestAvatar.Micro - } - return buildNoavatar(uid, 200), buildNoavatar(uid, 48) + return avatar, avatar } // TODO: Move this to *User diff --git a/docs/configuration.md b/docs/configuration.md index 4c3582e8..32cec701 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -92,6 +92,10 @@ DisableServerPush - This switch lets you disable the HTTP/2 server push feature. EnableCDNPush - This switch lets you enable the HTTP/2 CDN Server Push feature. This operates by sending a Link header on every request and may also work with reverse-proxies like Nginx for doing HTTP/2 server pushes. +DisableNoavatarRange - This switch lets you disable the noavatar algorithm which maps IDs to a set ranging from 0 to 50 for better cacheability. Default: false + +DisableDefaultNoavatar - This switch lets you disable the default noavatar algorithm which may intercept noavatars for increased efficiency. Default: false + NoAvatar - The default avatar to use for users when they don't have their own. The default for this may change in the near future to better utilise HTTP/2. Example: https://api.adorable.io/avatars/{width}/{id}.png ItemsPerPage - The number of posts, topics, etc. you want on each page. diff --git a/langs/english.json b/langs/english.json index f3a4408b..f8f70c2d 100644 --- a/langs/english.json +++ b/langs/english.json @@ -960,6 +960,7 @@ "panel_themes_menus_head":"Menus", "panel_themes_menus_main":"Main Menu", + "panel_themes_menus_items_suffix":" items", "panel_themes_menus_items_head":"Menu Items", "panel_themes_menus_items_edit_button_aria":"Edit menu item", "panel_themes_menus_items_delete_button_aria":"Delete menu item", diff --git a/public/analytics.js b/public/analytics.js index 6b8ea95e..90ee0d4b 100644 --- a/public/analytics.js +++ b/public/analytics.js @@ -8,13 +8,20 @@ const Gigabyte = Megabyte * 1024; const Terabyte = Gigabyte * 1024; const Petabyte = Terabyte * 1024; -function convertByteUnit(bytes) { - if(bytes >= Petabyte) return Math.ceil(bytes / Petabyte) + "PB"; - else if(bytes >= Terabyte) return Math.ceil(bytes / Terabyte) + "TB"; - else if(bytes >= Gigabyte) return Math.ceil(bytes / Gigabyte) + "GB"; - else if(bytes >= Megabyte) return Math.ceil(bytes / Megabyte) + "MB"; - else if(bytes >= Kilobyte) return Math.ceil(bytes / Kilobyte) + "KB"; - return bytes; +function convertByteUnit(bytes, places = 0) { + let out; + if(bytes >= Petabyte) out = [bytes / Petabyte, "PB"]; + else if(bytes >= Terabyte) out = [bytes / Terabyte, "TB"]; + else if(bytes >= Gigabyte) out = [bytes / Gigabyte, "GB"]; + else if(bytes >= Megabyte) out = [bytes / Megabyte, "MB"]; + else if(bytes >= Kilobyte) out = [bytes / Kilobyte, "KB"]; + else out = [bytes,"b"]; + + if(places==0) return Math.ceil(out[0]) + out[1]; + else { + let ex = Math.pow(10, places); + return (Math.round(out[0], ex) / ex) + out[1]; + } } // TODO: Fully localise this diff --git a/public/n1-200.png b/public/n1-200.png new file mode 100644 index 0000000000000000000000000000000000000000..1335aa37f9d4ee8a6faa2d918e79cbb76dd4c0e9 GIT binary patch literal 16937 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 literal 0 HcmV?d00001 diff --git a/public/n2-200.png b/public/n2-200.png new file mode 100644 index 0000000000000000000000000000000000000000..56d35bcafcc0f53a7441f93e51ea16192099af81 GIT binary patch literal 12906 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 d8jO8H`{MvnEC#{|~Ietb70f literal 0 HcmV?d00001 diff --git a/public/n3-48.png b/public/n3-48.png new file mode 100644 index 0000000000000000000000000000000000000000..cd1726fe29417cf82c1deaf39ddf35a22c7a79d2 GIT binary patch literal 1599 zcmV-F2Eh4=P)dGDcKZW}(5S#^?HAkf%mTQKzrct?u4784iM*E}E@>=eVW`ot& ztscYxJXB~&nQBmN7zuPIjF{|``%;d)@#b4ssswt=IBhKo4`GhZGJb|#_0GHRvpGCl z&lAcM^ctOVckVa&uHI3tY256Xv^b~mX?9H2)^}EMMF#5xwW`MCZQ|=2nl;%uCm0Nd zAJEKC(E&m@OpeLJX}Pd+mVLEVWP?$y$xC51+I*Y~4JD;z1D;=Q+)@;sugN3Ih|`xE zTl5-(`!F-JQ+^+y;V_V_Rbh$K#WR|^RlCL`)q+*YM_ka^@-^^Fc{bGUE= ztnEUH$^PhD;w+oZCWylQ`%|-W2+znLEEelTUa`eB{XB>sY@_Xtjd!a%lKh{C)UXIw zU9Xe!ZppwT$`H0LRovh7(Kef-Uv2PO96qn_Pp|JUa^xBI;OKo)ce5#R#cGxQA-%lD z=w}t^wLntSa{vfy<3?v5n|VTll~vcpJ9g}F4^1j{58K7AlCp+;;zHr~m;GTik2_q0 z2?>XRRDzWf%1xCWb!L==FK*7Z=FoX8^$0^twL+U+sn?Ea9?}K z=qduPWM<`kuzDTR4b3h+^W>h-zr@WU=GQem@#d{bYu0WM%kDmJXP($d*ibT$E{}*& zKEc_wJ2jsu1;=+L?fv0w<+}Bomo9s6^_ul)HIxVmul42!6fFF(%ULF7W zPq;xpZx$FO-Tgv|3zDrv+N(B>%qn0nw@5NnQwv$CL0EJ|%*1+g>PDshMNZ8UbeKp* zYA)gXB7**c8DY1l454ZB+bu$|6CFOUptPf_H&C4gca@hfa!&0F=qK~pARp53$BXsQ z0ugy=Cb1`=6|YveizKdw7A?(&P+<**HP@lQ@9eq;MKOm5Jrhb5F+!`e5x~0HsI0%O zrj*dD9Eqr3p<&v^P8dXqk1k}is{n;Y6UxNAfC5}aVxNE|56~phracHjMuLXchY>iE z45J%kaJHwCpjBjnwhYX#xV>!fpHJ+*tJSxgS`D=Bjx!*uYl>ILudSC;()(2~#Ux~; z&OF}I)^)D9z&h@DdBiGzn`8g0KoWVF~lCQF}IXTDTXd9Jud>*o`>*dC%Wsr^0GYjRBA zBcGY9LtD0Nmnz(`)I-s}O2gVhiL>bZwdB-{#FcAV*#-WJtcjC{sKeTY%eR*=Py8zP z)bnOO9Jef+$^5ZKzHV=F8dMZc0SnIjSOM~&M)TXvc?BhbF9PD|A-@`wsRl%yJv5OQ xR;*+8;+&SSuYxAF9(oYTYv{NE`uF_T@iz%R8&2B?F0B9n002ovPDHLkV1kWC1Xut7 literal 0 HcmV?d00001 diff --git a/public/n4-200.png b/public/n4-200.png new file mode 100644 index 0000000000000000000000000000000000000000..25ce6d778b50d13b87bf4ad6cd02433dc2e6edf1 GIT binary patch literal 12467 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 literal 0 HcmV?d00001 diff --git a/routes/misc.go b/routes/misc.go index 016c5d9c..b1b69fe1 100644 --- a/routes/misc.go +++ b/routes/misc.go @@ -14,6 +14,7 @@ import ( ) var cacheControlMaxAge = "max-age=" + strconv.Itoa(int(c.Day)) // TODO: Make this a c.Config value +var cacheControlMaxAgeWeek = "max-age=" + strconv.Itoa(int(c.Week)) // TODO: Make this a c.Config value // GET functions func StaticFile(w http.ResponseWriter, r *http.Request) { @@ -33,7 +34,11 @@ func StaticFile(w http.ResponseWriter, r *http.Request) { } h.Set("Last-Modified", file.FormattedModTime) h.Set("Content-Type", file.Mimetype) - h.Set("Cache-Control", cacheControlMaxAge) //Cache-Control: max-age=31536000 + if len(file.Sha256) != 0 { + h.Set("Cache-Control", cacheControlMaxAgeWeek) + } else { + h.Set("Cache-Control", cacheControlMaxAge) //Cache-Control: max-age=31536000 + } h.Set("Vary", "Accept-Encoding") if strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") && file.GzipLength > 0 { diff --git a/routes/panel/backups.go b/routes/panel/backups.go index 07ecf3af..89494020 100644 --- a/routes/panel/backups.go +++ b/routes/panel/backups.go @@ -57,6 +57,5 @@ func Backups(w http.ResponseWriter, r *http.Request, user c.User, backupURL stri backupList = append(backupList, c.BackupItem{backupFile.Name(), backupFile.ModTime()}) } - pi := c.PanelBackupPage{basePage, backupList} - return renderTemplate("panel_backups", w, r, basePage.Header, &pi) + return renderTemplate("panel", w, r, basePage.Header, c.Panel{basePage,"","","panel_backups", c.PanelBackupPage{basePage, backupList}}) } diff --git a/routes/panel/debug.go b/routes/panel/debug.go index fb411174..fa112320 100644 --- a/routes/panel/debug.go +++ b/routes/panel/debug.go @@ -42,5 +42,5 @@ func Debug(w http.ResponseWriter, r *http.Request, user c.User) c.RouteError { runtime.ReadMemStats(&memStats) pi := c.PanelDebugPage{basePage, goVersion, dbVersion, uptime, openConnCount, qgen.Builder.GetAdapter().GetName(), goroutines, cpus, memStats} - return renderTemplate("panel_debug", w, r, basePage.Header, &pi) + return renderTemplate("panel", w, r, basePage.Header, c.Panel{basePage,"panel_dashboard_right","","panel_debug", pi}) } diff --git a/routes/panel/logs.go b/routes/panel/logs.go index 4d2acc6a..8d0ded09 100644 --- a/routes/panel/logs.go +++ b/routes/panel/logs.go @@ -34,7 +34,7 @@ func LogsRegs(w http.ResponseWriter, r *http.Request, user c.User) c.RouteError pageList := c.Paginate(logCount, perPage, 5) pi := c.PanelRegLogsPage{basePage, llist, c.Paginator{pageList, page, lastPage}} - return renderTemplate("panel_reglogs", w, r, basePage.Header, &pi) + return renderTemplate("panel", w, r, basePage.Header, c.Panel{basePage,"","","panel_reglogs", pi}) } // TODO: Log errors when something really screwy is going on? @@ -125,7 +125,7 @@ func LogsMod(w http.ResponseWriter, r *http.Request, user c.User) c.RouteError { pageList := c.Paginate(logCount, perPage, 5) pi := c.PanelLogsPage{basePage, llist, c.Paginator{pageList, page, lastPage}} - return renderTemplate("panel_modlogs", w, r, basePage.Header, &pi) + return renderTemplate("panel", w, r, basePage.Header, c.Panel{basePage,"","","panel_modlogs", pi}) } func LogsAdmin(w http.ResponseWriter, r *http.Request, user c.User) c.RouteError { @@ -152,5 +152,5 @@ func LogsAdmin(w http.ResponseWriter, r *http.Request, user c.User) c.RouteError pageList := c.Paginate(logCount, perPage, 5) pi := c.PanelLogsPage{basePage, llist, c.Paginator{pageList, page, lastPage}} - return renderTemplate("panel_adminlogs", w, r, basePage.Header, &pi) + return renderTemplate("panel", w, r, basePage.Header, c.Panel{basePage,"","","panel_adminlogs", pi}) } diff --git a/routes/panel/plugins.go b/routes/panel/plugins.go index ed834d57..af6f77e3 100644 --- a/routes/panel/plugins.go +++ b/routes/panel/plugins.go @@ -22,8 +22,7 @@ func Plugins(w http.ResponseWriter, r *http.Request, user c.User) c.RouteError { pluginList = append(pluginList, plugin) } - pi := c.PanelPage{basePage, pluginList, nil} - return renderTemplate("panel_plugins", w, r, basePage.Header, &pi) + return renderTemplate("panel", w, r, basePage.Header, c.Panel{basePage,"","","panel_plugins", c.PanelPage{basePage, pluginList, nil}}) } // TODO: Abstract more of the plugin activation / installation / deactivation logic, so we can test all that more reliably and easily diff --git a/routes/panel/themes.go b/routes/panel/themes.go index 0b055d73..f5e6ab05 100644 --- a/routes/panel/themes.go +++ b/routes/panel/themes.go @@ -34,7 +34,7 @@ func Themes(w http.ResponseWriter, r *http.Request, user c.User) c.RouteError { } pi := c.PanelThemesPage{basePage, pThemeList, vThemeList} - return renderTemplate("panel_themes", w, r, basePage.Header, &pi) + return renderTemplate("panel", w, r, basePage.Header, c.Panel{basePage,"panel_themes","","panel_themes",&pi}) } func ThemesSetDefault(w http.ResponseWriter, r *http.Request, user c.User, uname string) c.RouteError { @@ -85,8 +85,7 @@ func ThemesMenus(w http.ResponseWriter, r *http.Request, user c.User) c.RouteErr }) } - pi := c.PanelMenuListPage{basePage, menuList} - return renderTemplate("panel_themes_menus", w, r, basePage.Header, &pi) + return renderTemplate("panel", w, r, basePage.Header, c.Panel{basePage,"","","panel_themes_menus", &c.PanelMenuListPage{basePage, menuList}}) } func ThemesMenusEdit(w http.ResponseWriter, r *http.Request, user c.User, smid string) c.RouteError { @@ -133,8 +132,7 @@ func ThemesMenusEdit(w http.ResponseWriter, r *http.Request, user c.User, smid s menuList = append(menuList, item) } - pi := c.PanelMenuPage{basePage, mid, menuList} - return renderTemplate("panel_themes_menus_items", w, r, basePage.Header, &pi) + return renderTemplate("panel", w, r, basePage.Header, c.Panel{basePage,"","","panel_themes_menus_items", &c.PanelMenuPage{basePage, mid, menuList}}) } func ThemesMenuItemEdit(w http.ResponseWriter, r *http.Request, user c.User, sitemID string) c.RouteError { @@ -159,8 +157,7 @@ func ThemesMenuItemEdit(w http.ResponseWriter, r *http.Request, user c.User, sit return c.InternalError(err, w, r) } - pi := c.PanelMenuItemPage{basePage, menuItem} - return renderTemplate("panel_themes_menus_item_edit", w, r, basePage.Header, &pi) + return renderTemplate("panel", w, r, basePage.Header, c.Panel{basePage,"","","panel_themes_menus_item_edit", &c.PanelMenuItemPage{basePage, menuItem}}) } func themesMenuItemSetters(r *http.Request, menuItem c.MenuItem) c.MenuItem { @@ -362,7 +359,7 @@ func ThemesWidgets(w http.ResponseWriter, r *http.Request, user c.User) c.RouteE } pi := c.PanelWidgetListPage{basePage, docks, c.WidgetEdit{&c.Widget{ID: 0, Type: "simple"}, make(map[string]string)}} - return renderTemplate("panel_themes_widgets", w, r, basePage.Header, &pi) + return renderTemplate("panel", w, r, basePage.Header, c.Panel{basePage,"","","panel_themes_widgets", pi}) } func widgetsParseInputs(r *http.Request, widget *c.Widget) (*c.WidgetEdit, error) { diff --git a/templates/panel_adminlogs.html b/templates/panel_adminlogs.html index c9fbc462..149690b2 100644 --- a/templates/panel_adminlogs.html +++ b/templates/panel_adminlogs.html @@ -1,8 +1,3 @@ -{{template "header.html" . }} -
-{{template "panel_menu.html" . }} -
-{{template "panel_before_head.html" . }}

{{lang "panel_logs_administration_head"}}

@@ -20,7 +15,4 @@
{{end}} - {{template "paginator.html" . }} - - -{{template "footer.html" . }} + {{template "paginator.html" . }} \ No newline at end of file diff --git a/templates/panel_analytics_memory.html b/templates/panel_analytics_memory.html index 6bb709b4..949a6ec3 100644 --- a/templates/panel_analytics_memory.html +++ b/templates/panel_analytics_memory.html @@ -48,15 +48,33 @@ options = Chartist.extend({}, {}, options); return function byteUnits(chart) { - if (chart instanceof Chartist.Line) { - chart.on('created', function() { - console.log("running created") - let vbits = document.getElementsByClassName("ct-vertical"); - for(let i = 0; i < vbits.length; i++) { - vbits[i].innerHTML = convertByteUnit(vbits[i].innerHTML); - } - }); - } + if(!chart instanceof Chartist.Line) return; + + chart.on('created', function() { + console.log("running created") + const vbits = document.getElementsByClassName("ct-vertical"); + if(vbits==null) return; + + let tbits = []; + for(let i = 0; i < vbits.length; i++) { + tbits[i] = vbits[i].innerHTML; + } + + const calc = (places) => { + if(places==3) return; + + const matcher = vbits[0].innerHTML; + let allMatch = true; + for(let i = 0; i < tbits.length; i++) { + let val = convertByteUnit(tbits[i], places); + if(val!=matcher) allMatch = false; + vbits[i].innerHTML = val; + } + + if(allMatch) calc(places + 1); + } + calc(0); + }); }; }; diff --git a/templates/panel_analytics_posts.html b/templates/panel_analytics_posts.html index 38b8833d..db31a7ca 100644 --- a/templates/panel_analytics_posts.html +++ b/templates/panel_analytics_posts.html @@ -16,7 +16,7 @@
{{range .ViewItems}}
- {{.Time}} + {{.Time}} {{.Count}}{{lang "panel_statistics_posts_suffix"}}
{{else}}
{{lang "panel_statistics_post_counts_no_post_counts"}}
{{end}} diff --git a/templates/panel_analytics_topics.html b/templates/panel_analytics_topics.html index 5a5d7710..a7888f7b 100644 --- a/templates/panel_analytics_topics.html +++ b/templates/panel_analytics_topics.html @@ -16,7 +16,7 @@
{{range .ViewItems}}
- {{.Time}} + {{.Time}} {{.Count}}{{lang "panel_statistics_topics_suffix"}}
{{end}} diff --git a/templates/panel_analytics_views.html b/templates/panel_analytics_views.html index 5b1d5428..6720987a 100644 --- a/templates/panel_analytics_views.html +++ b/templates/panel_analytics_views.html @@ -16,7 +16,7 @@
{{range .ViewItems}}
- {{.Time}} + {{.Time}} {{.Count}}{{lang "panel_statistics_views_suffix"}}
{{end}} diff --git a/templates/panel_backups.html b/templates/panel_backups.html index beeffe1b..d781b52c 100644 --- a/templates/panel_backups.html +++ b/templates/panel_backups.html @@ -1,8 +1,3 @@ -{{template "header.html" . }} -
- {{template "panel_menu.html" . }} -
-{{template "panel_before_head.html" . }}

{{lang "panel_backups_head"}}

@@ -17,7 +12,4 @@ {{else}}
{{lang "panel_backups_no_backups"}}
{{end}} -
- -
-{{template "footer.html" . }} +
\ No newline at end of file diff --git a/templates/panel_debug.html b/templates/panel_debug.html index 137a8fa6..90004f49 100644 --- a/templates/panel_debug.html +++ b/templates/panel_debug.html @@ -1,8 +1,3 @@ -{{template "header.html" . }} -
-{{template "panel_menu.html" . }} -
-{{template "panel_before_head.html" . }}

{{lang "panel_debug_head"}}

@@ -48,7 +43,4 @@
?
?
{{.MemStats.StackInuse}}
-
- -
-{{template "footer.html" . }} + \ No newline at end of file diff --git a/templates/panel_modlogs.html b/templates/panel_modlogs.html index 41152c3c..ae1348a0 100644 --- a/templates/panel_modlogs.html +++ b/templates/panel_modlogs.html @@ -1,8 +1,3 @@ -{{template "header.html" . }} -
-{{template "panel_menu.html" . }} -
-{{template "panel_before_head.html" . }}

{{lang "panel_logs_moderation_head"}}

@@ -20,7 +15,4 @@
{{end}} - {{template "paginator.html" . }} - - -{{template "footer.html" . }} + {{template "paginator.html" . }} \ No newline at end of file diff --git a/templates/panel_plugins.html b/templates/panel_plugins.html index e35717f1..d0a3e709 100644 --- a/templates/panel_plugins.html +++ b/templates/panel_plugins.html @@ -1,9 +1,3 @@ -{{template "header.html" . }} -
- -{{template "panel_menu.html" . }} -
-{{template "panel_before_head.html" . }}

{{lang "panel_plugins_head"}}

@@ -24,8 +18,4 @@
{{end}} - - - - -{{template "footer.html" . }} + \ No newline at end of file diff --git a/templates/panel_reglogs.html b/templates/panel_reglogs.html index e2313739..0b2b3495 100644 --- a/templates/panel_reglogs.html +++ b/templates/panel_reglogs.html @@ -1,14 +1,9 @@ -{{template "header.html" . }} -
-{{template "panel_menu.html" . }} -
-{{template "panel_before_head.html" . }}

{{lang "panel_logs_registration_head"}}

{{range .Logs}} -
+
{{if not .Success}}{{lang "panel_logs_registration_attempt"}}: {{end}}{{.Username}} ({{lang "panel_logs_registration_email"}}: {{.Email}}){{if .ParsedReason}} ({{lang "panel_logs_registration_reason"}}: {{.ParsedReason}}){{end}} {{if $.CurrentUser.Perms.ViewIPs}}
{{.IPAddress}}{{end}} @@ -20,7 +15,4 @@
{{end}}
- {{template "paginator.html" . }} -
-
-{{template "footer.html" . }} + {{template "paginator.html" . }} \ No newline at end of file diff --git a/templates/panel_themes.html b/templates/panel_themes.html index d8e6c51b..590f6469 100644 --- a/templates/panel_themes.html +++ b/templates/panel_themes.html @@ -1,17 +1,3 @@ -{{template "header.html" . }} -
-{{template "panel_menu.html" . }} -{{/** Stop inlining this x.x **/}} - - -
-{{template "panel_before_head.html" . }}

{{lang "panel_themes_primary_themes"}}

@@ -49,8 +35,4 @@
{{end}} - {{end}} - - - -{{template "footer.html" . }} + {{end}} \ No newline at end of file diff --git a/templates/panel_themes_menus.html b/templates/panel_themes_menus.html index 2ce4bf5a..cf514559 100644 --- a/templates/panel_themes_menus.html +++ b/templates/panel_themes_menus.html @@ -1,8 +1,3 @@ -{{template "header.html" . }} -
-{{template "panel_menu.html" . }} -
-{{template "panel_before_head.html" . }}

{{lang "panel_themes_menus_head"}}

@@ -10,10 +5,7 @@ {{range .ItemList}} {{end}} -
- - -{{template "footer.html" . }} + \ No newline at end of file diff --git a/templates/panel_themes_menus_item_edit.html b/templates/panel_themes_menus_item_edit.html index aec7329a..26c0ca8d 100644 --- a/templates/panel_themes_menus_item_edit.html +++ b/templates/panel_themes_menus_item_edit.html @@ -1,10 +1,5 @@ -{{template "header.html" . }} -
{{/** TODO: Set the order based on the order here **/}} {{/** 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"}}

@@ -59,11 +54,9 @@
-
+
+ +
- - - - -{{template "footer.html" . }} + \ No newline at end of file diff --git a/templates/panel_themes_menus_items.html b/templates/panel_themes_menus_items.html index 7686ce7e..b82ec6d0 100644 --- a/templates/panel_themes_menus_items.html +++ b/templates/panel_themes_menus_items.html @@ -1,8 +1,3 @@ -{{template "header.html" . }} -
-{{template "panel_menu.html" . }} -
-{{template "panel_before_head.html" . }}

{{lang "panel_themes_menus_items_head"}}

@@ -77,7 +72,4 @@
- -
-
-{{template "footer.html" . }} \ No newline at end of file + \ No newline at end of file diff --git a/templates/panel_themes_widgets.html b/templates/panel_themes_widgets.html index b437d396..8281bb29 100644 --- a/templates/panel_themes_widgets.html +++ b/templates/panel_themes_widgets.html @@ -9,11 +9,6 @@ type Widget struct { Literal bool } **/}} -{{template "header.html" . }} -
-{{template "panel_menu.html" . }} -
-{{template "panel_before_head.html" . }}

{{lang "panel_themes_widgets_head"}}

@@ -55,7 +50,4 @@ type Widget struct {
- - - -{{template "footer.html" . }} \ No newline at end of file + \ No newline at end of file diff --git a/themes/nox/public/panel.css b/themes/nox/public/panel.css index 1a758728..6a39147c 100644 --- a/themes/nox/public/panel.css +++ b/themes/nox/public/panel.css @@ -87,7 +87,7 @@ background-color: #444444; } .colstack_right .colstack_head.colstack_sub_head:not(:first-child) { - margin-top: 6px; + margin-top: 12px; } .colstack_head + .colstack_head.colstack_sub_head:not(:first-child) { margin-top: 2px; diff --git a/themes/shadow/public/panel.css b/themes/shadow/public/panel.css index 20ae1217..6c7c3c85 100644 --- a/themes/shadow/public/panel.css +++ b/themes/shadow/public/panel.css @@ -81,6 +81,12 @@ padding-right: 2px; } +#panel_themes .rowitem::after { + content: ""; + display: block; + clear: both; +} + .panel_submitrow .rowitem { display: flex; } diff --git a/themes/tempra_simple/public/panel.css b/themes/tempra_simple/public/panel.css index 4377372b..ccf7fb3d 100644 --- a/themes/tempra_simple/public/panel.css +++ b/themes/tempra_simple/public/panel.css @@ -187,4 +187,10 @@ } .wtype_about .w_about, .wtype_simple .w_simple, .wtype_wol .w_wol, .wtype_default .w_default { display: block; +} + +#panel_themes .rowitem::after { + content: ""; + display: block; + clear: both; } \ No newline at end of file