go1.16 and embed
This commit is contained in:
parent
f0add04396
commit
8e7bcfc21b
37 changed files with 98 additions and 1134 deletions
|
|
@ -22,10 +22,7 @@ const (
|
|||
TagsPrefix = "/tags"
|
||||
DeletePrefix = "/delete"
|
||||
WebDavPrefix = "/webdav"
|
||||
|
||||
Favicon = "/favicon.ico"
|
||||
BootstrapCSS = "/bootstrap.css"
|
||||
CustomCSS = "/custom.css"
|
||||
StaticPrefix = "/static"
|
||||
|
||||
DataDir = "data"
|
||||
)
|
||||
|
|
|
|||
|
|
@ -37,9 +37,7 @@ var reserved = []string{
|
|||
core.MovePrefix,
|
||||
core.DeletePrefix,
|
||||
core.WebDavPrefix,
|
||||
core.Favicon,
|
||||
core.BootstrapCSS,
|
||||
core.CustomCSS,
|
||||
core.StaticPrefix,
|
||||
}
|
||||
|
||||
func checkPath(path string) error {
|
||||
|
|
|
|||
|
|
@ -97,24 +97,6 @@ func authHandler(h ctxHandler) ctxHandler {
|
|||
}
|
||||
}
|
||||
|
||||
func staticHandler(ctx *Context) {
|
||||
var err error
|
||||
ctx.SetHeader("Content-Type", "text/css; charset=utf-8")
|
||||
ctx.SetHeader("Expires", time.Now().UTC().Add(max).Format(http.TimeFormat))
|
||||
switch ctx.Path() {
|
||||
case core.BootstrapCSS:
|
||||
err = ctx.Write(ctx.Srv.res["bootstrap.css"])
|
||||
case core.CustomCSS:
|
||||
err = ctx.Write(ctx.Srv.res["custom.css"])
|
||||
case core.Favicon:
|
||||
ctx.SetHeader("Content-Type", "image/x-icon")
|
||||
err = ctx.Write(ctx.Srv.res["favicon.ico"])
|
||||
}
|
||||
if err != nil {
|
||||
log.Println("static:", err)
|
||||
}
|
||||
}
|
||||
|
||||
type registerNotFoundHandler struct {
|
||||
s *HTTPServer
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,31 +10,15 @@ type route struct {
|
|||
Methods []string
|
||||
}
|
||||
|
||||
var static = []route{
|
||||
var registerRoutes = []route{
|
||||
{
|
||||
core.Favicon,
|
||||
staticHandler,
|
||||
[]string{"GET"},
|
||||
},
|
||||
{
|
||||
core.BootstrapCSS,
|
||||
staticHandler,
|
||||
[]string{"GET"},
|
||||
},
|
||||
{
|
||||
core.CustomCSS,
|
||||
staticHandler,
|
||||
[]string{"GET"},
|
||||
core.IndexURI,
|
||||
jwtRegisterHandler(
|
||||
registerHandler),
|
||||
[]string{"GET", "POST"},
|
||||
},
|
||||
}
|
||||
|
||||
var registerRoutes = append(static, route{
|
||||
core.IndexURI,
|
||||
jwtRegisterHandler(
|
||||
registerHandler),
|
||||
[]string{"GET", "POST"},
|
||||
})
|
||||
|
||||
var prefixRoutes = []route{
|
||||
{
|
||||
core.RawPrefix,
|
||||
|
|
@ -94,7 +78,7 @@ var prefixRoutes = []route{
|
|||
},
|
||||
}
|
||||
|
||||
var routes = append(static, []route{
|
||||
var routes = []route{
|
||||
{
|
||||
core.SearchURI,
|
||||
jwtHandler(
|
||||
|
|
@ -177,4 +161,4 @@ var routes = append(static, []route{
|
|||
logoutHandler),
|
||||
[]string{"GET", "POST"},
|
||||
},
|
||||
}...)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ package server
|
|||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"embed"
|
||||
"errors"
|
||||
"git.giftfish.de/ston1th/authdav"
|
||||
"git.giftfish.de/ston1th/docstore/pkg/core"
|
||||
|
|
@ -100,12 +101,16 @@ func (s *HTTPServer) Stop() error {
|
|||
func (s *HTTPServer) register() http.Handler {
|
||||
r := mux.NewRouter()
|
||||
r.NotFoundHandler = ®isterNotFoundHandler{s}
|
||||
r.Handle("/static/{file}", http.StripPrefix("/", http.FileServer(http.FS(static))))
|
||||
for _, v := range registerRoutes {
|
||||
r.HandleFunc(v.Path, s.contextWrapper(v.Handler)).Methods(v.Methods...)
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
//go:embed static/*
|
||||
var static embed.FS
|
||||
|
||||
func (s *HTTPServer) buildRoutes() http.Handler {
|
||||
r := mux.NewRouter()
|
||||
r.NotFoundHandler = ¬FoundHandler{s}
|
||||
|
|
@ -115,6 +120,7 @@ func (s *HTTPServer) buildRoutes() http.Handler {
|
|||
h := authdav.NewWebdavBasicAuth(core.WebDavPrefix, fs, nil, webdavLogger, s.DB, "DocStore WebDav")
|
||||
r.PathPrefix(core.WebDavPrefix).Handler(h)
|
||||
}
|
||||
r.Handle("/static/{file}", http.StripPrefix("/", http.FileServer(http.FS(static))))
|
||||
for _, v := range routes {
|
||||
r.HandleFunc(v.Path, s.contextWrapper(v.Handler)).Methods(v.Methods...)
|
||||
}
|
||||
|
|
|
|||
12
pkg/server/static/bootstrap.css
vendored
Normal file
12
pkg/server/static/bootstrap.css
vendored
Normal file
File diff suppressed because one or more lines are too long
166
pkg/server/static/custom.css
Normal file
166
pkg/server/static/custom.css
Normal file
|
|
@ -0,0 +1,166 @@
|
|||
@media (min-width: 768px) {
|
||||
.sm-pull-right {
|
||||
float: right !important;
|
||||
}
|
||||
.sm-pull-left {
|
||||
float: left !important;
|
||||
}
|
||||
}
|
||||
@media (min-width: 992px) {
|
||||
.md-pull-right {
|
||||
float: right !important;
|
||||
}
|
||||
.md-pull-left {
|
||||
float: left !important;
|
||||
}
|
||||
}
|
||||
@media (min-width: 1200px) {
|
||||
.lg-pull-right {
|
||||
float: right !important;
|
||||
}
|
||||
.lg-pull-left {
|
||||
float: left !important;
|
||||
}
|
||||
}
|
||||
body {
|
||||
padding-top: 60px;
|
||||
}
|
||||
.msg {
|
||||
margin-top: 30px;
|
||||
}
|
||||
a.dark {
|
||||
color: #222222;
|
||||
}
|
||||
a.tag {
|
||||
text-decoration: none !important;
|
||||
}
|
||||
a.para {
|
||||
text-decoration: none;
|
||||
font-size: 18px;
|
||||
}
|
||||
a.anchor {
|
||||
display: block;
|
||||
position: relative;
|
||||
top: -70px;
|
||||
visibility: hidden;
|
||||
}
|
||||
.mono {
|
||||
font-family: monospace;
|
||||
}
|
||||
.alert-primary {
|
||||
background-color: #375a7f;
|
||||
border-color: #375a7f;
|
||||
color: #ffffff;
|
||||
}
|
||||
h1,h2,h3,h4,h5,h6 {
|
||||
font-weight: bold;
|
||||
padding-top: 60px !important;
|
||||
margin-top: -55px !important;
|
||||
-webkit-background-clip: content-box !important;
|
||||
background-clip: content-box !important;
|
||||
}
|
||||
h1 {
|
||||
font-size: 2em;
|
||||
}
|
||||
h2 {
|
||||
font-size: 1.75em;
|
||||
}
|
||||
h3 {
|
||||
font-size: 1.5em;
|
||||
}
|
||||
h4 {
|
||||
font-size: 1.25em;
|
||||
}
|
||||
h5 {
|
||||
font-size: 1em;
|
||||
}
|
||||
h6 {
|
||||
font-size: 1em;
|
||||
}
|
||||
ul.toc {
|
||||
list-style-type: disc;
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
pre {
|
||||
display: block;
|
||||
padding: 10px;
|
||||
margin: 0 0 10.5px;
|
||||
font-size: 14px;
|
||||
line-height: 1.42857143;
|
||||
word-break: break-all;
|
||||
word-wrap: break-word;
|
||||
color: #0cdba6;
|
||||
background-color: #444444;
|
||||
border: 1px solid #444444;
|
||||
border-radius: 2px;
|
||||
}
|
||||
pre.wrap {
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
code {
|
||||
padding: 3px 3px 1px 0px;
|
||||
font-size: 90%;
|
||||
color: #0cdba6;
|
||||
background-color: #444444;
|
||||
border-radius: 2px;
|
||||
}
|
||||
embed {
|
||||
background-color: #999999;
|
||||
width: 100%;
|
||||
height: 700px;
|
||||
}
|
||||
textarea,input,select {
|
||||
color: #e2e2e2 !important;
|
||||
background-color: #444444 !important;
|
||||
}
|
||||
select.sections {
|
||||
height: 120px !important;
|
||||
}
|
||||
input.menu {
|
||||
color: #e2e2e2 !important;
|
||||
background-color: #222222 !important;
|
||||
}
|
||||
.menu-search-bar {
|
||||
padding-top: 4px;
|
||||
}
|
||||
.menu-search-input {
|
||||
background-color: #2f2f2f !important;
|
||||
}
|
||||
.custom-file-label {
|
||||
background-color: #444 !important;
|
||||
}
|
||||
.custom-file-label::after {
|
||||
color: #fff;
|
||||
}
|
||||
html, body, .container, .content {
|
||||
height: 100% !important;
|
||||
}
|
||||
.container, .content {
|
||||
position: relative;
|
||||
}
|
||||
.proper-content {
|
||||
padding-top: 40px;
|
||||
}
|
||||
.section {
|
||||
margin-bottom: 20px;
|
||||
width: 250px;
|
||||
}
|
||||
.push {
|
||||
height: 20px;
|
||||
}
|
||||
.full-width {
|
||||
width: 100%;
|
||||
}
|
||||
.col-nopad {
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
}
|
||||
.relative {
|
||||
position: relative;
|
||||
}
|
||||
.btn-breadcrumb {
|
||||
position: absolute;
|
||||
right: 1rem;
|
||||
top: 38%;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
BIN
pkg/server/static/favicon.ico
Normal file
BIN
pkg/server/static/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.3 KiB |
File diff suppressed because one or more lines are too long
23
pkg/server/templates/delete.html
Normal file
23
pkg/server/templates/delete.html
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
{{define "body"}}
|
||||
<div class="row">
|
||||
<div class="col-xs-4 offset-4">
|
||||
<div class="card border-primary mx-auto">
|
||||
<div class="card-header">
|
||||
<strong>{{.BodyTitle}}</strong>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p>You are about to delete
|
||||
{{if eq .Data 1}}the directory{{end}}
|
||||
{{if eq .Data 2}}the file{{end}}
|
||||
<a href="{{.Path}}">{{.Path}}</a>.
|
||||
{{if eq .Data 1}}<br>This will also remove all files and directories below.</p>{{end}}
|
||||
<form class="form-horizontal" action="/delete{{.Path}}" method="post">
|
||||
<input type="hidden" name="token" value="{{.Token}}">
|
||||
<button class="btn btn-sm btn-danger" type="submit">Delete</button>
|
||||
<a href="{{.Path}}" class="btn btn-sm btn-primary">Back</a>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
77
pkg/server/templates/dir.html
Normal file
77
pkg/server/templates/dir.html
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
{{define "body"}}
|
||||
<div class="row">
|
||||
<div class="nav-container full-width relative">
|
||||
<ol class="breadcrumb full-width">
|
||||
<li class="breadcrumb-item"></li>
|
||||
<li class="breadcrumb-item"><a href="/">root</a></li>
|
||||
{{range $item := .Paths}}
|
||||
<li class="breadcrumb-item{{if $item.Flag}} active{{end}}">{{if $item.Flag}}{{$item.Name}}{{else}}<a href="{{$item.Abs}}">{{$item.Name}}</a>{{end}}</li>
|
||||
{{end}}
|
||||
</ol>
|
||||
<form action="/index/all" method="post">
|
||||
<input type="hidden" name="token" value="{{.Token}}">
|
||||
<div class="btn-group btn-breadcrumb">
|
||||
<a href="/upload{{.Path}}" class="btn btn-sm btn-success">Upload</a>
|
||||
<a href="/new{{.Path}}" class="btn btn-sm btn-primary">New Directory</a>
|
||||
{{$pl := len .Paths}}
|
||||
{{if eq $pl 0}}
|
||||
<a href="/retag" class="btn btn-sm btn-warning">Retag All</a>
|
||||
<button class="btn btn-sm btn-warning" type="submit">Index All</button>
|
||||
{{else}}
|
||||
<a href="/move{{.Path}}" class="btn btn-sm btn-primary">Move</a>
|
||||
<a href="/delete{{.Path}}" class="btn btn-sm btn-danger">Delete</a>
|
||||
{{end}}
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<table class="table table-stripped table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Path</th>
|
||||
<th>Type</th>
|
||||
<th>Tags</th>
|
||||
<th>Options</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{if .Data}}
|
||||
{{range $item := .Data.Dirs}}
|
||||
<tr>
|
||||
<th><a href="{{$item.Abs}}">{{$item.Name}}</a></th>
|
||||
<td>Directory</td>
|
||||
<td></td>
|
||||
<td><div class="btn-group">
|
||||
<a href="/move{{$item.Abs}}" class="btn btn-sm btn-primary">Move</a>
|
||||
<a href="/delete{{$item.Abs}}" class="btn btn-sm btn-danger">Delete</a>
|
||||
</div></td>
|
||||
</tr>
|
||||
{{end}}
|
||||
{{range $item := .Data.Files}}
|
||||
<tr>
|
||||
<th><a href="{{$item.Abs}}">{{$item.Name}}</a></th>
|
||||
<td>File</td>
|
||||
<td>
|
||||
{{range $t := $item.Tags}}
|
||||
<a href="/search?query=tags:{{$t}}" class="btn badge btn-primary">{{$t}}</a>
|
||||
{{end}}
|
||||
</td>
|
||||
<td><div class="btn-group">
|
||||
{{if $item.Scan}}
|
||||
<a href="#" class="btn btn-sm btn-warning">Scanning</a>
|
||||
{{else}}
|
||||
{{if not $item.Flag}}
|
||||
<a href="/index{{$item.Abs}}" class="btn btn-sm btn-success">Index</a>
|
||||
{{end}}
|
||||
{{end}}
|
||||
<a href="/move{{$item.Abs}}" class="btn btn-sm btn-primary">Move</a>
|
||||
<a href="/delete{{$item.Abs}}" class="btn btn-sm btn-danger">Delete</a>
|
||||
</div></td>
|
||||
</tr>
|
||||
{{end}}
|
||||
{{end}}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{{end}}
|
||||
12
pkg/server/templates/enoent.html
Normal file
12
pkg/server/templates/enoent.html
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
{{define "body"}}
|
||||
<div class="alert alert-danger msg">
|
||||
<h4>File missing!</h4>
|
||||
<p>This file is indexed but has been removed from the file system.</p>
|
||||
<p>Do you want to delete this entry from the index?</p>
|
||||
</div>
|
||||
<form class="form-horizontal" action="/delete{{.Path}}" method="post">
|
||||
<input type="hidden" name="token" value="{{.Token}}">
|
||||
<input type="hidden" name="clean" value="true">
|
||||
<button class="btn btn-sm btn-danger" type="submit">Delete</button>
|
||||
</form>
|
||||
{{end}}
|
||||
41
pkg/server/templates/file.html
Normal file
41
pkg/server/templates/file.html
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
{{define "body"}}
|
||||
<div class="row">
|
||||
<div class="nav-container full-width relative">
|
||||
<ol class="breadcrumb full-width">
|
||||
<li class="breadcrumb-item"></li>
|
||||
<li class="breadcrumb-item"><a href="/">root</a></li>
|
||||
{{range $item := .Paths}}
|
||||
<li class="breadcrumb-item{{if $item.Flag}} active{{end}}">{{if $item.Flag}}{{$item.Name}}{{else}}<a href="{{$item.Abs}}">{{$item.Name}}</a>{{end}}</li>
|
||||
{{end}}
|
||||
</ol>
|
||||
<div class="btn-group btn-breadcrumb">
|
||||
{{if .Data.Scan}}
|
||||
<a href="#" class="btn btn-sm btn-warning">Scanning</a>
|
||||
{{else}}
|
||||
{{if .Data.Flag}}
|
||||
<a href="/retag{{.Data.Name}}" class="btn btn-sm btn-primary">Retag</a>
|
||||
{{else}}
|
||||
<a href="/index{{.Data.Name}}" class="btn btn-sm btn-success">Index</a>
|
||||
{{end}}
|
||||
{{end}}
|
||||
<a target="_blank" href="{{.Data.Abs}}" class="btn btn-sm btn-primary">Raw</a>
|
||||
<a href="/move{{.Data.Name}}" class="btn btn-sm btn-primary">Move</a>
|
||||
<a href="/delete{{.Data.Name}}" class="btn btn-sm btn-danger">Delete</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="alert alert-secondary full-width">
|
||||
{{if .Tags}}
|
||||
Tags
|
||||
{{range $t := .Tags}}
|
||||
<a href="/search?query=tags:{{$t}}" class="btn badge btn-primary tag">{{$t}}</a>
|
||||
{{end}}
|
||||
{{end}}
|
||||
<span class="float-right">{{.Created}}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<embed src="{{.Data.Abs}}" toolbar="1" statusbar="1" navpanes="1"></embed>
|
||||
</div>
|
||||
{{end}}
|
||||
17
pkg/server/templates/forbidden.html
Normal file
17
pkg/server/templates/forbidden.html
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
{{define "body"}}
|
||||
<div class="page-header">
|
||||
<div class="row">
|
||||
<div class="col-xs-4 offset-4">
|
||||
<div class="card border-danger mx-auto">
|
||||
<div class="card-header">
|
||||
<strong>403 - Forbidden</strong>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<h5>Access to this page is restricted</h5>
|
||||
<a href="/" class="btn btn-sm btn-primary">Back</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
44
pkg/server/templates/index.html
Normal file
44
pkg/server/templates/index.html
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>DocStore | {{.Title}}</title>
|
||||
<link rel="shortcut icon" type="image/x-icon" href="/static/favicon.ico" integrity="sha256-bgotk/IPq4Yvt6s8AQGPTM5ZjPjQ6rrBRa2EyxpnFSc="></link>
|
||||
<link rel="stylesheet" type="text/css" href="/static/bootstrap.css" media="screen" integrity="sha256-3YeveuySvBgp2GItUS8eV1R/9T1zcPMyvw22SyVf8qo="></link>
|
||||
<link rel="stylesheet" type="text/css" href="/static/custom.css" media="screen" integrity="sha256-wLiyjr/D8ZaaIPLjUmZ3zdm45/HW/cy4kCVTViwkPeI="></link>
|
||||
<meta name="theme-color" content="#375a7f">
|
||||
<meta name="description" content="{{.Title}}">
|
||||
</head>
|
||||
<body id="top">
|
||||
<div class="navbar navbar-expand fixed-top navbar-dark bg-primary">
|
||||
<div class="container">
|
||||
<a href="/" class="navbar-brand">DocStore</a>
|
||||
<div class="collapse navbar-collapse">
|
||||
{{template "menu" .}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container">
|
||||
<div class="proper-content">
|
||||
{{if .Msg}}
|
||||
<div class="alert alert-danger msg">
|
||||
<h4>Error!</h4>
|
||||
<p>{{.Msg}}</p>
|
||||
</div>
|
||||
{{end}}
|
||||
{{template "body" .}}
|
||||
</div>
|
||||
<div class="push"></div>
|
||||
<footer>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<ul class="list-unstyled">
|
||||
<li class="float-md-right"><a href="#top">Back to top</a></li>
|
||||
<li><a href="https://git.giftfish.de/ston1th/docstore">Git</a></li>
|
||||
</ul>
|
||||
<p>© DocStore {{.Version}} Request: <strong>{{.Time}}</strong></p>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
7
pkg/server/templates/ise.html
Normal file
7
pkg/server/templates/ise.html
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
{{define "body"}}
|
||||
<div class="alert alert-danger msg">
|
||||
<h4>Error!</h4>
|
||||
<p>{{.Data}}</p>
|
||||
</div>
|
||||
<a href="{{.Path}}" class="btn btn-sm btn-primary">Back</a>
|
||||
{{end}}
|
||||
34
pkg/server/templates/login.html
Normal file
34
pkg/server/templates/login.html
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
{{define "body"}}
|
||||
<div class="page-header">
|
||||
<div class="row">
|
||||
<div class="col-xs-4 offset-4">
|
||||
<div class="card border-primary mx-auto">
|
||||
<div class="card-header">
|
||||
<strong>{{.BodyTitle}}</strong>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form class="form-horizontal" action="/login" method="post">
|
||||
<input type="hidden" name="token" value="{{.Token}}">
|
||||
<input type="hidden" name="referer" value="{{.Data.Referer}}">
|
||||
<div class="form-group">
|
||||
<label class="col-form-label" for="user">Username</label>
|
||||
<input class="form-control input-sm" type="text" id="user" name="user" value="{{.Data.User}}" autofocus required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-form-label" for="password">Password</label>
|
||||
<input class="form-control input-sm" type="password" id="password" name="password" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="custom-control custom-checkbox">
|
||||
<input type="checkbox" class="custom-control-input" id="remember" name="remember">
|
||||
<label class="custom-control-label" for="remember">Remember Me</label>
|
||||
</div>
|
||||
</div>
|
||||
<button class="btn btn-sm btn-primary" type="submit">Login</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
24
pkg/server/templates/loginTotp.html
Normal file
24
pkg/server/templates/loginTotp.html
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
{{define "body"}}
|
||||
<div class="page-header">
|
||||
<div class="row">
|
||||
<div class="col-xs-4 offset-4">
|
||||
<div class="card border-primary mx-auto">
|
||||
<div class="card-header">
|
||||
<strong>{{.BodyTitle}}</strong>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form class="form-horizontal" action="/totp" method="post">
|
||||
<input type="hidden" name="token" value="{{.Token}}">
|
||||
<div class="form-group">
|
||||
<label class="col-form-label" for="pin">PIN</label>
|
||||
<input class="form-control input-sm" type="text" id="pin" name="pin" autocomplete="off" autofocus required>
|
||||
</div>
|
||||
<button class="btn btn-sm btn-primary" type="submit">Verify</button>
|
||||
<a href="/logout" class="btn btn-sm btn-primary">Cancel</a>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
17
pkg/server/templates/logs.html
Normal file
17
pkg/server/templates/logs.html
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
{{define "body"}}
|
||||
<div class="page-header">
|
||||
<div class="row">
|
||||
<h2>{{.BodyTitle}}</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-3">
|
||||
<div class="col col-nopad">
|
||||
<div class="alert alert-primary">
|
||||
<p>This log will display error information about batch operations such as <code>Retag All</code> or <code>Index All</code>.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-3">
|
||||
<textarea class="form-control input-sm md-text mono" rows="30" spellcheck="false" autofocus>{{.Data}}</textarea>
|
||||
</div>
|
||||
{{end}}
|
||||
25
pkg/server/templates/menu.html
Normal file
25
pkg/server/templates/menu.html
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
{{define "menu"}}
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item"><a class="nav-link" href="/">Root</a></li>
|
||||
{{if .Login}}
|
||||
<li class="nav-item"><a class="nav-link" href="/tags">Tags</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="/logs">Logs</a></li>
|
||||
{{end}}
|
||||
</ul>
|
||||
{{if .Login}}
|
||||
<form class="form-inline" method="post" action="/search">
|
||||
<input type="hidden" name="token" value="{{.Token}}">
|
||||
<input type="text" class="form-control mr-sm-2 menu" placeholder="Query" name="query" value="{{.Query}}" autocomplete="off">
|
||||
<button class="btn btn-sm btn-info" type="submit">Search</button>
|
||||
</form>
|
||||
{{end}}
|
||||
<ul class="nav navbar-nav ml-auto">
|
||||
{{if .Login}}
|
||||
<li class="nav-item"><a class="nav-link" href="/stats">Stats</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="/user/edit">Profile</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="/logout">Logout</a></li>
|
||||
{{else}}
|
||||
<li class="nav-item"><a class="nav-link" href="/login">Login</a></li>
|
||||
{{end}}
|
||||
</ul>
|
||||
{{end}}
|
||||
30
pkg/server/templates/move.html
Normal file
30
pkg/server/templates/move.html
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
{{define "body"}}
|
||||
<div class="row">
|
||||
<div class="col-xs-4 offset-4">
|
||||
<div class="card border-primary mx-auto">
|
||||
<div class="card-header">
|
||||
<strong>{{.BodyTitle}}</strong>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form class="form-horizontal" action="/move{{.Path}}" method="post">
|
||||
<input type="hidden" name="token" value="{{.Token}}">
|
||||
<div class="form-group">
|
||||
<label class="col-form-label" for="destination">Destination</label>
|
||||
<select class="form-control input-sm" id="destination" name="destination" required>
|
||||
{{range $item := .Paths}}
|
||||
<option value="{{$item.Abs}}"{{if $item.Flag}} selected{{end}}>{{$item.Abs}}</option>
|
||||
{{end}}
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-form-label" for="name">Name</label>
|
||||
<input class="form-control input-sm" type="text" id="name" name="name" autocomplete="off" value="{{.Data}}">
|
||||
</div>
|
||||
<button class="btn btn-sm btn-primary" type="submit">Move</button>
|
||||
<a href="{{.Path}}" class="btn btn-sm btn-primary">Back</a>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
23
pkg/server/templates/newDir.html
Normal file
23
pkg/server/templates/newDir.html
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
{{define "body"}}
|
||||
<div class="row">
|
||||
<div class="col-xs-4 offset-4">
|
||||
<div class="card border-primary mx-auto">
|
||||
<div class="card-header">
|
||||
<strong>{{.BodyTitle}}</strong>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p>Create new directory in <a href="{{.Path}}">{{.Path}}</a>.</p>
|
||||
<form class="form-horizontal" action="/new{{.Path}}" method="post">
|
||||
<input type="hidden" name="token" value="{{.Token}}">
|
||||
<div class="form-group">
|
||||
<label class="col-form-label" for="name">Name</label>
|
||||
<input class="form-control input-sm" type="text" id="name" name="name" autocomplete="off" value="{{.Data}}" autofocus required>
|
||||
</div>
|
||||
<button class="btn btn-sm btn-primary" type="submit">Create</button>
|
||||
<a href="{{.Path}}" class="btn btn-sm btn-primary">Back</a>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
17
pkg/server/templates/notFound.html
Normal file
17
pkg/server/templates/notFound.html
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
{{define "body"}}
|
||||
<div class="page-header">
|
||||
<div class="row">
|
||||
<div class="col-xs-4 offset-4">
|
||||
<div class="card border-danger mx-auto">
|
||||
<div class="card-header">
|
||||
<strong>404 - Page Not Found</strong>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<h5>The requested page could not be found</h5>
|
||||
<a href="/" class="btn btn-sm btn-primary">Back</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
29
pkg/server/templates/register.html
Normal file
29
pkg/server/templates/register.html
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
{{define "body"}}
|
||||
<div class="row">
|
||||
<div class="col-xs-4 offset-4">
|
||||
<div class="card border-primary mx-auto">
|
||||
<div class="card-header">
|
||||
<strong>{{.BodyTitle}}</strong>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form class="form-horizontal" action="/" method="post">
|
||||
<input type="hidden" name="token" value="{{.Token}}">
|
||||
<div class="form-group">
|
||||
<label class="col-form-label" for="user">Username</label>
|
||||
<input class="form-control input-sm" type="text" id="user" name="user" autocomplete="off" value="{{.Data}}" autofocus required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-form-label" for="password">Password</label>
|
||||
<input class="form-control input-sm" type="password" id="password" name="password" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-form-label" for="repeat">Repeat</label>
|
||||
<input class="form-control input-sm" type="password" id="repeat" name="repeat" required>
|
||||
</div>
|
||||
<button class="btn btn-sm btn-primary" type="submit">Create</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
71
pkg/server/templates/search.html
Normal file
71
pkg/server/templates/search.html
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
{{define "body"}}
|
||||
<div class="page-header">
|
||||
<div class="row">
|
||||
<h2>{{.BodyTitle}}</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-3">
|
||||
<div class="col col-nopad">
|
||||
<form class="form-horizontal" action="/search" method="post">
|
||||
<input type="hidden" name="token" value="{{.Token}}">
|
||||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<input type="text" class="form-control input-sm" placeholder="Query" name="query" value="{{.Query}}" autocomplete="off" autofocus>
|
||||
<div class="input-group-append">
|
||||
<button class="btn btn-sm btn-primary" type="submit">Search</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-3">
|
||||
{{if .Data}}
|
||||
<table class="table table-stripped table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>File</th>
|
||||
<th>Tags</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{range $item := .Data}}
|
||||
<tr>
|
||||
<td>
|
||||
<a class="mono" href="{{$item.Path}}"><b>{{$item.Path}}</b></a>
|
||||
{{if $item.HTML}}
|
||||
<br><pre class="wrap">{{$item.HTML}}</pre>
|
||||
{{end}}
|
||||
</td>
|
||||
<td>
|
||||
{{range $t := $item.Tags}}
|
||||
<a href="/search?query=tags:{{$t}}" class="btn badge btn-primary">{{$t}}</a>
|
||||
{{end}}
|
||||
</td>
|
||||
</tr>
|
||||
{{end}}
|
||||
</tbody>
|
||||
</table>
|
||||
{{else}}
|
||||
<b>No search results found.</b>
|
||||
</div>
|
||||
<div class="row mt-3">
|
||||
<div class="col col-nopad">
|
||||
<div class="alert alert-primary">
|
||||
<h4>Query Syntax</h4>
|
||||
<p>Documentation: <a target="_blank" rel="noopener noreferrer" href="https://github.com/bcampbell/qs/blob/master/syntax.md">https://github.com/bcampbell/qs/blob/master/syntax.md</a></p>
|
||||
<p>Fields</p>
|
||||
<pre><code>tags:insurance
|
||||
tags:insurance OR tags:invoice
|
||||
# combine tags
|
||||
tags:insurance AND tags:invoice
|
||||
# exclude tags
|
||||
tags:insurance -tags:invoice
|
||||
created:<="2016-09-21"</code></pre>
|
||||
<p>Fulltext</p>
|
||||
<pre><code>some text here</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
{{end}}
|
||||
33
pkg/server/templates/stats.html
Normal file
33
pkg/server/templates/stats.html
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
{{define "body"}}
|
||||
<div class="page-header">
|
||||
<div class="row">
|
||||
<h2>{{.BodyTitle}}</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<table class="table table-stripped table-hover">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><b>Goroutines</b></td>
|
||||
<td>{{.Data.Goroutines}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Memory usage</b></td>
|
||||
<td>{{.Data.Alloc}} MiB</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Memory allocated</b></td>
|
||||
<td>{{.Data.Sys}} MiB</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Documents</b></td>
|
||||
<td>{{.Data.Docs}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Go Version</b></td>
|
||||
<td>{{.Data.GoVersion}}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{{end}}
|
||||
20
pkg/server/templates/tagsDel.html
Normal file
20
pkg/server/templates/tagsDel.html
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
{{define "body"}}
|
||||
<div class="row">
|
||||
<div class="col-xs-4 offset-4">
|
||||
<div class="card border-primary mx-auto">
|
||||
<div class="card-header">
|
||||
<strong>{{.BodyTitle}}</strong>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p>You are about to delete the tag
|
||||
<a href="/tags/edit/{{.Data}}">{{.Data}}</a>.
|
||||
<form class="form-horizontal" action="/tags/del/{{.Data}}" method="post">
|
||||
<input type="hidden" name="token" value="{{.Token}}">
|
||||
<button class="btn btn-sm btn-danger" type="submit">Delete</button>
|
||||
<a href="/tags" class="btn btn-sm btn-primary">Back</a>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
30
pkg/server/templates/tagsEdit.html
Normal file
30
pkg/server/templates/tagsEdit.html
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
{{define "body"}}
|
||||
<div class="row">
|
||||
<div class="col-8 offset-2">
|
||||
<div class="card border-primary mx-auto">
|
||||
<div class="card-header">
|
||||
<strong>{{.BodyTitle}}</strong>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="alert alert-dismissible alert-primary">
|
||||
<strong>Note</strong> Editing a tag does not update tags already assigned to a document.
|
||||
You need to retag all documents to avoid false-positive searches.
|
||||
</div>
|
||||
<form class="form-horizontal" action="/tags/edit/{{.Data.Name}}" method="post">
|
||||
<input type="hidden" name="token" value="{{.Token}}">
|
||||
<div class="form-group">
|
||||
<label class="col-form-label" for="name">Name</label>
|
||||
<input class="form-control input-sm" type="text" id="name" name="name" value="{{.Data.Name}}" disabled>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-form-label" for="regex">Regex</label>
|
||||
<input class="form-control input-sm mono" type="text" id="regex" name="regex" value="{{.Data.Regex}}" autofocus required>
|
||||
</div>
|
||||
<button class="btn btn-sm btn-primary" type="submit">Update</button>
|
||||
<a href="/tags" class="btn btn-sm btn-primary">Back</a>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
38
pkg/server/templates/tagsList.html
Normal file
38
pkg/server/templates/tagsList.html
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
{{define "body"}}
|
||||
<div class="page-header">
|
||||
<div class="row">
|
||||
<h2>{{.BodyTitle}}</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<div class="col-xs-5">
|
||||
<a class="btn btn-sm btn-primary" href="/tags/new"><b>New Tag</b></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<table class="table table-stripped table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Regex</th>
|
||||
<th>Options</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{if .Data}}
|
||||
{{range $item := .Data}}
|
||||
{{$len := len $item.Regex}}
|
||||
<tr>
|
||||
<td><a href="/search?query=tags:{{$item.Name}}" class="btn badge btn-primary tag">{{$item.Name}}</a></td>
|
||||
<td><code>{{printf "%.50s" $item.Regex}}{{if gt $len 50}}...{{end}}</code></td>
|
||||
<td><div class="btn-group">
|
||||
<a href="/tags/edit/{{$item.Name}}" class="btn btn-sm btn-primary">Edit</a>
|
||||
<a href="/tags/del/{{$item.Name}}" class="btn btn-sm btn-danger">Delete</a>
|
||||
</div></td>
|
||||
</tr>
|
||||
{{end}}
|
||||
{{end}}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{{end}}
|
||||
26
pkg/server/templates/tagsNew.html
Normal file
26
pkg/server/templates/tagsNew.html
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
{{define "body"}}
|
||||
<div class="row">
|
||||
<div class="col-8 offset-2">
|
||||
<div class="card border-primary mx-auto">
|
||||
<div class="card-header">
|
||||
<strong>{{.BodyTitle}}</strong>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form class="form-horizontal" action="/tags/new" method="post">
|
||||
<input type="hidden" name="token" value="{{.Token}}">
|
||||
<div class="form-group">
|
||||
<label class="col-form-label" for="name">Name</label>
|
||||
<input class="form-control input-sm" type="text" id="name" name="name" value="{{.Data.Name}}" autofocus required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-form-label" for="regex">Regex</label>
|
||||
<input class="form-control input-sm mono" type="text" id="regex" name="regex" value="{{.Data.Regex}}" required>
|
||||
</div>
|
||||
<button class="btn btn-sm btn-primary" type="submit">Create</button>
|
||||
<a href="/tags" class="btn btn-sm btn-primary">Back</a>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
30
pkg/server/templates/upload.html
Normal file
30
pkg/server/templates/upload.html
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
{{define "body"}}
|
||||
<div class="row">
|
||||
<div class="col-xs-4 offset-4">
|
||||
<div class="card border-primary mx-auto">
|
||||
<div class="card-header">
|
||||
<strong>{{.BodyTitle}}</strong>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form class="form-horizontal" action="/upload{{.Path}}" method="post" enctype="multipart/form-data">
|
||||
<input type="hidden" name="token" value="{{.Token}}">
|
||||
<div class="form-group">
|
||||
<label class="col-form-label" for="name">Name</label>
|
||||
<input class="form-control input-sm" type="text" id="name" name="name" autocomplete="off" value="{{.Data}}" placeholder="optional">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="input-group mb-3">
|
||||
<div class="custom-file">
|
||||
<input type="file" class="custom-file-input" id="file" name="file">
|
||||
<label class="custom-file-label" for="file">Choose file</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button class="btn btn-sm btn-success" type="submit">Upload</button>
|
||||
<a href="{{.Path}}" class="btn btn-sm btn-primary">Back</a>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
31
pkg/server/templates/userEdit.html
Normal file
31
pkg/server/templates/userEdit.html
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
{{define "body"}}
|
||||
<div class="row">
|
||||
<div class="col-xs-4 offset-4">
|
||||
<div class="card border-primary mx-auto">
|
||||
<div class="card-header">
|
||||
<strong>{{.BodyTitle}}</strong>
|
||||
{{if .Data.Secret}}
|
||||
<a href="/user/totp" class="btn btn-sm btn-danger float-right">Disable TOTP</a>
|
||||
{{else}}
|
||||
<a href="/user/totp" class="btn btn-sm btn-success float-right">Enable TOTP</a>
|
||||
{{end}}
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form class="form-horizontal" action="/user/edit" method="post">
|
||||
<input type="hidden" name="token" value="{{.Token}}">
|
||||
<div class="form-group">
|
||||
<label class="col-form-label" for="password">New Password</label>
|
||||
<input class="form-control input-sm" type="password" id="password" name="password" autofocus>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-form-label" for="repeat">Repeat</label>
|
||||
<input class="form-control input-sm" type="password" id="repeat" name="repeat">
|
||||
</div>
|
||||
<button class="btn btn-sm btn-primary" type="submit">Update</button>
|
||||
<a href="/" class="btn btn-sm btn-primary">Back</a>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
36
pkg/server/templates/userTotp.html
Normal file
36
pkg/server/templates/userTotp.html
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
{{define "body"}}
|
||||
<div class="row">
|
||||
<div class="col-xs-4 offset-4">
|
||||
<div class="card border-primary mx-auto">
|
||||
<div class="card-header">
|
||||
<strong>{{.BodyTitle}}</strong>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form class="form-horizontal" action="/user/totp" method="post">
|
||||
<input type="hidden" name="token" value="{{.Token}}">
|
||||
{{if .Data.Secret}}
|
||||
<input type="hidden" name="url" value="{{.Data.URL}}">
|
||||
<div class="form-group">
|
||||
<img src="{{.Data.Image}}" alt="{{.Data.Secret}}">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-form-label" for="secret">Secret</label>
|
||||
<pre><code id="secret">{{.Data.Secret}}</code></pre>
|
||||
</div>
|
||||
{{end}}
|
||||
<div class="form-group">
|
||||
<label class="col-form-label" for="pin">PIN</label>
|
||||
<input class="form-control input-sm" type="text" id="pin" name="pin" autocomplete="off" autofocus required>
|
||||
</div>
|
||||
{{if .Data.Secret}}
|
||||
<button class="btn btn-sm btn-success" type="submit">Enable</button>
|
||||
{{else}}
|
||||
<button class="btn btn-sm btn-danger" type="submit">Disable</button>
|
||||
{{end}}
|
||||
<a href="/user/edit" class="btn btn-sm btn-primary">Back</a>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
Loading…
Add table
Add a link
Reference in a new issue