Commit 464ade1d authored by Toby Allen's avatar Toby Allen Committed by GitHub

Add new browse sort - namedirfirst (#1551)

* Revert "browse: sort listing by dir first (#1527)"

 commit 4e1229e7.

* Add new browse sort order  namedirfirst. Make namedirfirst default sort
parent ce47cf51
...@@ -16,6 +16,4 @@ Caddyfile ...@@ -16,6 +16,4 @@ Caddyfile
og_static/ og_static/
.vscode/ .vscode/
\ No newline at end of file
caddyhttp/browse/temp*
\ No newline at end of file
...@@ -21,9 +21,10 @@ import ( ...@@ -21,9 +21,10 @@ import (
) )
const ( const (
sortByName = "name" sortByName = "name"
sortBySize = "size" sortByNameDirFirst = "namedirfirst"
sortByTime = "time" sortBySize = "size"
sortByTime = "time"
) )
// Browse is an http.Handler that can show a file listing when // Browse is an http.Handler that can show a file listing when
...@@ -128,6 +129,7 @@ func (fi FileInfo) HumanModTime(format string) string { ...@@ -128,6 +129,7 @@ func (fi FileInfo) HumanModTime(format string) string {
// Implement sorting for Listing // Implement sorting for Listing
type byName Listing type byName Listing
type byNameDirFirst Listing
type bySize Listing type bySize Listing
type byTime Listing type byTime Listing
...@@ -137,6 +139,15 @@ func (l byName) Swap(i, j int) { l.Items[i], l.Items[j] = l.Items[j], l.Items[i] ...@@ -137,6 +139,15 @@ func (l byName) Swap(i, j int) { l.Items[i], l.Items[j] = l.Items[j], l.Items[i]
// Treat upper and lower case equally // Treat upper and lower case equally
func (l byName) Less(i, j int) bool { func (l byName) Less(i, j int) bool {
return strings.ToLower(l.Items[i].Name) < strings.ToLower(l.Items[j].Name)
}
// By Name Dir First
func (l byNameDirFirst) Len() int { return len(l.Items) }
func (l byNameDirFirst) Swap(i, j int) { l.Items[i], l.Items[j] = l.Items[j], l.Items[i] }
// Treat upper and lower case equally
func (l byNameDirFirst) Less(i, j int) bool {
// if both are dir or file sort normally // if both are dir or file sort normally
if l.Items[i].IsDir == l.Items[j].IsDir { if l.Items[i].IsDir == l.Items[j].IsDir {
...@@ -176,6 +187,8 @@ func (l Listing) applySort() { ...@@ -176,6 +187,8 @@ func (l Listing) applySort() {
switch l.Sort { switch l.Sort {
case sortByName: case sortByName:
sort.Sort(sort.Reverse(byName(l))) sort.Sort(sort.Reverse(byName(l)))
case sortByNameDirFirst:
sort.Sort(sort.Reverse(byNameDirFirst(l)))
case sortBySize: case sortBySize:
sort.Sort(sort.Reverse(bySize(l))) sort.Sort(sort.Reverse(bySize(l)))
case sortByTime: case sortByTime:
...@@ -188,6 +201,8 @@ func (l Listing) applySort() { ...@@ -188,6 +201,8 @@ func (l Listing) applySort() {
switch l.Sort { switch l.Sort {
case sortByName: case sortByName:
sort.Sort(byName(l)) sort.Sort(byName(l))
case sortByNameDirFirst:
sort.Sort(byNameDirFirst(l))
case sortBySize: case sortBySize:
sort.Sort(bySize(l)) sort.Sort(bySize(l))
case sortByTime: case sortByTime:
...@@ -345,11 +360,11 @@ func (b Browse) handleSortOrder(w http.ResponseWriter, r *http.Request, scope st ...@@ -345,11 +360,11 @@ func (b Browse) handleSortOrder(w http.ResponseWriter, r *http.Request, scope st
// If the query 'sort' or 'order' is empty, use defaults or any values previously saved in Cookies // If the query 'sort' or 'order' is empty, use defaults or any values previously saved in Cookies
switch sort { switch sort {
case "": case "":
sort = sortByName sort = sortByNameDirFirst
if sortCookie, sortErr := r.Cookie("sort"); sortErr == nil { if sortCookie, sortErr := r.Cookie("sort"); sortErr == nil {
sort = sortCookie.Value sort = sortCookie.Value
} }
case sortByName, sortBySize, sortByTime: case sortByName, sortByNameDirFirst, sortBySize, sortByTime:
http.SetCookie(w, &http.Cookie{Name: "sort", Value: sort, Path: scope, Secure: r.TLS != nil}) http.SetCookie(w, &http.Cookie{Name: "sort", Value: sort, Path: scope, Secure: r.TLS != nil})
} }
......
...@@ -70,6 +70,13 @@ func TestSort(t *testing.T) { ...@@ -70,6 +70,13 @@ func TestSort(t *testing.T) {
t.Errorf("The listing isn't time sorted: %v", listing.Items) t.Errorf("The listing isn't time sorted: %v", listing.Items)
} }
// sort by name dir first
listing.Sort = "namedirfirst"
listing.applySort()
if !sort.IsSorted(byNameDirFirst(listing)) {
t.Errorf("The listing isn't namedirfirst sorted: %v", listing.Items)
}
// reverse by name // reverse by name
listing.Sort = "name" listing.Sort = "name"
listing.Order = "desc" listing.Order = "desc"
...@@ -93,6 +100,14 @@ func TestSort(t *testing.T) { ...@@ -93,6 +100,14 @@ func TestSort(t *testing.T) {
if !isReversed(byTime(listing)) { if !isReversed(byTime(listing)) {
t.Errorf("The listing isn't reversed by time: %v", listing.Items) t.Errorf("The listing isn't reversed by time: %v", listing.Items)
} }
// reverse by name dir first
listing.Sort = "namedirfirst"
listing.Order = "desc"
listing.applySort()
if !isReversed(byNameDirFirst(listing)) {
t.Errorf("The listing isn't reversed by namedirfirst: %v", listing.Items)
}
} }
func TestBrowseHTTPMethods(t *testing.T) { func TestBrowseHTTPMethods(t *testing.T) {
...@@ -257,6 +272,9 @@ func TestBrowseJson(t *testing.T) { ...@@ -257,6 +272,9 @@ func TestBrowseJson(t *testing.T) {
Mode: f.Mode(), Mode: f.Mode(),
}) })
} }
// Test that sort=name returns correct listing.
listing := Listing{Items: fileinfos} // this listing will be used for validation inside the tests listing := Listing{Items: fileinfos} // this listing will be used for validation inside the tests
tests := []struct { tests := []struct {
...@@ -269,33 +287,33 @@ func TestBrowseJson(t *testing.T) { ...@@ -269,33 +287,33 @@ func TestBrowseJson(t *testing.T) {
}{ }{
//test case 1: testing for default sort and order and without the limit parameter, default sort is by name and the default order is ascending //test case 1: testing for default sort and order and without the limit parameter, default sort is by name and the default order is ascending
//without the limit query entire listing will be produced //without the limit query entire listing will be produced
{"/", "", "", -1, false, listing.Items}, {"/?sort=name", "", "", -1, false, listing.Items},
//test case 2: limit is set to 1, orderBy and sortBy is default //test case 2: limit is set to 1, orderBy and sortBy is default
{"/?limit=1", "", "", 1, false, listing.Items[:1]}, {"/?limit=1&sort=name", "", "", 1, false, listing.Items[:1]},
//test case 3 : if the listing request is bigger than total size of listing then it should return everything //test case 3 : if the listing request is bigger than total size of listing then it should return everything
{"/?limit=100000000", "", "", 100000000, false, listing.Items}, {"/?limit=100000000&sort=name", "", "", 100000000, false, listing.Items},
//test case 4 : testing for negative limit //test case 4 : testing for negative limit
{"/?limit=-1", "", "", -1, false, listing.Items}, {"/?limit=-1&sort=name", "", "", -1, false, listing.Items},
//test case 5 : testing with limit set to -1 and order set to descending //test case 5 : testing with limit set to -1 and order set to descending
{"/?limit=-1&order=desc", "", "desc", -1, false, listing.Items}, {"/?limit=-1&order=desc&sort=name", "", "desc", -1, false, listing.Items},
//test case 6 : testing with limit set to 2 and order set to descending //test case 6 : testing with limit set to 2 and order set to descending
{"/?limit=2&order=desc", "", "desc", 2, false, listing.Items}, {"/?limit=2&order=desc&sort=name", "", "desc", 2, false, listing.Items},
//test case 7 : testing with limit set to 3 and order set to descending //test case 7 : testing with limit set to 3 and order set to descending
{"/?limit=3&order=desc", "", "desc", 3, false, listing.Items}, {"/?limit=3&order=desc&sort=name", "", "desc", 3, false, listing.Items},
//test case 8 : testing with limit set to 3 and order set to ascending //test case 8 : testing with limit set to 3 and order set to ascending
{"/?limit=3&order=asc", "", "asc", 3, false, listing.Items}, {"/?limit=3&order=asc&sort=name", "", "asc", 3, false, listing.Items},
//test case 9 : testing with limit set to 1111111 and order set to ascending //test case 9 : testing with limit set to 1111111 and order set to ascending
{"/?limit=1111111&order=asc", "", "asc", 1111111, false, listing.Items}, {"/?limit=1111111&order=asc&sort=name", "", "asc", 1111111, false, listing.Items},
//test case 10 : testing with limit set to default and order set to ascending and sorting by size //test case 10 : testing with limit set to default and order set to ascending and sorting by size
{"/?order=asc&sort=size", "size", "asc", -1, false, listing.Items}, {"/?order=asc&sort=size&sort=name", "size", "asc", -1, false, listing.Items},
//test case 11 : testing with limit set to default and order set to ascending and sorting by last modified //test case 11 : testing with limit set to default and order set to ascending and sorting by last modified
{"/?order=asc&sort=time", "time", "asc", -1, false, listing.Items}, {"/?order=asc&sort=time&sort=name", "time", "asc", -1, false, listing.Items},
//test case 12 : testing with limit set to 1 and order set to ascending and sorting by last modified //test case 12 : testing with limit set to 1 and order set to ascending and sorting by last modified
{"/?order=asc&sort=time&limit=1", "time", "asc", 1, false, listing.Items}, {"/?order=asc&sort=time&limit=1&sort=name", "time", "asc", 1, false, listing.Items},
//test case 13 : testing with limit set to -100 and order set to ascending and sorting by last modified //test case 13 : testing with limit set to -100 and order set to ascending and sorting by last modified
{"/?order=asc&sort=time&limit=-100", "time", "asc", -100, false, listing.Items}, {"/?order=asc&sort=time&limit=-100&sort=name", "time", "asc", -100, false, listing.Items},
//test case 14 : testing with limit set to -100 and order set to ascending and sorting by size //test case 14 : testing with limit set to -100 and order set to ascending and sorting by size
{"/?order=asc&sort=size&limit=-100", "size", "asc", -100, false, listing.Items}, {"/?order=asc&sort=size&limit=-100&sort=name", "size", "asc", -100, false, listing.Items},
} }
for i, test := range tests { for i, test := range tests {
......
...@@ -342,12 +342,20 @@ footer { ...@@ -342,12 +342,20 @@ footer {
<thead> <thead>
<tr> <tr>
<th> <th>
{{- if and (eq .Sort "namedirfirst") (ne .Order "desc")}}
<a href="?sort=namedirfirst&order=desc{{if ne 0 .ItemsLimitedTo}}&limit={{.ItemsLimitedTo}}{{end}}">Name <svg width="1em" height=".4em" version="1.1" viewBox="0 0 12.922194 6.0358899"><use xlink:href="#up-arrow"></use></svg></a>
{{- else if and (eq .Sort "namedirfirst") (ne .Order "asc")}}
<a href="?sort=namedirfirst&order=asc{{if ne 0 .ItemsLimitedTo}}&limit={{.ItemsLimitedTo}}{{end}}">Name <svg width="1em" height=".4em" version="1.1" viewBox="0 0 12.922194 6.0358899"><use xlink:href="#down-arrow"></use></svg></a>
{{- else}}
<a href="?sort=namedirfirst&order=asc{{if ne 0 .ItemsLimitedTo}}&limit={{.ItemsLimitedTo}}{{end}}">Name</a>
{{- end}}
|
{{- if and (eq .Sort "name") (ne .Order "desc")}} {{- if and (eq .Sort "name") (ne .Order "desc")}}
<a href="?sort=name&order=desc{{if ne 0 .ItemsLimitedTo}}&limit={{.ItemsLimitedTo}}{{end}}">Name <svg width="1em" height=".4em" version="1.1" viewBox="0 0 12.922194 6.0358899"><use xlink:href="#up-arrow"></use></svg></a> <a href="?sort=name&order=desc{{if ne 0 .ItemsLimitedTo}}&limit={{.ItemsLimitedTo}}{{end}}">(a-z) <svg width="1em" height=".4em" version="1.1" viewBox="0 0 12.922194 6.0358899"><use xlink:href="#up-arrow"></use></svg></a>
{{- else if and (eq .Sort "name") (ne .Order "asc")}} {{- else if and (eq .Sort "name") (ne .Order "asc")}}
<a href="?sort=name&order=asc{{if ne 0 .ItemsLimitedTo}}&limit={{.ItemsLimitedTo}}{{end}}">Name <svg width="1em" height=".4em" version="1.1" viewBox="0 0 12.922194 6.0358899"><use xlink:href="#down-arrow"></use></svg></a> <a href="?sort=name&order=asc{{if ne 0 .ItemsLimitedTo}}&limit={{.ItemsLimitedTo}}{{end}}">(a-z) <svg width="1em" height=".4em" version="1.1" viewBox="0 0 12.922194 6.0358899"><use xlink:href="#down-arrow"></use></svg></a>
{{- else}} {{- else}}
<a href="?sort=name&order=asc{{if ne 0 .ItemsLimitedTo}}&limit={{.ItemsLimitedTo}}{{end}}">Name</a> <a href="?sort=name&order=asc{{if ne 0 .ItemsLimitedTo}}&limit={{.ItemsLimitedTo}}{{end}}">(a-z)</a>
{{- end}} {{- end}}
</th> </th>
<th> <th>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment