move assets to server package

This commit is contained in:
sentriz
2020-03-22 01:11:48 +00:00
parent 4e3a0db739
commit 52d2dbcce9
20 changed files with 21 additions and 20 deletions

13
server/assets/assets.go Normal file
View File

@@ -0,0 +1,13 @@
package assets
import "strings"
// PrefixDo runs a given callback for every path in our assets with
// the given prefix
func PrefixDo(pre string, cb func(path string, asset *EmbeddedAsset)) {
for path, asset := range Bytes {
if strings.HasPrefix(path, pre) {
cb(path, asset)
}
}
}

10981
server/assets/assets_gen.go Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,31 @@
{{ define "layout" }}
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>gonic</title>
{{ template "head" }}
</head>
<body>
<div id="content">
<div id="header">
<a href="{{ path "/admin/home" }}">
<img src="{{ path "/admin/static/gonic.png" }}">
</a>
</div>
{{ range $flash := .Flashes }}
<div class="padded flash-{{ $flash.Type }}">
<i class="mdi mdi-alert-circle"></i> {{ $flash.Message }}
</div>
{{ end }}
{{ template "content" . }}
<div class="side-padded text-right">
<span class="light">{{ .Version }}</span>
senan kelly, 2020
<span class="light">&#124;</span>
<a href="https://senan.xyz/g/gonic">github</a>
</div>
</div>
</body>
</html>
{{ end }}

View File

@@ -0,0 +1,10 @@
{{ define "content" }}
<div class="side-padded light text-right">
welcome {{ .User.Name }}
&#124;
<a href="{{ path "/admin/home" }}">home</a>
&#124;
<a href="{{ path "/admin/logout" }}">logout <i class="mdi mdi-logout-variant"></i></a>
</div>
{{ template "user" . }}
{{ end }}

View File

@@ -0,0 +1,12 @@
{{ define "user" }}
<div class="padded box">
<div class="box-title">
<i class="mdi mdi-account-key"></i> changing account password
</div>
<form class="block" action="{{ path "/admin/change_own_password_do" }}" method="post">
<input type="password" id="password_one" name="password_one" placeholder="new password">
<input type="password" id="password_two" name="password_two" placeholder="verify new password">
<input type="submit" value="change">
</form>
</div>
{{ end }}

View File

@@ -0,0 +1,12 @@
{{ define "user" }}
<div class="padded box">
<div class="box-title">
<i class="mdi mdi-account-key"></i> changing {{ .SelectedUser.Name }}'s password
</div>
<form class="block" action="{{ printf "/admin/change_password_do?user=%s" .SelectedUser.Name | path }}" method="post">
<input type="password" id="password_one" name="password_one" placeholder="new password">
<input type="password" id="password_two" name="password_two" placeholder="verify new password">
<input type="submit" value="change">
</form>
</div>
{{ end }}

View File

@@ -0,0 +1,13 @@
{{ define "user" }}
<div class="padded box">
<div class="box-title">
<i class="mdi mdi-account-plus"></i> creating new user
</div>
<form class="block" action="{{ path "/admin/create_user_do" }}" method="post">
<input type="text" id="username" name="username" placeholder="username">
<input type="password" id="password_one" name="password_one" placeholder="password">
<input type="password" id="password_two" name="password_two" placeholder="verify password">
<input type="submit" value="create">
</form>
</div>
{{ end }}

View File

@@ -0,0 +1,14 @@
{{ define "user" }}
<div class="padded box">
<div class="box-title">
<i class="mdi mdi-account-remove"></i> deleting user {{ .SelectedUser.Name }}
</div>
<div class="text-right">
are you sure?<br/>
<span class="light">their plays, starred, etc. will also be deleted</span>
</div>
<form class="block" action="{{ printf "/admin/delete_user_do?user=%s" .SelectedUser.Name | path }}" method="post">
<input type="submit" value="yes">
</form>
</div>
{{ end }}

View File

@@ -0,0 +1,173 @@
{{ define "user" }}
<div class="padded box">
<div class="box-title">
<i class="mdi mdi-chart-arc"></i> stats
</div>
<div class="block-right">
<table id="stats" class="text-right">
<tr>
<td>artists:</td> <td>{{ .ArtistCount }}</td>
</tr>
<tr>
<td>albums:</td> <td>{{ .AlbumCount }}</td>
</tr>
<tr>
<td>tracks:</td> <td>{{ .TrackCount }}</td>
</tr>
</table>
</div>
</div>
<div class="padded box">
<div class="box-title">
<i class="mdi mdi-lastfm"></i> last.fm
</div>
<div class="text-right">
{{ if .CurrentLastFMAPIKey }}
<span class="light">current status</span>
{{ if .User.LastFMSession }}
linked
<span class="light">&#124;</span>
<form action="{{ path "/admin/unlink_lastfm_do" }}" method="post">
<input type="submit" value="unlink">
</form>
{{ else }}
<span class="angry">unlinked</span>
{{ $cbPath := path "/admin/link_lastfm_do" }}
{{ $cbURL := printf "%s%s" .RequestRoot $cbPath }}
<a href="https://www.last.fm/api/auth/?api_key={{ .CurrentLastFMAPIKey }}&cb={{ $cbURL }}">link&#8230;</a>
{{ end }}
{{ else }}
<p class="light">api key not set</p>
{{ if not .User.IsAdmin }}
<p class="light">please ask your admin to set it</p>
{{ end }}
{{ end }}
{{ if .User.IsAdmin }}
<p><a href="{{ path "/admin/update_lastfm_api_key" }}">update api key&#8230;</a></p>
{{ end }}
</div>
</div>
<div class="padded box">
{{ if .User.IsAdmin }}
{{/* admin panel to manage all users */}}
<div class="box-title">
<i class="mdi mdi-account-multiple"></i> users
</div>
<div class="text-right">
{{ range $user := .AllUsers }}
<i>{{ $user.Name }}</i>
<span class="light no-small">{{ $user.CreatedAt | date }}</span>
<span class="light">&#124;</span>
<a href="{{ printf "/admin/change_password?user=%s" $user.Name | path }}">change password&#8230;</a>
<span class="light">&#124;</span>
{{ if $user.IsAdmin }}
<span class="light">delete&#8230;</span>
{{ else }}
<a href="{{ printf "/admin/delete_user?user=%s" $user.Name | path }}">delete&#8230;</a>
{{ end }}
<br/>
{{ end }}
<a href="{{ path "/admin/create_user" }}" class="button">create new&#8230;</a>
</div>
{{ else }}
{{/* user panel to manage themselves */}}
<div class="box-title">
<i class="mdi mdi-account"></i> your account
</div>
<div class="text-right">
<a href="{{ path "/admin/change_own_password" }}" class="button">change password&#8230;</a>
</div>
{{ end }}
</div>
<div class="padded box">
<div class="box-title">
<i class="mdi mdi-folder-multiple"></i> recent folders
</div>
<div class="block-right text-right">
{{ if eq (len .RecentFolders) 0 }}
<span class="light">no folders yet</span>
{{ end }}
<table id="recent-folders">
{{ range $folder := .RecentFolders }}
<tr>
<td class="text-right">{{ $folder.RightPath }}</td>
<td class="no-small"><span class="light" title="{{ $folder.ModifiedAt }}">{{ $folder.ModifiedAt | dateHuman }}</span></td>
</tr>
{{ end }}
</table>
{{- if and (not .IsScanning) (.User.IsAdmin) -}}
{{- if not .LastScanTime.IsZero -}}
<p class="light" title="{{ .LastScanTime }}">scanned {{ .LastScanTime | dateHuman }}</p>
{{ end }}
<form action="{{ path "/admin/start_scan_do" }}" method="post">
<td><input type="submit" value="start scan"></td>
</form>
{{ end }}
</div>
</div>
<div class="padded box">
<div class="box-title">
<i class="mdi mdi-file-music"></i> transcoding device profiles
</div>
<div class="block-right">
<p class="light text-right">you can find your device's client name in the gonic logs</p>
<p class="light text-right">some common client names: "<span class="emp">DSub</span>", "<span class="emp">Jamstash</span>", "<span class="emp">Soundwaves</span>"</p>
<p class="light text-right">or use "*" as fallback rule for any client</p>
<table id="transcode-preferences">
{{ range $pref := .TranscodePreferences }}
<tr>
<form id="transcode-pref-{{ $pref.Client }}" action="{{ printf "/admin/delete_transcode_pref_do?client=%s" $pref.Client | path }}" method="post"></form>
<td>{{ $pref.Client }}</td>
<td>{{ $pref.Profile }}</td>
<td><input form="transcode-pref-{{ $pref.Client }}" type="submit" value="delete"></td>
</tr>
{{ end }}
<tr>
<form id="transcode-pref-add" action="{{ path "/admin/create_transcode_pref_do" }}" method="post"></form>
<td><input form="transcode-pref-add" type="text" name="client" placeholder="client name"></td>
<td><select form="transcode-pref-add" name="profile">
{{ range $profile := .TranscodeProfiles }}
<option value="{{ $profile }}">{{ $profile }}</option>
{{ end }}
</select></td>
<td><input form="transcode-pref-add" type="submit" value="save"></td>
</tr>
</table>
</div>
</div>
<div class="padded box">
<div class="box-title">
<i class="mdi mdi-playlist-music"></i> playlists
</div>
<div class="block-right text-right">
{{ if eq (len .Playlists) 0 }}
<span class="light">no playlists yet</span>
{{ end }}
<table id="recent-playlists">
{{ range $playlist := .Playlists }}
<tr>
<td class="text-right">{{ $playlist.Name }}</td>
<td><span class="light">({{ $playlist.TrackCount }} tracks)</span></td>
<td class="no-small"><span class="light" title="{{ $playlist.CreatedAt }}">{{ $playlist.CreatedAt | dateHuman }}</span></td>
</tr>
{{ end }}
</table>
<form
id="playlist-upload-form"
enctype="multipart/form-data"
action="{{ path "/admin/upload_playlist_do" }}"
method="post"
>
<div style="position: relative;">
<input id="playlist-upload-input" style="position: absolute; opacity: 0;" name="playlist-files" type="file" multiple />
<input type="button" value="upload m3u8">
</div>
</form>
<script>
document.getElementById("playlist-upload-input").onchange = (e) => {
document.getElementById("playlist-upload-form").submit();
}
</script>
</div>
</div>
{{ end }}

View File

@@ -0,0 +1,12 @@
{{ define "content" }}
<div class="padded box">
<div class="box-title">
<i class="mdi mdi-login-variant"></i> login
</div>
<form class="block" action="{{ path "/admin/login_do" }}" method="post">
<input type="text" id="username" name="username" placeholder="username">
<input type="password" id="password" name="password" placeholder="password">
<input type="submit" value="login">
</form>
</div>
{{ end }}

View File

@@ -0,0 +1,7 @@
{{ define "content" }}
<div class="padded">
<div class="text-right">
page not found
</div>
</div>
{{ end }}

View File

@@ -0,0 +1,18 @@
{{ define "user" }}
<div class="padded box">
<div class="box-title">
<i class="mdi mdi-key-change"></i> updating last.fm keys
</div>
<div class="text-right">
<p class="light">(you can get an api key <a href="https://www.last.fm/api/account/create" target="_blank">here</a>)</p>
<br/>
<p><span class="light">current key</span> <i>{{ default "not set" .CurrentLastFMAPIKey }}</i></p>
<p><span class="light">current secret</span> <i>{{ default "not set" .CurrentLastFMAPISecret }}</i></p>
</div>
<form class="block" action="{{ path "/admin/update_lastfm_api_key_do" }}" method="post">
<input type="text" id="api_key" name="api_key" placeholder="new key">
<input type="text" id="secret" name="secret" placeholder="new secret">
<input type="submit" value="update">
</form>
</div>
{{ end }}

View File

@@ -0,0 +1,8 @@
{{ define "head" }}
<link rel="stylesheet" href="{{ path "/admin/static/reset.css" }}">
<link rel="stylesheet" href="https://cdn.materialdesignicons.com/3.6.95/css/materialdesignicons.min.css">
<link rel="stylesheet" href="{{ path "/admin/static/main.css" | noCache }}">
<link rel="shortcut icon" href="{{ path "/admin/static/favicon.ico" }}" type="image/x-icon">
<link rel="icon" href="{{ path "/admin/static/favicon.ico" }}" type="image/x-icon">
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
{{ end }}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 236 KiB

View File

@@ -0,0 +1,153 @@
:root {
--size: 13px;
}
@media only screen and (max-width: 780px) {
:root {
--size: 11px;
}
}
*,
span,
div,
i,
input,
body,
html {
font-family: monospace;
font-size: var(--size);
}
body {
max-width: 780px;
margin: 0 auto;
overflow-y: scroll;
}
input[type],
select,
textarea {
border-radius: 0;
border: 1px solid #ccc;
box-sizing: border-box;
margin: 1px 0;
padding: 0;
height: calc(var(--size) * 1.5);
vertical-align: middle;
}
input[type] {
width: calc(var(--size) * 8);
background-color: white;
cursor: pointer;
}
input[type=text],
input[type=password] {
width: 100%;
}
form {
display: inline;
}
form.block {
max-width: 400px;
margin-left: auto;
margin-right: 0;
display: flex;
flex-direction: column;
align-items: flex-end;
text-align: right;
}
form > * {
width: 100%;
}
table {
overflow: hidden;
white-space: nowrap;
}
table td {
padding-left: calc(var(--size) * 0.5);
}
a,
a:visited {
color: #0064c1;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
#content > * {
margin: calc(var(--size) * 1.5);
}
#header {
border-bottom: 2px solid #0000001a;
}
#header img {
width: 60%;
display: block;
margin: 0 auto;
height: auto;
}
.flash-warning {
background-color: #fd1b1b1c;
border-right: 2px solid #fd1b1b1c;
border-bottom: 2px solid #fd1b1b1c;
}
.flash-normal {
background-color: #15ff5424;
border-right: 2px solid #15ff5424;
border-bottom: 2px solid #15ff5424;
}
.box {
background-color: #00000005;
border-right: 2px solid #0000000c;
border-bottom: 2px solid #0000000c;
}
@media only screen and (max-width: 780px) {
.no-small {
display: none;
}
}
.text-right {
text-align: right;
}
.block-right > * {
margin-left: auto;
}
.padded {
padding: var(--size);
}
.side-padded {
padding: 0 var(--size);
}
.angry {
background-color: #f4433669;
}
.light {
color: #00000082;
}
.emp {
font-style: italic;
}

View File

@@ -0,0 +1,135 @@
/* http://meyerweb.com/eric/tools/css/reset/
v2.0 | 20110126
License: none (public domain)
*/
html,
body,
div,
span,
applet,
object,
iframe,
h1,
h2,
h3,
h4,
h5,
h6,
p,
blockquote,
pre,
a,
abbr,
acronym,
address,
big,
cite,
code,
del,
dfn,
em,
img,
ins,
kbd,
q,
s,
samp,
small,
strike,
strong,
sub,
sup,
tt,
var,
b,
u,
i,
center,
dl,
dt,
dd,
ol,
ul,
li,
fieldset,
form,
label,
legend,
table,
caption,
tbody,
tfoot,
thead,
tr,
th,
td,
article,
aside,
canvas,
details,
embed,
figure,
figcaption,
footer,
header,
hgroup,
menu,
nav,
output,
ruby,
section,
summary,
time,
mark,
audio,
video {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
}
/* html5 display-role reset for older browsers */
article,
aside,
details,
figcaption,
figure,
footer,
header,
hgroup,
menu,
nav,
section {
display: block;
}
body {
line-height: 1;
}
ol,
ul {
list-style: none;
}
blockquote,
q {
quotes: none;
}
blockquote:before,
blockquote:after,
q:before,
q:after {
content: "";
content: none;
}
table {
border-collapse: collapse;
border-spacing: 0;
}

View File

@@ -18,8 +18,8 @@ import (
"github.com/oxtoacart/bpool"
"github.com/wader/gormstore"
"senan.xyz/g/gonic/assets"
"senan.xyz/g/gonic/db"
"senan.xyz/g/gonic/server/assets"
"senan.xyz/g/gonic/server/ctrlbase"
"senan.xyz/g/gonic/version"
)

View File

@@ -10,9 +10,9 @@ import (
"github.com/gorilla/mux"
"senan.xyz/g/gonic/assets"
"senan.xyz/g/gonic/db"
"senan.xyz/g/gonic/scanner"
"senan.xyz/g/gonic/server/assets"
"senan.xyz/g/gonic/server/ctrladmin"
"senan.xyz/g/gonic/server/ctrlbase"
"senan.xyz/g/gonic/server/ctrlsubsonic"