mirror of
				https://github.com/caddyserver/caddy.git
				synced 2025-11-03 19:17:29 -05:00 
			
		
		
		
	Add new browse sort - namedirfirst (#1551)
* Revert "browse: sort listing by dir first (#1527)" commit 4e1229e7c9bd5643ed079f3dafa25df4e426da56. * Add new browse sort order namedirfirst. Make namedirfirst default sort
This commit is contained in:
		
							parent
							
								
									ce47cf51be
								
							
						
					
					
						commit
						464ade1da7
					
				
							
								
								
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@ -17,5 +17,3 @@ Caddyfile
 | 
			
		||||
og_static/
 | 
			
		||||
 | 
			
		||||
.vscode/
 | 
			
		||||
 | 
			
		||||
caddyhttp/browse/temp*
 | 
			
		||||
@ -22,6 +22,7 @@ import (
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	sortByName         = "name"
 | 
			
		||||
	sortByNameDirFirst = "namedirfirst"
 | 
			
		||||
	sortBySize         = "size"
 | 
			
		||||
	sortByTime         = "time"
 | 
			
		||||
)
 | 
			
		||||
@ -128,6 +129,7 @@ func (fi FileInfo) HumanModTime(format string) string {
 | 
			
		||||
 | 
			
		||||
// Implement sorting for Listing
 | 
			
		||||
type byName Listing
 | 
			
		||||
type byNameDirFirst Listing
 | 
			
		||||
type bySize 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]
 | 
			
		||||
 | 
			
		||||
// Treat upper and lower case equally
 | 
			
		||||
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 l.Items[i].IsDir == l.Items[j].IsDir {
 | 
			
		||||
@ -176,6 +187,8 @@ func (l Listing) applySort() {
 | 
			
		||||
		switch l.Sort {
 | 
			
		||||
		case sortByName:
 | 
			
		||||
			sort.Sort(sort.Reverse(byName(l)))
 | 
			
		||||
		case sortByNameDirFirst:
 | 
			
		||||
			sort.Sort(sort.Reverse(byNameDirFirst(l)))
 | 
			
		||||
		case sortBySize:
 | 
			
		||||
			sort.Sort(sort.Reverse(bySize(l)))
 | 
			
		||||
		case sortByTime:
 | 
			
		||||
@ -188,6 +201,8 @@ func (l Listing) applySort() {
 | 
			
		||||
		switch l.Sort {
 | 
			
		||||
		case sortByName:
 | 
			
		||||
			sort.Sort(byName(l))
 | 
			
		||||
		case sortByNameDirFirst:
 | 
			
		||||
			sort.Sort(byNameDirFirst(l))
 | 
			
		||||
		case sortBySize:
 | 
			
		||||
			sort.Sort(bySize(l))
 | 
			
		||||
		case sortByTime:
 | 
			
		||||
@ -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
 | 
			
		||||
	switch sort {
 | 
			
		||||
	case "":
 | 
			
		||||
		sort = sortByName
 | 
			
		||||
		sort = sortByNameDirFirst
 | 
			
		||||
		if sortCookie, sortErr := r.Cookie("sort"); sortErr == nil {
 | 
			
		||||
			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})
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -70,6 +70,13 @@ func TestSort(t *testing.T) {
 | 
			
		||||
		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
 | 
			
		||||
	listing.Sort = "name"
 | 
			
		||||
	listing.Order = "desc"
 | 
			
		||||
@ -93,6 +100,14 @@ func TestSort(t *testing.T) {
 | 
			
		||||
	if !isReversed(byTime(listing)) {
 | 
			
		||||
		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) {
 | 
			
		||||
@ -257,6 +272,9 @@ func TestBrowseJson(t *testing.T) {
 | 
			
		||||
			Mode:    f.Mode(),
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Test that sort=name returns correct listing.
 | 
			
		||||
 | 
			
		||||
	listing := Listing{Items: fileinfos} // this listing will be used for validation inside the tests
 | 
			
		||||
 | 
			
		||||
	tests := []struct {
 | 
			
		||||
@ -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
 | 
			
		||||
		//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
 | 
			
		||||
		{"/?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
 | 
			
		||||
		{"/?limit=100000000", "", "", 100000000, false, listing.Items},
 | 
			
		||||
		{"/?limit=100000000&sort=name", "", "", 100000000, false, listing.Items},
 | 
			
		||||
		//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
 | 
			
		||||
		{"/?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
 | 
			
		||||
		{"/?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
 | 
			
		||||
		{"/?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
 | 
			
		||||
		{"/?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
 | 
			
		||||
		{"/?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
 | 
			
		||||
		{"/?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
 | 
			
		||||
		{"/?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
 | 
			
		||||
		{"/?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
 | 
			
		||||
		{"/?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
 | 
			
		||||
		{"/?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 {
 | 
			
		||||
 | 
			
		||||
@ -342,12 +342,20 @@ footer {
 | 
			
		||||
					<thead>
 | 
			
		||||
					<tr>
 | 
			
		||||
						<th>
 | 
			
		||||
							{{- 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>
 | 
			
		||||
							{{- 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>
 | 
			
		||||
							{{- 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=name&order=asc{{if ne 0 .ItemsLimitedTo}}&limit={{.ItemsLimitedTo}}{{end}}">Name</a>
 | 
			
		||||
							<a href="?sort=namedirfirst&order=asc{{if ne 0 .ItemsLimitedTo}}&limit={{.ItemsLimitedTo}}{{end}}">Name</a>
 | 
			
		||||
							{{- end}}
 | 
			
		||||
							|
 | 
			
		||||
							{{- if and (eq .Sort "name") (ne .Order "desc")}}
 | 
			
		||||
							<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")}}
 | 
			
		||||
							<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}}
 | 
			
		||||
							<a href="?sort=name&order=asc{{if ne 0 .ItemsLimitedTo}}&limit={{.ItemsLimitedTo}}{{end}}">(a-z)</a>
 | 
			
		||||
							{{- end}}
 | 
			
		||||
						</th>
 | 
			
		||||
						<th>
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user