Convert multiple pages into SPA
This commit is contained in:
@@ -45,8 +45,24 @@ func (wc *WebController) serveDirectory(w http.ResponseWriter, r *http.Request,
|
||||
td.Title = fmt.Sprintf("%s ~ pixeldrain", node.Path[node.BaseIndex].Name)
|
||||
td.Other = node
|
||||
td.OGData = wc.metadataFromFilesystem(r, node)
|
||||
err = wc.templates.Run(w, r, "filesystem", td)
|
||||
err = wc.templates.Run(w, r, "wrap", td)
|
||||
if err != nil && !util.IsNetError(err) {
|
||||
log.Error("Error executing template filesystem: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (wc *WebController) serveForbidden(w http.ResponseWriter, r *http.Request) {
|
||||
log.Debug("Forbidden: %s", r.URL)
|
||||
w.WriteHeader(http.StatusForbidden)
|
||||
wc.templates.Run(w, r, "403", wc.newTemplateData(w, r))
|
||||
}
|
||||
|
||||
func (wc *WebController) serveNotFound(w http.ResponseWriter, r *http.Request) {
|
||||
log.Debug("Not Found: %s", r.URL)
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
wc.templates.Run(w, r, "404", wc.newTemplateData(w, r))
|
||||
}
|
||||
func (wc *WebController) serveUnavailableForLegalReasons(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusUnavailableForLegalReasons)
|
||||
wc.templates.Run(w, r, "451", wc.newTemplateData(w, r))
|
||||
}
|
||||
|
@@ -3,10 +3,8 @@ package webcontroller
|
||||
import (
|
||||
"fmt"
|
||||
"html/template"
|
||||
"math/rand"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/julienschmidt/httprouter"
|
||||
)
|
||||
@@ -50,6 +48,10 @@ func userStyle(style string, hue int) template.CSS {
|
||||
switch style {
|
||||
default:
|
||||
fallthrough
|
||||
case "adwaita":
|
||||
def = adwaitaDarkStyle
|
||||
light = adwaitaLightStyle
|
||||
hasLight = true
|
||||
case "nord":
|
||||
def = nordDarkStyle
|
||||
light = nordLightStyle
|
||||
@@ -83,16 +85,14 @@ func userStyle(style string, hue int) template.CSS {
|
||||
def = skeuosPixeldrainStyle
|
||||
case "sweet":
|
||||
def = sweetPixeldrainStyle
|
||||
case "adwaita":
|
||||
def = adwaitaDarkStyle
|
||||
light = adwaitaLightStyle
|
||||
hasLight = true
|
||||
case "adwaita_dark":
|
||||
def = adwaitaDarkStyle
|
||||
case "adwaita_light":
|
||||
def = adwaitaLightStyle
|
||||
case "pixeldrain98":
|
||||
def = pixeldrain98Style
|
||||
case "pixeldrain98_dark":
|
||||
def = pixeldrain98StyleDark
|
||||
}
|
||||
|
||||
if hue >= 0 && hue <= 360 {
|
||||
@@ -223,7 +223,6 @@ func (s styleSheet) String() string {
|
||||
--background_color: %s;
|
||||
--background: %s;
|
||||
--background_text_color: %s;
|
||||
--background_pattern: url("%s");
|
||||
--background_pattern_color: %s;
|
||||
--navigation_background: %s;
|
||||
--body_color: %s;
|
||||
@@ -257,14 +256,13 @@ func (s styleSheet) String() string {
|
||||
s.BackgroundColor.CSS(),
|
||||
s.Background.CSS(),
|
||||
s.BackgroundText.CSS(),
|
||||
BackgroundTiles(),
|
||||
s.BackgroundPattern.CSS(),
|
||||
s.Navigation.CSS(),
|
||||
s.BodyColor.CSS(),
|
||||
s.BodyBackground.CSS(),
|
||||
s.BodyText.CSS(),
|
||||
s.Separator.CSS(),
|
||||
s.BodyColor.WithAlpha(0.75).CSS(), // shaded_background
|
||||
s.BodyColor.WithAlpha(0.7).CSS(), // shaded_background
|
||||
s.CardColor.CSS(),
|
||||
s.Chart1.CSS(),
|
||||
s.Chart2.CSS(),
|
||||
@@ -286,31 +284,6 @@ func (dark styleSheet) withLight(light styleSheet) string {
|
||||
)
|
||||
}
|
||||
|
||||
func BackgroundTiles() template.URL {
|
||||
var (
|
||||
now = time.Now()
|
||||
month = now.Month()
|
||||
day = now.Day()
|
||||
file string
|
||||
)
|
||||
|
||||
if now.Weekday() == time.Wednesday && rand.Intn(20) == 0 {
|
||||
file = "checker_wednesday"
|
||||
} else if month == time.August && day == 8 {
|
||||
file = "checker_dwarf"
|
||||
} else if month == time.August && day == 24 {
|
||||
file = "checker_developers"
|
||||
} else if month == time.October && day == 31 {
|
||||
file = "checker_halloween"
|
||||
} else if month == time.December && (day == 25 || day == 26 || day == 27) {
|
||||
file = "checker_christmas"
|
||||
} else {
|
||||
file = fmt.Sprintf("checker%d", now.UnixNano()%20)
|
||||
}
|
||||
|
||||
return template.URL("/res/img/background_patterns/" + file + "_transparent.png")
|
||||
}
|
||||
|
||||
// Following are all the available styles
|
||||
|
||||
var purpleDrainStyle = styleSheet{
|
||||
@@ -638,3 +611,106 @@ var pixeldrain98Style = styleSheet{
|
||||
|
||||
StyleOverrides: override98,
|
||||
}
|
||||
|
||||
var pixeldrain98StyleDark = styleSheet{
|
||||
Input: HSL{0, 0, .25},
|
||||
InputHover: HSL{0, 0, .30},
|
||||
InputText: RGB{255, 255, 255},
|
||||
InputDisabledText: RGB{128, 128, 128},
|
||||
Highlight: HSL{240, 1, .7},
|
||||
HighlightText: HSL{0, 1, 1},
|
||||
Danger: HSL{1, .71, .7},
|
||||
Link: HSL{240, 1, .8},
|
||||
|
||||
BackgroundColor: HSL{180, 1, .08},
|
||||
BackgroundText: HSL{0, 1, 1},
|
||||
BodyColor: HSL{0, 0, .25},
|
||||
BodyText: HSL{0, 1, 1},
|
||||
Separator: HSL{0, 0, .33},
|
||||
CardColor: HSL{0, 0, .25},
|
||||
|
||||
StyleOverrides: `
|
||||
:root {
|
||||
--border_98: inset -1px -1px #222,
|
||||
inset 1px 1px #666,
|
||||
inset -2px -2px #333,
|
||||
inset 2px 2px #555;
|
||||
--inset_98: inset -1px -1px #666,
|
||||
inset 1px 1px #111,
|
||||
inset -2px -2px #555,
|
||||
inset 2px 2px #333;
|
||||
}
|
||||
|
||||
button, .button,
|
||||
dialog,
|
||||
fieldset,
|
||||
.highlight_border,
|
||||
.page_content,
|
||||
footer, .footer_content,
|
||||
.card,
|
||||
.window,
|
||||
.block,
|
||||
.sharebar,
|
||||
.directory_sorters, .directory_area,
|
||||
.container > .directory,
|
||||
.file_preview > .directory,
|
||||
.directory > .node,
|
||||
.file, .file_button,
|
||||
.upload_task,
|
||||
.add_button,
|
||||
.expandable,
|
||||
.upload_widget,
|
||||
.highlight_shaded {
|
||||
border: none !important;
|
||||
border-radius: 0 !important;
|
||||
box-shadow: var(--border_98) !important;
|
||||
}
|
||||
legend {
|
||||
background-color: var(--body_color);
|
||||
border: none !important;
|
||||
}
|
||||
.window, .page_content, .file_button, .expandable, pre {
|
||||
padding: 3px !important;
|
||||
}
|
||||
.window > .header,
|
||||
.headerbar,
|
||||
.upload_widget > .header {
|
||||
background: linear-gradient(90deg, #003d66, #005c99) !important;
|
||||
color: #fff !important;
|
||||
}
|
||||
.tab_bar > button, .tab_bar > .button {
|
||||
border-top-left-radius: 3px !important;
|
||||
border-top-right-radius: 3px !important;
|
||||
box-shadow: var(--border_98) !important;
|
||||
}
|
||||
.directory > tr {
|
||||
border: none !important;
|
||||
}
|
||||
.button_toggle_navigation {
|
||||
padding: 8px !important;
|
||||
}
|
||||
|
||||
input[type="email"],
|
||||
input[type="number"],
|
||||
input[type="password"],
|
||||
input[type="text"],
|
||||
input[type="date"],
|
||||
select, textarea, pre {
|
||||
border-radius: 0 !important;
|
||||
border: none !important;
|
||||
box-shadow: var(--inset_98) !important;
|
||||
}
|
||||
code {
|
||||
border-radius: 0 !important;
|
||||
}
|
||||
|
||||
.file_preview,
|
||||
hr,
|
||||
.toolbar > .separator,
|
||||
.toolbar > .grid > .separator {
|
||||
border-radius: 0 !important;
|
||||
border: none !important;
|
||||
box-shadow: var(--inset_98) !important;
|
||||
}
|
||||
`,
|
||||
}
|
||||
|
@@ -117,7 +117,10 @@ func New(r *httprouter.Router, prefix string, conf Config) (wc *WebController) {
|
||||
r.Handle("DELETE", "/api/*p", proxyHandler)
|
||||
}
|
||||
|
||||
r.NotFound = http.HandlerFunc(wc.serveNotFound)
|
||||
r.NotFound = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
log.Info("running wrap handler")
|
||||
wc.serveTemplate("wrap", handlerOpts{})(w, r, nil)
|
||||
})
|
||||
|
||||
// Request method shorthands. These help keep the array of handlers aligned
|
||||
const PST, GET = "POST", "GET"
|
||||
@@ -128,14 +131,10 @@ func New(r *httprouter.Router, prefix string, conf Config) (wc *WebController) {
|
||||
path string // The URL path this API will be registered on
|
||||
handler httprouter.Handle // The function to run when this API is called
|
||||
}{
|
||||
// General navigation
|
||||
{GET, "" /* */, wc.serveLandingPage()},
|
||||
{GET, "home" /* */, wc.serveTemplate("home", handlerOpts{})},
|
||||
{GET, "api" /* */, wc.serveMarkdown("api.md", handlerOpts{})},
|
||||
{GET, "d/*path" /* */, wc.serveDirectory},
|
||||
{GET, "widgets" /* */, wc.serveTemplate("widgets", handlerOpts{})},
|
||||
{GET, "about" /* */, wc.serveMarkdown("about.md", handlerOpts{})},
|
||||
{GET, "appearance" /* */, wc.serveTemplate("appearance", handlerOpts{})},
|
||||
{GET, "hosting" /* */, wc.serveMarkdown("hosting.md", handlerOpts{})},
|
||||
{GET, "acknowledgements" /**/, wc.serveMarkdown("acknowledgements.md", handlerOpts{})},
|
||||
{GET, "business" /* */, wc.serveMarkdown("business.md", handlerOpts{})},
|
||||
@@ -144,23 +143,7 @@ func New(r *httprouter.Router, prefix string, conf Config) (wc *WebController) {
|
||||
{GET, "filesystem" /* */, wc.serveMarkdown("filesystem.md", handlerOpts{})},
|
||||
{GET, "100_gigabit_ethernet", wc.serveMarkdown("100_gigabit_ethernet.md", handlerOpts{NoExec: true})},
|
||||
{GET, "apps" /* */, wc.serveTemplate("apps", handlerOpts{})},
|
||||
{GET, "speedtest" /* */, wc.serveTemplate("speedtest", handlerOpts{})},
|
||||
{GET, "status" /* */, wc.serveTemplate("status", handlerOpts{})},
|
||||
|
||||
// User account pages
|
||||
{GET, "login" /* */, wc.serveTemplate("login", handlerOpts{NoEmbed: true})},
|
||||
{GET, "register" /* */, wc.serveTemplate("login", handlerOpts{NoEmbed: true})},
|
||||
{GET, "logout" /* */, wc.serveTemplate("logout", handlerOpts{Auth: true, NoEmbed: true})},
|
||||
{PST, "logout" /* */, wc.serveLogout},
|
||||
|
||||
// User account settings
|
||||
{GET, "user/*p", wc.serveTemplate("user_home", handlerOpts{Auth: true, NoEmbed: true})},
|
||||
|
||||
// Admin settings
|
||||
{GET, "admin", wc.serveTemplate("admin", handlerOpts{Auth: true})},
|
||||
{GET, "admin/*p", wc.serveTemplate("admin", handlerOpts{Auth: true})},
|
||||
|
||||
// Misc
|
||||
{GET, "theme.css", wc.themeHandler},
|
||||
} {
|
||||
r.Handle(h.method, prefix+"/"+h.path, middleware(h.handler))
|
||||
@@ -198,24 +181,8 @@ type handlerOpts struct {
|
||||
NoExec bool
|
||||
}
|
||||
|
||||
func (wc *WebController) serveLandingPage() httprouter.Handle {
|
||||
return func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
|
||||
var td = wc.newTemplateData(w, r)
|
||||
var template = "home"
|
||||
|
||||
// If the user is logged in, run user home template
|
||||
if td.Authenticated {
|
||||
template = "user_home"
|
||||
}
|
||||
|
||||
if err := wc.templates.Run(w, r, template, td); err != nil && !util.IsNetError(err) {
|
||||
log.Error("Error executing template '%s': %s", template, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (wc *WebController) serveTemplate(tpl string, opts handlerOpts) httprouter.Handle {
|
||||
return func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
|
||||
return func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
||||
if opts.NoEmbed {
|
||||
w.Header().Set("X-Frame-Options", "DENY")
|
||||
}
|
||||
@@ -314,22 +281,6 @@ func (wc *WebController) serveFile(path string) httprouter.Handle {
|
||||
}
|
||||
}
|
||||
|
||||
func (wc *WebController) serveForbidden(w http.ResponseWriter, r *http.Request) {
|
||||
log.Debug("Forbidden: %s", r.URL)
|
||||
w.WriteHeader(http.StatusForbidden)
|
||||
wc.templates.Run(w, r, "403", wc.newTemplateData(w, r))
|
||||
}
|
||||
|
||||
func (wc *WebController) serveNotFound(w http.ResponseWriter, r *http.Request) {
|
||||
log.Debug("Not Found: %s", r.URL)
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
wc.templates.Run(w, r, "404", wc.newTemplateData(w, r))
|
||||
}
|
||||
func (wc *WebController) serveUnavailableForLegalReasons(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusUnavailableForLegalReasons)
|
||||
wc.templates.Run(w, r, "451", wc.newTemplateData(w, r))
|
||||
}
|
||||
|
||||
func (wc *WebController) getAPIKey(r *http.Request) (key string, err error) {
|
||||
if cookie, err := r.Cookie("pd_auth_key"); err == nil {
|
||||
if len(cookie.Value) == 36 {
|
||||
|
Reference in New Issue
Block a user