mirror of
https://github.com/gmemstr/sliproad.git
synced 2024-09-20 00:21:15 +01:00
Implement new frontend, "/" at end of provider.
Started work on a new basic frontend, with some magic code from @tomhodgins (Tom Hodgins) for templating and processing data, which was the primary purpose for considering a full-fledged JavaScript framework. Fairly simple right now, with minimal "bling", and seems "functional enough". Might need to consider options for using less or no JS down the line if there is demand. As part of this frontend, actually implemented route logic for fetching a sorted list of providers (might be worth investigating whether storing this final result in memory is worth the performance to memory trade-off). Also fixed a bug where adding "/" to the end of a provider name without a file path would result in a 404. This was addressed with some Regex filtering on the path that should be able to handle that matching.
This commit is contained in:
parent
49dba732d3
commit
292e24978d
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -22,4 +22,3 @@ nas
|
|||
|
||||
*.db
|
||||
.lock
|
||||
assets/web/*
|
48
assets/web/css/styles.css
Normal file
48
assets/web/css/styles.css
Normal file
|
@ -0,0 +1,48 @@
|
|||
* {
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
body {
|
||||
|
||||
}
|
||||
|
||||
.grid-lg, .grid-sm {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(5, 1fr);
|
||||
grid-template-rows: repeat(5, 2fr);
|
||||
grid-column-gap: 5px;
|
||||
grid-row-gap: 5px;
|
||||
}
|
||||
|
||||
.grid-lg a {
|
||||
display: flex;
|
||||
padding: 10vh;
|
||||
justify-content: center;
|
||||
background-color: black;
|
||||
font-size: 32px;
|
||||
font-weight: bold;
|
||||
text-decoration: none;
|
||||
transition: background-color 0.5s;
|
||||
}
|
||||
|
||||
.grid-sm a {
|
||||
display: flex;
|
||||
padding: 2vh;
|
||||
justify-content: center;
|
||||
background-color: black;
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
text-decoration: none;
|
||||
transition: background-color 0.5s;
|
||||
}
|
||||
|
||||
.grid-lg a:visited, .grid-lg a,
|
||||
.grid-sm a:visited, .grid-sm a {
|
||||
color: white;
|
||||
}
|
||||
.grid-lg a:hover,
|
||||
.grid-sm a:hover {
|
||||
color: white;
|
||||
background-color: darkgray;
|
||||
transition: background-color 0.5s;
|
||||
}
|
19
assets/web/index.html
Normal file
19
assets/web/index.html
Normal file
|
@ -0,0 +1,19 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport"
|
||||
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
|
||||
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
||||
<title>NAS</title>
|
||||
<link rel="stylesheet" href="/css/styles.css">
|
||||
</head>
|
||||
<body>
|
||||
<h1>NAS</h1>
|
||||
|
||||
<main id="main">
|
||||
</main>
|
||||
|
||||
<script src="/javascript/app.js"></script>
|
||||
</body>
|
||||
</html>
|
80
assets/web/javascript/app.js
Normal file
80
assets/web/javascript/app.js
Normal file
|
@ -0,0 +1,80 @@
|
|||
// Register our router, and fire it off initially in case user is being linked a dir.
|
||||
window.addEventListener("hashchange", router, false);
|
||||
router()
|
||||
|
||||
function getFileListing(provider, path = "") {
|
||||
fetch(`/api/files/${provider}${path}`)
|
||||
.then((response) => {
|
||||
return response.json()
|
||||
})
|
||||
.then((data) => {
|
||||
let files = data["Files"]
|
||||
html`
|
||||
<div class="grid-sm">
|
||||
${files.map(file =>
|
||||
`<a href="${!file.IsDirectory ? `/api/files/${provider}${path}/${file.Name}` : `#${provider + "/" + file.Name}`}">
|
||||
${file.Name}${file.IsDirectory ? '/' : ''}
|
||||
</a>
|
||||
`
|
||||
).join('')}
|
||||
</div>
|
||||
`
|
||||
})
|
||||
}
|
||||
|
||||
function getProviders() {
|
||||
fetch(`/api/providers`)
|
||||
.then((response) => {
|
||||
return response.json()
|
||||
})
|
||||
.then((data) => {
|
||||
let providers = data
|
||||
html`
|
||||
<div class="grid-lg">
|
||||
${providers.map(provider =>
|
||||
`<a href=#${provider}>
|
||||
${provider}
|
||||
</a>
|
||||
`
|
||||
).join('')}
|
||||
</div>
|
||||
`
|
||||
})
|
||||
}
|
||||
|
||||
function router(event = null) {
|
||||
let hash = location.hash.replace("#", "")
|
||||
// If hash is empty, "redirect" to index.
|
||||
if (hash === "") {
|
||||
getProviders()
|
||||
return
|
||||
}
|
||||
|
||||
let path = hash.split("/")
|
||||
let provider = path.shift()
|
||||
console.log(path, provider)
|
||||
getFileListing(provider, "/" + path)
|
||||
}
|
||||
|
||||
// Tagged template function for parsing a string of text as HTML objects
|
||||
// <3 @innovati for this brilliance.
|
||||
function html(strings, ...things) {
|
||||
// Our "body", where we'll render stuff.
|
||||
const body = document.getElementById("main")
|
||||
let x = document.createRange().createContextualFragment(
|
||||
strings.reduce(
|
||||
(markup, string, index) => {
|
||||
markup += string
|
||||
|
||||
if (things[index]) {
|
||||
markup += things[index]
|
||||
}
|
||||
|
||||
return markup
|
||||
},
|
||||
''
|
||||
)
|
||||
)
|
||||
body.innerHTML = ""
|
||||
body.append(x)
|
||||
}
|
|
@ -6,6 +6,8 @@ import (
|
|||
"github.com/gmemstr/nas/files"
|
||||
"github.com/gorilla/mux"
|
||||
"net/http"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func HandleProvider() common.Handler {
|
||||
|
@ -14,6 +16,7 @@ func HandleProvider() common.Handler {
|
|||
vars := mux.Vars(r)
|
||||
if r.Method == "GET" {
|
||||
providerCodename := vars["provider"]
|
||||
providerCodename = strings.Replace(providerCodename, "/", "", -1)
|
||||
provider := *files.Providers[providerCodename]
|
||||
|
||||
fileList := provider.GetDirectory("")
|
||||
|
@ -44,6 +47,16 @@ func HandleProvider() common.Handler {
|
|||
func ListProviders() common.Handler {
|
||||
|
||||
return func(rc *common.RouterContext, w http.ResponseWriter, r *http.Request) *common.HTTPError {
|
||||
var providers []string
|
||||
for v, _ := range files.ProviderConfig {
|
||||
providers = append(providers, v)
|
||||
}
|
||||
sort.Strings(providers)
|
||||
data, err := json.Marshal(providers)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
w.Write(data)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,11 +35,12 @@ func Init() *mux.Router {
|
|||
r := mux.NewRouter()
|
||||
|
||||
// "Static" paths
|
||||
r.PathPrefix("/static/").Handler(http.StripPrefix("/static/", http.FileServer(http.Dir("assets/web/static"))))
|
||||
r.PathPrefix("/javascript/").Handler(http.StripPrefix("/javascript/", http.FileServer(http.Dir("assets/web/javascript"))))
|
||||
r.PathPrefix("/css/").Handler(http.StripPrefix("/css/", http.FileServer(http.Dir("assets/web/css"))))
|
||||
|
||||
// Paths that require specific handlers
|
||||
r.Handle("/", Handle(
|
||||
auth.RequireAuthorization(1),
|
||||
//auth.RequireAuthorization(1),
|
||||
rootHandler(),
|
||||
)).Methods("GET")
|
||||
|
||||
|
@ -48,11 +49,11 @@ func Init() *mux.Router {
|
|||
)).Methods("POST", "GET")
|
||||
|
||||
r.Handle("/api/providers", Handle(
|
||||
auth.RequireAuthorization(1),
|
||||
//auth.RequireAuthorization(1),
|
||||
ListProviders(),
|
||||
)).Methods("GET")
|
||||
|
||||
r.Handle(`/api/files/{provider}`, Handle(
|
||||
r.Handle(`/api/files/{provider:[a-zA-Z0-9]+\/*}`, Handle(
|
||||
//auth.RequireAuthorization(1),
|
||||
HandleProvider(),
|
||||
)).Methods("GET")
|
||||
|
|
Loading…
Reference in a new issue