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.
This commit is contained in:
Azareal 2019-05-03 18:34:18 +10:00
parent a8e1076f7c
commit a1161e20f3
38 changed files with 129 additions and 166 deletions

View File

@ -1,7 +1,7 @@
/* /*
* *
* Gosora Alerts System * Gosora Alerts System
* Copyright Azareal 2017 - 2019 * Copyright Azareal 2017 - 2020
* *
*/ */
package common package common

View File

@ -96,6 +96,8 @@ type config struct {
LoosePort bool LoosePort bool
DisableServerPush bool DisableServerPush bool
EnableCDNPush bool EnableCDNPush bool
DisableNoavatarRange bool
DisableDefaultNoavatar bool
Noavatar string // ? - Move this into the settings table? Noavatar string // ? - Move this into the settings table?
ItemsPerPage int // ? - Move this into the settings table? ItemsPerPage int // ? - Move this into the settings table?

View File

@ -1,7 +1,7 @@
/* /*
* *
* Gosora User File * Gosora User File
* Copyright Azareal 2017 - 2019 * Copyright Azareal 2017 - 2020
* *
*/ */
package common package common
@ -456,27 +456,45 @@ type GuestAvatar struct {
} }
func buildNoavatar(uid int, width int) string { 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) return strings.Replace(strings.Replace(Config.Noavatar, "{id}", strconv.Itoa(uid), 1), "{width}", strconv.Itoa(width), 1)
} }
// ? Make this part of *User? // ? Make this part of *User?
// TODO: Write tests for this // TODO: Write tests for this
func BuildAvatar(uid int, avatar string) (normalAvatar string, microAvatar string) { func BuildAvatar(uid int, avatar string) (normalAvatar string, microAvatar string) {
if avatar != "" { if avatar == "" {
if avatar[0] == '.' { if uid == 0 {
if avatar[1] == '.' { return guestAvatar.Normal, guestAvatar.Micro
normalAvatar = "/uploads/avatar_" + strconv.Itoa(uid) + "_tmp" + avatar[1:] }
return normalAvatar, normalAvatar return buildNoavatar(uid, 200), buildNoavatar(uid, 48)
} }
normalAvatar = "/uploads/avatar_" + strconv.Itoa(uid) + avatar if avatar[0] == '.' {
if avatar[1] == '.' {
normalAvatar = "/uploads/avatar_" + strconv.Itoa(uid) + "_tmp" + avatar[1:]
return normalAvatar, normalAvatar return normalAvatar, normalAvatar
} }
return avatar, avatar normalAvatar = "/uploads/avatar_" + strconv.Itoa(uid) + avatar
return normalAvatar, normalAvatar
} }
if uid == 0 { return avatar, avatar
return guestAvatar.Normal, guestAvatar.Micro
}
return buildNoavatar(uid, 200), buildNoavatar(uid, 48)
} }
// TODO: Move this to *User // TODO: Move this to *User

View File

@ -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. 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 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. ItemsPerPage - The number of posts, topics, etc. you want on each page.

View File

@ -960,6 +960,7 @@
"panel_themes_menus_head":"Menus", "panel_themes_menus_head":"Menus",
"panel_themes_menus_main":"Main Menu", "panel_themes_menus_main":"Main Menu",
"panel_themes_menus_items_suffix":" items",
"panel_themes_menus_items_head":"Menu Items", "panel_themes_menus_items_head":"Menu Items",
"panel_themes_menus_items_edit_button_aria":"Edit menu item", "panel_themes_menus_items_edit_button_aria":"Edit menu item",
"panel_themes_menus_items_delete_button_aria":"Delete menu item", "panel_themes_menus_items_delete_button_aria":"Delete menu item",

View File

@ -8,13 +8,20 @@ const Gigabyte = Megabyte * 1024;
const Terabyte = Gigabyte * 1024; const Terabyte = Gigabyte * 1024;
const Petabyte = Terabyte * 1024; const Petabyte = Terabyte * 1024;
function convertByteUnit(bytes) { function convertByteUnit(bytes, places = 0) {
if(bytes >= Petabyte) return Math.ceil(bytes / Petabyte) + "PB"; let out;
else if(bytes >= Terabyte) return Math.ceil(bytes / Terabyte) + "TB"; if(bytes >= Petabyte) out = [bytes / Petabyte, "PB"];
else if(bytes >= Gigabyte) return Math.ceil(bytes / Gigabyte) + "GB"; else if(bytes >= Terabyte) out = [bytes / Terabyte, "TB"];
else if(bytes >= Megabyte) return Math.ceil(bytes / Megabyte) + "MB"; else if(bytes >= Gigabyte) out = [bytes / Gigabyte, "GB"];
else if(bytes >= Kilobyte) return Math.ceil(bytes / Kilobyte) + "KB"; else if(bytes >= Megabyte) out = [bytes / Megabyte, "MB"];
return bytes; 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 // TODO: Fully localise this

BIN
public/n1-200.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
public/n1-48.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

BIN
public/n2-200.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
public/n2-48.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

BIN
public/n3-200.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

BIN
public/n3-48.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
public/n4-200.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
public/n4-48.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -14,6 +14,7 @@ import (
) )
var cacheControlMaxAge = "max-age=" + strconv.Itoa(int(c.Day)) // TODO: Make this a c.Config value 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 // GET functions
func StaticFile(w http.ResponseWriter, r *http.Request) { 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("Last-Modified", file.FormattedModTime)
h.Set("Content-Type", file.Mimetype) 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") h.Set("Vary", "Accept-Encoding")
if strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") && file.GzipLength > 0 { if strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") && file.GzipLength > 0 {

View File

@ -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()}) backupList = append(backupList, c.BackupItem{backupFile.Name(), backupFile.ModTime()})
} }
pi := c.PanelBackupPage{basePage, backupList} return renderTemplate("panel", w, r, basePage.Header, c.Panel{basePage,"","","panel_backups", c.PanelBackupPage{basePage, backupList}})
return renderTemplate("panel_backups", w, r, basePage.Header, &pi)
} }

View File

@ -42,5 +42,5 @@ func Debug(w http.ResponseWriter, r *http.Request, user c.User) c.RouteError {
runtime.ReadMemStats(&memStats) runtime.ReadMemStats(&memStats)
pi := c.PanelDebugPage{basePage, goVersion, dbVersion, uptime, openConnCount, qgen.Builder.GetAdapter().GetName(), goroutines, cpus, 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})
} }

View File

@ -34,7 +34,7 @@ func LogsRegs(w http.ResponseWriter, r *http.Request, user c.User) c.RouteError
pageList := c.Paginate(logCount, perPage, 5) pageList := c.Paginate(logCount, perPage, 5)
pi := c.PanelRegLogsPage{basePage, llist, c.Paginator{pageList, page, lastPage}} 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? // 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) pageList := c.Paginate(logCount, perPage, 5)
pi := c.PanelLogsPage{basePage, llist, c.Paginator{pageList, page, lastPage}} 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 { 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) pageList := c.Paginate(logCount, perPage, 5)
pi := c.PanelLogsPage{basePage, llist, c.Paginator{pageList, page, lastPage}} 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})
} }

View File

@ -22,8 +22,7 @@ func Plugins(w http.ResponseWriter, r *http.Request, user c.User) c.RouteError {
pluginList = append(pluginList, plugin) pluginList = append(pluginList, plugin)
} }
pi := c.PanelPage{basePage, pluginList, nil} return renderTemplate("panel", w, r, basePage.Header, c.Panel{basePage,"","","panel_plugins", c.PanelPage{basePage, pluginList, nil}})
return renderTemplate("panel_plugins", w, r, basePage.Header, &pi)
} }
// TODO: Abstract more of the plugin activation / installation / deactivation logic, so we can test all that more reliably and easily // TODO: Abstract more of the plugin activation / installation / deactivation logic, so we can test all that more reliably and easily

View File

@ -34,7 +34,7 @@ func Themes(w http.ResponseWriter, r *http.Request, user c.User) c.RouteError {
} }
pi := c.PanelThemesPage{basePage, pThemeList, vThemeList} 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 { 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", w, r, basePage.Header, c.Panel{basePage,"","","panel_themes_menus", &c.PanelMenuListPage{basePage, menuList}})
return renderTemplate("panel_themes_menus", w, r, basePage.Header, &pi)
} }
func ThemesMenusEdit(w http.ResponseWriter, r *http.Request, user c.User, smid string) c.RouteError { 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) menuList = append(menuList, item)
} }
pi := c.PanelMenuPage{basePage, mid, menuList} return renderTemplate("panel", w, r, basePage.Header, c.Panel{basePage,"","","panel_themes_menus_items", &c.PanelMenuPage{basePage, mid, menuList}})
return renderTemplate("panel_themes_menus_items", w, r, basePage.Header, &pi)
} }
func ThemesMenuItemEdit(w http.ResponseWriter, r *http.Request, user c.User, sitemID string) c.RouteError { 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) return c.InternalError(err, w, r)
} }
pi := c.PanelMenuItemPage{basePage, menuItem} return renderTemplate("panel", w, r, basePage.Header, c.Panel{basePage,"","","panel_themes_menus_item_edit", &c.PanelMenuItemPage{basePage, menuItem}})
return renderTemplate("panel_themes_menus_item_edit", w, r, basePage.Header, &pi)
} }
func themesMenuItemSetters(r *http.Request, menuItem c.MenuItem) c.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)}} 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) { func widgetsParseInputs(r *http.Request, widget *c.Widget) (*c.WidgetEdit, error) {

View File

@ -1,8 +1,3 @@
{{template "header.html" . }}
<div class="colstack panel_stack">
{{template "panel_menu.html" . }}
<main class="colstack_right">
{{template "panel_before_head.html" . }}
<div class="colstack_item colstack_head"> <div class="colstack_item colstack_head">
<div class="rowitem"><h1>{{lang "panel_logs_administration_head"}}</h1></div> <div class="rowitem"><h1>{{lang "panel_logs_administration_head"}}</h1></div>
</div> </div>
@ -20,7 +15,4 @@
</div> </div>
{{end}} {{end}}
</div> </div>
{{template "paginator.html" . }} {{template "paginator.html" . }}
</main>
</div>
{{template "footer.html" . }}

View File

@ -48,15 +48,33 @@
options = Chartist.extend({}, {}, options); options = Chartist.extend({}, {}, options);
return function byteUnits(chart) { return function byteUnits(chart) {
if (chart instanceof Chartist.Line) { if(!chart instanceof Chartist.Line) return;
chart.on('created', function() {
console.log("running created") chart.on('created', function() {
let vbits = document.getElementsByClassName("ct-vertical"); console.log("running created")
for(let i = 0; i < vbits.length; i++) { const vbits = document.getElementsByClassName("ct-vertical");
vbits[i].innerHTML = convertByteUnit(vbits[i].innerHTML); 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);
});
}; };
}; };

View File

@ -16,7 +16,7 @@
<div id="panel_analytics_posts_table" class="colstack_item rowlist" aria-label="{{lang "panel_statistics_post_counts_table_aria"}}"> <div id="panel_analytics_posts_table" class="colstack_item rowlist" aria-label="{{lang "panel_statistics_post_counts_table_aria"}}">
{{range .ViewItems}} {{range .ViewItems}}
<div class="rowitem panel_compactrow editable_parent"> <div class="rowitem panel_compactrow editable_parent">
<a class="panel_upshift {{if or (or (or (eq $.TimeRange "six-hours") (eq $.TimeRange "twelve-hours")) (eq $.TimeRange "one-day")) (eq $.TimeRange "two-days")}}unix_to_24_hour_time{{else}}unix_to_date{{end}}">{{.Time}}</a> <a class="panel_upshift unix_{{if or (or (or (eq $.TimeRange "six-hours") (eq $.TimeRange "twelve-hours")) (eq $.TimeRange "one-day")) (eq $.TimeRange "two-days")}}to_24_hour_time{{else}}to_date{{end}}">{{.Time}}</a>
<span class="panel_compacttext to_right">{{.Count}}{{lang "panel_statistics_posts_suffix"}}</span> <span class="panel_compacttext to_right">{{.Count}}{{lang "panel_statistics_posts_suffix"}}</span>
</div> </div>
{{else}}<div class="rowitem passive rowmsg">{{lang "panel_statistics_post_counts_no_post_counts"}}</div>{{end}} {{else}}<div class="rowitem passive rowmsg">{{lang "panel_statistics_post_counts_no_post_counts"}}</div>{{end}}

View File

@ -16,7 +16,7 @@
<div id="panel_analytics_topics_table" class="colstack_item rowlist" aria-label="{{lang "panel_statistics_topic_counts_table_aria"}}"> <div id="panel_analytics_topics_table" class="colstack_item rowlist" aria-label="{{lang "panel_statistics_topic_counts_table_aria"}}">
{{range .ViewItems}} {{range .ViewItems}}
<div class="rowitem panel_compactrow editable_parent"> <div class="rowitem panel_compactrow editable_parent">
<a class="panel_upshift {{if or (or (or (eq $.TimeRange "six-hours") (eq $.TimeRange "twelve-hours")) (eq $.TimeRange "one-day")) (eq $.TimeRange "two-days")}}unix_to_24_hour_time{{else}}unix_to_date{{end}}">{{.Time}}</a> <a class="panel_upshift unix_{{if or (or (or (eq $.TimeRange "six-hours") (eq $.TimeRange "twelve-hours")) (eq $.TimeRange "one-day")) (eq $.TimeRange "two-days")}}to_24_hour_time{{else}}to_date{{end}}">{{.Time}}</a>
<span class="panel_compacttext to_right">{{.Count}}{{lang "panel_statistics_topics_suffix"}}</span> <span class="panel_compacttext to_right">{{.Count}}{{lang "panel_statistics_topics_suffix"}}</span>
</div> </div>
{{end}} {{end}}

View File

@ -16,7 +16,7 @@
<div id="panel_analytics_views_table" class="colstack_item rowlist" aria-label="{{lang "panel_statistics_requests_table_aria"}}"> <div id="panel_analytics_views_table" class="colstack_item rowlist" aria-label="{{lang "panel_statistics_requests_table_aria"}}">
{{range .ViewItems}} {{range .ViewItems}}
<div class="rowitem panel_compactrow editable_parent"> <div class="rowitem panel_compactrow editable_parent">
<a class="panel_upshift {{if or (or (or (eq $.TimeRange "six-hours") (eq $.TimeRange "twelve-hours")) (eq $.TimeRange "one-day")) (eq $.TimeRange "two-days")}}unix_to_24_hour_time{{else}}unix_to_date{{end}}">{{.Time}}</a> <a class="panel_upshift unix_{{if or (or (or (eq $.TimeRange "six-hours") (eq $.TimeRange "twelve-hours")) (eq $.TimeRange "one-day")) (eq $.TimeRange "two-days")}}to_24_hour_time{{else}}to_date{{end}}">{{.Time}}</a>
<span class="panel_compacttext to_right">{{.Count}}{{lang "panel_statistics_views_suffix"}}</span> <span class="panel_compacttext to_right">{{.Count}}{{lang "panel_statistics_views_suffix"}}</span>
</div> </div>
{{end}} {{end}}

View File

@ -1,8 +1,3 @@
{{template "header.html" . }}
<div class="colstack panel_stack">
{{template "panel_menu.html" . }}
<main class="colstack_right">
{{template "panel_before_head.html" . }}
<div class="colstack_item colstack_head"> <div class="colstack_item colstack_head">
<div class="rowitem"><h1>{{lang "panel_backups_head"}}</h1></div> <div class="rowitem"><h1>{{lang "panel_backups_head"}}</h1></div>
</div> </div>
@ -17,7 +12,4 @@
{{else}} {{else}}
<div class="rowitem rowmsg">{{lang "panel_backups_no_backups"}}</div> <div class="rowitem rowmsg">{{lang "panel_backups_no_backups"}}</div>
{{end}} {{end}}
</div> </div>
</main>
</div>
{{template "footer.html" . }}

View File

@ -1,8 +1,3 @@
{{template "header.html" . }}
<div class="colstack panel_stack">
{{template "panel_menu.html" . }}
<main id="panel_dashboard_right" class="colstack_right">
{{template "panel_before_head.html" . }}
<div class="colstack_item colstack_head"> <div class="colstack_item colstack_head">
<div class="rowitem"><h1>{{lang "panel_debug_head"}}</h1></div> <div class="rowitem"><h1>{{lang "panel_debug_head"}}</h1></div>
</div> </div>
@ -48,7 +43,4 @@
<div class="grid_item grid_stat"><span>?</span></div> <div class="grid_item grid_stat"><span>?</span></div>
<div class="grid_item grid_stat"><span>?</span></div> <div class="grid_item grid_stat"><span>?</span></div>
<div class="grid_item grid_stat"><span>{{.MemStats.StackInuse}}</span></div> <div class="grid_item grid_stat"><span>{{.MemStats.StackInuse}}</span></div>
</div> </div>
</main>
</div>
{{template "footer.html" . }}

View File

@ -1,8 +1,3 @@
{{template "header.html" . }}
<div class="colstack panel_stack">
{{template "panel_menu.html" . }}
<main class="colstack_right">
{{template "panel_before_head.html" . }}
<div class="colstack_item colstack_head"> <div class="colstack_item colstack_head">
<div class="rowitem"><h1>{{lang "panel_logs_moderation_head"}}</h1></div> <div class="rowitem"><h1>{{lang "panel_logs_moderation_head"}}</h1></div>
</div> </div>
@ -20,7 +15,4 @@
</div> </div>
{{end}} {{end}}
</div> </div>
{{template "paginator.html" . }} {{template "paginator.html" . }}
</main>
</div>
{{template "footer.html" . }}

View File

@ -1,9 +1,3 @@
{{template "header.html" . }}
<div class="colstack panel_stack">
{{template "panel_menu.html" . }}
<main class="colstack_right">
{{template "panel_before_head.html" . }}
<div class="colstack_item colstack_head"> <div class="colstack_item colstack_head">
<div class="rowitem"><h1>{{lang "panel_plugins_head"}}</h1></div> <div class="rowitem"><h1>{{lang "panel_plugins_head"}}</h1></div>
</div> </div>
@ -24,8 +18,4 @@
</span> </span>
</div> </div>
{{end}} {{end}}
</div> </div>
</main>
</div>
{{template "footer.html" . }}

View File

@ -1,14 +1,9 @@
{{template "header.html" . }}
<div class="colstack panel_stack">
{{template "panel_menu.html" . }}
<main class="colstack_right">
{{template "panel_before_head.html" . }}
<div class="colstack_item colstack_head"> <div class="colstack_item colstack_head">
<div class="rowitem"><h1>{{lang "panel_logs_registration_head"}}</h1></div> <div class="rowitem"><h1>{{lang "panel_logs_registration_head"}}</h1></div>
</div> </div>
<div id="panel_modlogs" class="colstack_item rowlist"> <div id="panel_modlogs" class="colstack_item rowlist">
{{range .Logs}} {{range .Logs}}
<div class="rowitem panel_compactrow {{if not .Success}}bg_red{{end}}"> <div class="rowitem panel_compactrow{{if not .Success}} bg_red{{end}}">
<span{{if not .Success}} class="panel_registration_attempt"{{end}} style="float: left;"> <span{{if not .Success}} class="panel_registration_attempt"{{end}} style="float: left;">
<span>{{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}}</span> <span>{{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}}</span>
{{if $.CurrentUser.Perms.ViewIPs}}<br /><small style="margin-left: 2px;font-size: 12px;" title="{{.IPAddress}}">{{.IPAddress}}</small>{{end}} {{if $.CurrentUser.Perms.ViewIPs}}<br /><small style="margin-left: 2px;font-size: 12px;" title="{{.IPAddress}}">{{.IPAddress}}</small>{{end}}
@ -20,7 +15,4 @@
</div> </div>
{{end}} {{end}}
</div> </div>
{{template "paginator.html" . }} {{template "paginator.html" . }}
</main>
</div>
{{template "footer.html" . }}

View File

@ -1,17 +1,3 @@
{{template "header.html" . }}
<div class="colstack panel_stack">
{{template "panel_menu.html" . }}
{{/** Stop inlining this x.x **/}}
<style type="text/css">
.rowitem::after {
content: "";
display: block;
clear: both;
}
</style>
<main class="colstack_right">
{{template "panel_before_head.html" . }}
<div class="colstack_item colstack_head"> <div class="colstack_item colstack_head">
<div class="rowitem"><h1>{{lang "panel_themes_primary_themes"}}</h1></div> <div class="rowitem"><h1>{{lang "panel_themes_primary_themes"}}</h1></div>
</div> </div>
@ -49,8 +35,4 @@
</div> </div>
{{end}} {{end}}
</div> </div>
{{end}} {{end}}
</main>
</div>
{{template "footer.html" . }}

View File

@ -1,8 +1,3 @@
{{template "header.html" . }}
<div class="colstack panel_stack">
{{template "panel_menu.html" . }}
<main class="colstack_right">
{{template "panel_before_head.html" . }}
<div class="colstack_item colstack_head"> <div class="colstack_item colstack_head">
<div class="rowitem"><h1>{{lang "panel_themes_menus_head"}}</h1></div> <div class="rowitem"><h1>{{lang "panel_themes_menus_head"}}</h1></div>
</div> </div>
@ -10,10 +5,7 @@
{{range .ItemList}} {{range .ItemList}}
<div class="rowitem panel_compactrow editable_parent"> <div class="rowitem panel_compactrow editable_parent">
<a href="/panel/themes/menus/edit/{{.ID}}" class="editable_block panel_upshift">{{if .Name}}{{.Name}} - {{end}}#{{.ID}}</a> <a href="/panel/themes/menus/edit/{{.ID}}" class="editable_block panel_upshift">{{if .Name}}{{.Name}} - {{end}}#{{.ID}}</a>
<a class="panel_compacttext to_right">{{.ItemCount}} items</a> <a class="panel_compacttext to_right">{{.ItemCount}}{{lang "panel_themes_menus_items_suffix"}}</a>
</div> </div>
{{end}} {{end}}
</div> </div>
</main>
</div>
{{template "footer.html" . }}

View File

@ -1,10 +1,5 @@
{{template "header.html" . }}
<div class="colstack panel_stack">
{{/** TODO: Set the order based on the order here **/}} {{/** TODO: Set the order based on the order here **/}}
{{/** TODO: Write the backend code and JS code for saving this menu **/}} {{/** TODO: Write the backend code and JS code for saving this menu **/}}
{{template "panel_menu.html" . }}
<main class="colstack_right">
{{template "panel_before_head.html" . }}
<div class="colstack_item colstack_head"> <div class="colstack_item colstack_head">
<div class="rowitem"><h1>{{lang "panel_themes_menus_edit_head"}}</h1></div> <div class="rowitem"><h1>{{lang "panel_themes_menus_edit_head"}}</h1></div>
</div> </div>
@ -59,11 +54,9 @@
</select></div> </select></div>
</div> </div>
<div class="formrow"> <div class="formrow">
<div class="formitem"><button name="panel-button" class="formbutton">{{lang "panel_themes_menus_edit_update_button"}}</button></div> <div class="formitem">
<button name="panel-button" class="formbutton">{{lang "panel_themes_menus_edit_update_button"}}</button>
</div>
</div> </div>
</div> </div>
</form> </form>
</main>
</div>
{{template "footer.html" . }}

View File

@ -1,8 +1,3 @@
{{template "header.html" . }}
<div class="colstack panel_stack">
{{template "panel_menu.html" . }}
<main class="colstack_right">
{{template "panel_before_head.html" . }}
<div class="colstack_item colstack_head"> <div class="colstack_item colstack_head">
<div class="rowitem"> <div class="rowitem">
<h1>{{lang "panel_themes_menus_items_head"}}</h1> <h1>{{lang "panel_themes_menus_items_head"}}</h1>
@ -77,7 +72,4 @@
<div class="formitem"><button name="panel-button" class="formbutton">{{lang "panel_themes_menus_create_button"}}</button></div> <div class="formitem"><button name="panel-button" class="formbutton">{{lang "panel_themes_menus_create_button"}}</button></div>
</div> </div>
</div> </div>
</form> </form>
</main>
</div>
{{template "footer.html" . }}

View File

@ -9,11 +9,6 @@ type Widget struct {
Literal bool Literal bool
} }
**/}} **/}}
{{template "header.html" . }}
<div class="colstack panel_stack">
{{template "panel_menu.html" . }}
<main class="colstack_right">
{{template "panel_before_head.html" . }}
<div class="colstack_item colstack_head"> <div class="colstack_item colstack_head">
<div class="rowitem"><h1>{{lang "panel_themes_widgets_head"}}</h1></div> <div class="rowitem"><h1>{{lang "panel_themes_widgets_head"}}</h1></div>
</div> </div>
@ -55,7 +50,4 @@ type Widget struct {
</form> </form>
</div> </div>
</div> </div>
</div> </div>
</main>
</div>
{{template "footer.html" . }}

View File

@ -87,7 +87,7 @@
background-color: #444444; background-color: #444444;
} }
.colstack_right .colstack_head.colstack_sub_head:not(:first-child) { .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) { .colstack_head + .colstack_head.colstack_sub_head:not(:first-child) {
margin-top: 2px; margin-top: 2px;

View File

@ -81,6 +81,12 @@
padding-right: 2px; padding-right: 2px;
} }
#panel_themes .rowitem::after {
content: "";
display: block;
clear: both;
}
.panel_submitrow .rowitem { .panel_submitrow .rowitem {
display: flex; display: flex;
} }

View File

@ -187,4 +187,10 @@
} }
.wtype_about .w_about, .wtype_simple .w_simple, .wtype_wol .w_wol, .wtype_default .w_default { .wtype_about .w_about, .wtype_simple .w_simple, .wtype_wol .w_wol, .wtype_default .w_default {
display: block; display: block;
}
#panel_themes .rowitem::after {
content: "";
display: block;
clear: both;
} }