pull/144/head
Henrique Dias 2016-12-30 16:22:26 +00:00
parent 4f063734c4
commit 997f42a531
8 changed files with 260 additions and 81 deletions

View File

@ -768,6 +768,69 @@ header #logout {
color: rgba(255, 255, 255, .5);
}
/* BREADCRUMB */
header>div:last-child>div:first-child>* {
display: inline-block;
vertical-align: middle;
}
header>div:last-child>div:first-child>i {
margin-right: .3em;
}
#breadcrumbs-button {
padding: .4em 0.3em;
border-radius: .1em;
cursor: pointer;
transition: .1s ease all;
}
#breadcrumbs-button.active,
#breadcrumbs-button:hover {
box-shadow: 0 0 5px rgba(0, 0, 0, 0.1);
background: #fff;
}
#current-file {
line-height: 2.7em;
}
#breadcrumbs {
transition: .1s ease all;
padding: 0;
margin: 0;
list-style: none;
display: inline-flex;
flex-direction: column;
border-radius: 2px;
border-top-left-radius: 0;
box-shadow: 0 0 5px rgba(0, 0, 0, 0.1);
background: #fff;
position: absolute;
left: 0;
top: 2.3em;
min-width: 7em;
z-index: 999;
opacity: 0;
visibility: hidden;
color: #656565;
}
#breadcrumbs.active {
opacity: 1;
visibility: visible;
}
#breadcrumbs li {
line-height: 1.5em;
padding: .3em;
}
/* MORE STUFF */
header>div {
display: flex;
width: 100%;
@ -775,7 +838,7 @@ header>div {
}
header>div:first-child>div:nth-child(1) {
margin-right: 2em;
margin-right: 1em;
font-weight: 500;
font-size: 1.5em;
line-height: 2;
@ -802,10 +865,12 @@ header #file-only {
padding-right: .3em;
margin-right: .3em;
transition: .2s ease all;
visibility: visible;
}
#file-only.disabled {
opacity: 0;
visibility: hidden;
}
header p {
@ -921,8 +986,8 @@ header .action span {
}
.floating .action {
background-color: #68EFAD;
color: #306e50;
background-color: #2196f3 !important;
color: #fff;
box-shadow: 0 1px 3px rgba(0, 0, 0, .06), 0 1px 2px rgba(0, 0, 0, .12);
}
@ -954,31 +1019,36 @@ header .action span {
/* LISTING */
#listing {
max-width: calc(100% - 1.2em);
width: 100%;
}
#listing h2 {
margin: 0 0 0 0.5em;
font-size: 1em;
color: rgba(0, 0, 0, 0.2);
font-weight: 500;
}
#listing.list h2 {
display: none;
}
#listing>div {
display: flex;
padding: 0;
flex-wrap: wrap;
justify-content: flex-start;
max-width: calc(100% - 2.2em);
width: 100%;
position: relative;
}
#listing.list {
flex-direction: column;
margin-top: -1em;
margin-top: 2em;
width: 100%;
max-width: 100%;
}
#listing.list .item {
width: 100%;
margin: 0;
border: 0;
box-shadow: none;
border-radius: 0;
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
padding: 1em;
}
#listing .item {
margin: .5em;
padding: 0.5em;
@ -991,15 +1061,7 @@ header .action span {
display: flex;
flex-wrap: nowrap;
color: #6f6f6f;
}
.item:hover {
box-shadow: 0 1px 3px rgba(0, 0, 0, .12), 0 1px 2px rgba(0, 0, 0, .24) !important;
}
.item[aria-selected=true] {
background: #2196f3 !important;
color: #fff !important;
transition: .1s ease all;
}
.item div:first-of-type {
@ -1028,6 +1090,56 @@ header .action span {
vertical-align: bottom;
}
#listing .item.header {
display: none !important;
background-color: #ccc;
}
#listing.list .item.header {
display: flex !important;
background: #fafafa;
position: fixed;
width: 100%;
top: 8em;
left: 0;
z-index: 999;
}
#listing.list .item.header>div:first-child {
width: 0;
}
#listing.list .item.header>div:last-child {
/* width: 100%; */
}
#listing.list .item.header>div:last-child *:first-child {
margin-right: 3em;
}
#listing.list .item {
width: 100%;
margin: 0;
border: 0;
box-shadow: none;
border-radius: 0;
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
padding: 1em;
}
#listing .item:hover {
box-shadow: 0 1px 3px rgba(0, 0, 0, .12), 0 1px 2px rgba(0, 0, 0, .24) !important;
}
#listing.list .item:hover {
box-shadow: none !important;
}
#listing .item[aria-selected=true] {
background: #2196f3 !important;
color: #fff !important;
}
#listing.list .item div:first-of-type {
width: 3em;
}
@ -1038,6 +1150,21 @@ header .action span {
#listing.list .item div:last-of-type {
width: calc(100% - 3em);
display: flex;
align-items: center;
}
#listing .item div:last-of-type * {
text-overflow: ellipsis;
overflow: hidden;
}
#listing.list .item div:last-of-type span {
width: 50%;
}
#listing.list .item div:last-of-type p:first-of-type {
width: 25%;
}

View File

@ -185,7 +185,7 @@ function resetSearchText() {
let box = document.querySelector('#search > div div');
if (user.AllowCommands) {
box.innerHTML = `Search or use one of your supported commands: ${user.Commands.join(", ")} `;
box.innerHTML = `Search or use one of your supported commands: ${user.Commands.join(", ")}.`;
} else {
box.innerHTML = "Type and press enter to search.";
}
@ -323,6 +323,11 @@ document.addEventListener("DOMContentLoaded", function(event) {
if (user.AllowEdit) {
buttons.delete.addEventListener("click", deleteEvent);
}
document.getElementById("breadcrumbs-button").addEventListener("click", event => {
event.currentTarget.classList.toggle("active");
document.getElementById("breadcrumbs").classList.toggle("active");
});
setupSearch();
return false;

View File

@ -41,13 +41,12 @@ var renameEvent = function(event) {
let keyDownEvent = (event) => {
if (event.keyCode == 13) {
let newName = span.innerHTML,
newLink = removeLastDirectoryPartOf(toWebDavURL(link)) + newName,
newLink = removeLastDirectoryPartOf(toWebDavURL(link)) + "/" + newName,
html = document.getElementById('rename').changeToLoading(),
request = new XMLHttpRequest();
request.open('MOVE', toWebDavURL(link));
request.setRequestHeader('Destination', newLink);
request.setRequestHeader('Content-type', 'text/plain; charset=utf-8');
request.send();
request.onreadystatechange = function() {
// TODO: redirect if it's moved to another folder

View File

@ -33,7 +33,7 @@
<div>
<div><p>File Manager</p></div>
<div id="search">
<i class="material-icons" title="Storage">storage</i>
<i class="material-icons" title="Search">search</i>
<input type="text" placeholder="Search or execute a command...">
<div>
<div>Loading...</div>
@ -49,20 +49,17 @@
<!-- BOTTOM BAR -->
<div>
<div>
{{ $lnk := .PreviousLink }}
<div class="action{{ if eq $lnk ""}} disabled{{ end }}" id="prev">
{{ if ne $lnk ""}}<a href="{{ $lnk }}">{{ end }}
<i class="material-icons" title="Previous">subdirectory_arrow_left</i>
{{ if ne $lnk ""}}</a>{{ end }}
{{ if ne $lnk ""}}
<ul class="prev-links">
{{ range $link, $name := .BreadcrumbMap }}<a href="{{ $absURL }}{{ $link }}"><li>{{ $name }}</li></a>{{ end }}
</ul>
{{ end }}
</div>
{{ if ne .Name "/"}}
<p id="breadcrumbs-button">Previous</p>
<ul id="breadcrumbs">
{{ range $item := .BreadcrumbMap }}
<a href="{{ $absURL }}{{ $item.URL }}"><li>{{ $item.Name }}</li></a>
{{ end }}
</ul><i class="material-icons">keyboard_arrow_right</i>
{{ if ne .Name "/"}}<p>{{ .Name }}</p>{{ end }}
{{ end }}
<p id="current-file">{{ if ne .Name "/"}}{{ .Name }}{{ else }}Root{{ end }}</p>
</div>
<!-- ACTIONS -->

View File

@ -2,41 +2,76 @@
{{ with .Data }}
<div class="listing">
<div class="container" id="listing">
{{- range .Items}}
{{ if .UserAllowed }}
<div ondragstart="itemDragStart(event)"
{{ if .IsDir}}ondragover="itemDragOver(event)" ondrop="itemDrop(event)"{{ end }}
draggable="true"
class="item"
onclick="selectItemEvent(event)"
ondblclick="openItemEvent(event)"
data-dir="{{ .IsDir }}"
data-url="{{ .URL }}"
id="{{ EncodeBase64 .Name }}">
<div>
{{- if .IsDir}}
<i class="material-icons">folder</i>
{{- else}}
<i class="material-icons">insert_drive_file</i>
{{- end}}
</div>
<div>
<span class="name">{{.Name}}</span>
{{- if .IsDir}}
<p data-order="-1">&mdash;</p>
{{- else}}
<p data-order="{{.Size}}">{{.HumanSize}}</p>
{{- end}}
<p>
<time datetime="{{.HumanModTime "2006-01-02T15:04:05Z"}}">{{.HumanModTime "2 Jan 2006 03:04 PM"}}</time>
</p>
<div>
<div class="item header">
<div>
</div>
<div>
<span class="name">Name</span>
<p>Size</p>
<p>Modified time</p>
</div>
</div>
</div>
{{ end }}
{{- end}}
<h2>Folders</h2>
<div>
{{- range .Items}}
{{ if and (.UserAllowed) (.IsDir) }}
{{ template "item" .}}
{{ end }}
{{- end}}
</div>
<h2>Files</h2>
<div>
{{- range .Items}}
{{ if and (.UserAllowed) (not .IsDir) }}
{{ template "item" .}}
{{ end }}
{{- end}}
</div>
</div>
</div>
<input style="display:none" type="file" id="upload-input" onchange="handleFiles(this.files, '')" value="Upload" multiple>
{{ end }}
{{ end }}
{{ define "item" }}
<div ondragstart="itemDragStart(event)"
{{ if .IsDir}}ondragover="itemDragOver(event)" ondrop="itemDrop(event)"{{ end }}
draggable="true"
class="item"
onclick="selectItemEvent(event)"
ondblclick="openItemEvent(event)"
data-dir="{{ .IsDir }}"
data-url="{{ .URL }}"
id="{{ EncodeBase64 .Name }}">
<div>
{{- if .IsDir}}
<i class="material-icons">folder</i>
{{- else}}
{{ if eq .Type "image" }}
<i class="material-icons">insert_photo</i>
{{ else if eq .Type "audio" }}
<i class="material-icons">volume_up</i>
{{ else if eq .Type "video" }}
<i class="material-icons">movie</i>
{{ else }}
<i class="material-icons">insert_drive_file</i>
{{ end }}
{{- end}}
</div>
<div>
<span class="name">{{.Name}}</span>
{{- if .IsDir}}
<p data-order="-1">&mdash;</p>
{{- else}}
<p data-order="{{.Size}}">{{.HumanSize}}</p>
{{- end}}
<p>
<time datetime="{{.HumanModTime "2006-01-02T15:04:05Z"}}">{{.HumanModTime "2 Jan 2006 03:04 PM"}}</time>
</p>
</div>
</div>
{{ end }}

View File

@ -67,11 +67,15 @@ func GetListing(u *config.User, filePath string, baseURL string) (*Listing, erro
// Absolute URL
url := url.URL{Path: baseURL + name}
fileinfos = append(fileinfos, Info{
i := Info{
FileInfo: f,
URL: url.String(),
UserAllowed: u.Allowed(filePath),
})
UserAllowed: u.Allowed("/" + name),
}
i.RetrieveFileType()
fileinfos = append(fileinfos, i)
}
return &Listing{

View File

@ -31,7 +31,7 @@ func ServeListing(w http.ResponseWriter, r *http.Request, c *config.Config, u *c
// Copy the query values into the Listing struct
var limit int
listing.Sort, listing.Order, limit, err = handleSortOrder(w, r, c.Scope)
listing.Sort, listing.Order, limit, err = handleSortOrder(w, r, c.BaseURL)
if err != nil {
return http.StatusBadRequest, err
}

View File

@ -32,10 +32,16 @@ type Info struct {
Token string
}
// BreadcrumbMapItem ...
type BreadcrumbMapItem struct {
Name string
URL string
}
// BreadcrumbMap returns p.Path where every element is a map
// of URLs and path segment names.
func (i Info) BreadcrumbMap() map[string]string {
result := map[string]string{}
func (i Info) BreadcrumbMap() []BreadcrumbMapItem {
result := []BreadcrumbMapItem{}
if len(i.Path) == 0 {
return result
@ -54,11 +60,17 @@ func (i Info) BreadcrumbMap() map[string]string {
}
if i == 0 && part == "" {
// Leading slash (root)
result["/"] = "/"
result = append([]BreadcrumbMapItem{{
Name: "/",
URL: "/",
}}, result...)
continue
}
result[strings.Join(parts[:i+1], "/")] = part
result = append([]BreadcrumbMapItem{{
Name: part,
URL: strings.Join(parts[:i+1], "/"),
}}, result...)
}
return result