pull/144/head
Henrique Dias 2016-06-14 18:19:10 +01:00
parent 8393244e9d
commit e137f46169
7 changed files with 157 additions and 64 deletions

View File

@ -417,7 +417,8 @@ td, th {
body {
font-family: 'Roboto', sans-serif;
text-rendering: optimizespeed;
padding-top: 4em;
padding-top: 5em;
background-color: #f5f5f5;
}
a {
color: #006ed3;
@ -462,6 +463,7 @@ table {
tr {
border-bottom: 1px dashed #dadada;
transition: .1s ease all;
cursor: pointer;
}
tr.selected {
background-color: #ccc;
@ -503,18 +505,19 @@ td .name, td .goup {
vertical-align: middle;
}
footer {
padding: 40px 20px;
font-size: 12px;
font-size: .6em;
text-align: center;
color: grey;
}
footer a,
footer a:hover {
color: inherit;
}
.container {
margin: 0 auto;
width: 95%;
max-width: 960px;
}
.listing i {
vertical-align: middle;
}
pre {
border: 1px solid #e6e6e6;
background-color: #f5f5f5;
@ -577,47 +580,53 @@ header h1 {
}
header p {
font-size: 1.5em;
padding: 0.25em 0;
}
header p i {
vertical-align: middle;
font-size: 1em !important;
color: rgba(0, 0, 0, 0.21);
}
header p i {
vertical-align: middle;
}
header form {
display: inline-block;
background-color: #1E88E5;
padding: .75em;
color: #212121;
border-radius: .3em;
height: 100%;
vertical-align: middle;
display: inline-block;
background-color: #1E88E5;
padding: .75em;
color: #212121;
border-radius: .3em;
height: 100%;
vertical-align: middle;
}
header form input,
header form i {
header form input, header form i {
vertical-align: middle;
}
header form i {
margin-right: .3em;
color: rgba(0,0,0,0.5)
color: rgba(0, 0, 0, 0.5)
}
header form input {
border: 0;
outline: 0;
background-color: transparent;
min-width: 20em;
border: 0;
outline: 0;
background-color: transparent;
min-width: 20em;
}
::-webkit-input-placeholder { /* WebKit, Blink, Edge */
color: rgba(0,0,0,0.5);
::-webkit-input-placeholder {
/* WebKit, Blink, Edge */
color: rgba(0, 0, 0, 0.5);
}
:-moz-placeholder { /* Mozilla Firefox 4 to 18 */
color: rgba(0,0,0,0.5);
opacity: 1;
:-moz-placeholder {
/* Mozilla Firefox 4 to 18 */
color: rgba(0, 0, 0, 0.5);
opacity: 1;
}
::-moz-placeholder { /* Mozilla Firefox 19+ */
color: rgba(0,0,0,0.5);
opacity: 1;
::-moz-placeholder {
/* Mozilla Firefox 19+ */
color: rgba(0, 0, 0, 0.5);
opacity: 1;
}
:-ms-input-placeholder { /* Internet Explorer 10-11 */
color: rgba(0,0,0,0.5);
:-ms-input-placeholder {
/* Internet Explorer 10-11 */
color: rgba(0, 0, 0, 0.5);
}
header, #toolbar {
position: fixed;
@ -627,17 +636,19 @@ header, #toolbar {
padding: .5em;
display: flex;
}
#toolbar div,
header div {
#toolbar div, header div {
flex-grow: 1;
vertical-align: middle;
}
#toolbar p,
header p {
#toolbar p, header p {
display: inline-block;
margin: 0;
vertical-align: middle;
}
#toolbar p a, header p a,
#toolbar p a:hover, header p a:hover {
color: inherit;
}
#toolbar {
background-color: #6f6f6f;
color: #fff;
@ -646,11 +657,10 @@ header p {
transition: .2s ease-in-out all;
}
#toolbar.enabled {
top: 0;
opacity: 1;
top: 0;
opacity: 1;
}
#toolbar div:nth-child(2),
header div:nth-child(2) {
#toolbar div:nth-child(2), header div:nth-child(2) {
text-align: right;
}
.action {
@ -662,7 +672,7 @@ header div:nth-child(2) {
transition: .2s ease all;
}
.action.disabled {
opacity: 0;
opacity: .2;
}
.action i {
padding: .5em;
@ -672,3 +682,45 @@ header div:nth-child(2) {
.action:hover i {
background-color: rgba(0, 0, 0, 0.1);
}
/* LISTING */
#listing {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
padding: 0 .5em;
}
#listing .item {
background-color: #fff;
border-radius: .2em;
padding: .5em;
margin: 0 .5em 1em;
border: .2em solid #fff;
cursor: pointer;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06), 0 1px 2px rgba(0, 0, 0, 0.12);
transition: .2s ease all;
flex-grow: 1;
}
.item:hover {
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24) !important;
}
.item.selected {
border-color: #6f6f6f !important;
}
.item div {
display: inline-block;
vertical-align: middle;
}
.item p {
margin: 0;
font-size: .9em;
color: #4e4e4e;
}
.item span {
font-weight: bold;
}
.item i {
font-size: 4em;
margin-right: .1em;
}

View File

@ -3,7 +3,7 @@
var selectedItems = [];
document.addEventListener("DOMContentLoaded", function(event) {
var items = document.getElementsByTagName('tr');
var items = document.getElementsByClassName('item');
Array.from(items).forEach(link => {
link.addEventListener('click', function(event) {
var url = link.getElementsByTagName('a')[0].getAttribute('href');
@ -31,7 +31,7 @@ document.addEventListener("DOMContentLoaded", function(event) {
});
var backEvent = function(event) {
var items = document.getElementsByTagName('tr');
var items = document.getElementsByClassName('item');
Array.from(items).forEach(link => {
link.classList.remove('selected');
});

View File

@ -5,17 +5,17 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<link href='https://fonts.googleapis.com/css?family=Roboto:400,500' rel='stylesheet' type='text/css'>
<link rel="stylesheet" href="/_filemanagerinternal/css/styles.css">
<script src="/_filemanagerinternal/js/application.js"></script>
<style>
</style>
<link rel="stylesheet" href="{{ .Config.BaseURL }}/_filemanagerinternal/css/styles.css">
<script src="{{ .Config.BaseURL }}/_filemanagerinternal/js/application.js"></script>
{{ if ne .Config.StyleSheet "" }}<style>{{ .Config.StyleSheet}}</style>{{ end }}
</head>
<body>
<header>
<div>
<p>File Manager <i class="material-icons">chevron_right</i> {{ .Name }}</p>
{{ $lnk := .PreviousLink }}
{{ if ne $lnk ""}}<a href="../../{{.PreviousLink}}"><div class="action" id="prev"><i class="material-icons">subdirectory_arrow_left</i></div></a>{{ else }}
<div class="action disabled" id="prev"><i class="material-icons">subdirectory_arrow_left</i></div>{{ end }}
<p><a href="{{ if eq .Config.BaseURL "" }}/{{ else }}{{ .Config.BaseURL }}{{ end }}">File Manager</a> {{ if ne .Name "."}}<i class="material-icons">chevron_right</i> {{ .Name }}</p>{{ end }}
</div>
<div>
<form>
@ -39,12 +39,11 @@
</div>
</div>
File Manager {{range $url, $name := .BreadcrumbMap}}<i>></i><a href="/{{$url}}">{{$name}}</a>{{end}}
<main>
{{ template "content" .Data }}
</main>
<footer>
Served with <a rel="noopener noreferrer" href="https://caddyserver.com">Caddy</a>.
Served with <a rel="noopener noreferrer" href="https://caddyserver.com">Caddy</a> and <a rel="noopener noreferrer" href="https://github.com/hacdias/caddy-filemanager">File Manager</a>.
</footer>
<script type="text/javascript">
function localizeDatetime(e, index, ar) {

View File

@ -1,7 +1,32 @@
{{ define "content" }}
<div class="listing">
<div>There are {{.NumDirs}}</b> director{{if eq 1 .NumDirs}}y{{else}}ies{{end}} and {{.NumFiles}}</b> file{{if ne 1 .NumFiles}}s{{end}} in here.</div>
<div class="container" id="listing">
{{- range .Items}}
<div class="item">
<div>
<a href="{{.URL}}">
{{- if .IsDir}}
<i class="material-icons">folder</i>
{{- else}}
<i class="material-icons">insert_drive_file</i>
{{- end}}
</a>
</div>
<div>
<span class="name">{{.Name}}</span>
{{- if .IsDir}}
<p data-order="-1">&mdash;</p>
{{- else}}
<p data-order="{{.Size}}">{{.HumanSize}}</p>
{{- end}}
<p class="hideable"><time datetime="{{.HumanModTime "2006-01-02T15:04:05Z"}}">{{.HumanModTime "01/02/2006 03:04:05 PM -07:00"}}</time></p>
</div>
</div>
{{- end}}
</div>
<!--
<table class="container" aria-describedby="summary">
<thead>
<tr>
@ -57,6 +82,6 @@
</tr>
{{- end}}
</tbody>
</table>
</table> -->
</div>
{{ end }}

View File

@ -35,7 +35,7 @@ type FileInfo struct {
func GetFileInfo(url *url.URL, c *Config) (*FileInfo, int, error) {
var err error
path := strings.Replace(url.Path, c.BaseURL, c.PathScope, 1)
path := strings.Replace(url.Path, c.BaseURL, "", 1)
path = filepath.Clean(path)
path = strings.Replace(path, "\\", "/", -1)
@ -138,10 +138,10 @@ func (fi FileInfo) ServeAsHTML(w http.ResponseWriter, r *http.Request, c *Config
return fi.serveListing(w, r, c)
}
return fi.serveSingleFile(w, r)
return fi.serveSingleFile(w, r, c)
}
func (fi FileInfo) serveSingleFile(w http.ResponseWriter, r *http.Request) (int, error) {
func (fi FileInfo) serveSingleFile(w http.ResponseWriter, r *http.Request, c *Config) (int, error) {
err := fi.GetExtendedFileInfo()
if err != nil {
return ErrorToHTTPCode(err), err
@ -149,9 +149,10 @@ func (fi FileInfo) serveSingleFile(w http.ResponseWriter, r *http.Request) (int,
page := &Page{
Info: &PageInfo{
Name: fi.Path,
Path: fi.Path,
Data: fi,
Name: fi.Path,
Path: fi.Path,
Data: fi,
Config: c,
},
}
@ -202,9 +203,10 @@ func (fi FileInfo) serveListing(w http.ResponseWriter, r *http.Request, c *Confi
page := &Page{
Info: &PageInfo{
Name: listing.Name,
Path: listing.Path,
Data: listing,
Name: listing.Name,
Path: listing.Path,
Config: c,
Data: listing,
},
}

11
page.go
View File

@ -49,6 +49,17 @@ func (p PageInfo) BreadcrumbMap() map[string]string {
return result
}
// PreviousLink returns the path of the previous folder
func (p PageInfo) PreviousLink() string {
parts := strings.Split(p.Path, "/")
if len(parts) <= 1 {
return ""
}
return parts[len(parts)-2]
}
// PrintAsHTML formats the page in HTML and executes the template
func (p Page) PrintAsHTML(w http.ResponseWriter, templates ...string) (int, error) {
templates = append(templates, "base")

View File

@ -4,6 +4,7 @@ import (
"fmt"
"io/ioutil"
"net/http"
"strings"
"github.com/mholt/caddy"
"github.com/mholt/caddy/caddyhttp/httpserver"
@ -54,7 +55,7 @@ func parseConfiguration(c *caddy.Controller) ([]Config, error) {
}
for c.Next() {
var cfg = Config{PathScope: "."}
var cfg = Config{PathScope: ".", BaseURL: ""}
for c.NextBlock() {
switch c.Val() {
case "show":
@ -67,6 +68,9 @@ func parseConfiguration(c *caddy.Controller) ([]Config, error) {
return configs, c.ArgErr()
}
cfg.BaseURL = c.Val()
cfg.BaseURL = strings.TrimPrefix(cfg.BaseURL, "/")
cfg.BaseURL = strings.TrimSuffix(cfg.BaseURL, "/")
cfg.BaseURL = "/" + cfg.BaseURL
case "styles":
if !c.NextArg() {
return configs, c.ArgErr()