@@ -7,39 +7,85 @@ import (
77 "net/http"
88 "path"
99 "regexp"
10+ "sort"
11+ "strconv"
1012 "strings"
1113 "time"
1214
1315 "github.com/minio/minio-go/v7"
1416)
1517
18+ // objectWithIcon represents an S3 object with additional display properties
19+ type objectWithIcon struct {
20+ Key string
21+ Size int64
22+ LastModified time.Time
23+ Owner string
24+ Icon string
25+ IsFolder bool
26+ DisplayName string
27+ }
28+
1629// HandleBucketView shows the details page of a bucket.
1730func HandleBucketView (s3 S3 , templates fs.FS , allowDelete bool , listRecursive bool , rootURL string ) http.HandlerFunc {
18- type objectWithIcon struct {
19- Key string
20- Size int64
21- LastModified time.Time
22- Owner string
23- Icon string
24- IsFolder bool
25- DisplayName string
26- }
27-
2831 type pageData struct {
29- RootURL string
30- BucketName string
31- Objects []objectWithIcon
32- AllowDelete bool
33- Paths []string
34- CurrentPath string
32+ RootURL string
33+ BucketName string
34+ Objects []objectWithIcon
35+ AllowDelete bool
36+ Paths []string
37+ CurrentPath string
38+ CurrentS3 * S3Instance
39+ S3Instances []* S3Instance
40+ HasError bool
41+ ErrorMessage string
42+ SortBy string
43+ SortOrder string
44+ Page int
45+ PerPage int
46+ TotalItems int
47+ TotalPages int
48+ HasPrevPage bool
49+ HasNextPage bool
50+ Search string
3551 }
3652
3753 return func (w http.ResponseWriter , r * http.Request ) {
3854 regex := regexp .MustCompile (`\/buckets\/([^\/]*)\/?(.*)` )
39- matches := regex .FindStringSubmatch (r .RequestURI )
55+ matches := regex .FindStringSubmatch (r .URL . Path )
4056 bucketName := matches [1 ]
4157 path := matches [2 ]
4258
59+ // Get sorting parameters from query string
60+ sortBy := r .URL .Query ().Get ("sortBy" )
61+ sortOrder := r .URL .Query ().Get ("sortOrder" )
62+
63+ // Default sorting
64+ if sortBy == "" {
65+ sortBy = "key"
66+ }
67+ if sortOrder == "" {
68+ sortOrder = "asc"
69+ }
70+
71+ // Get pagination parameters
72+ page := 1
73+ if pageStr := r .URL .Query ().Get ("page" ); pageStr != "" {
74+ if p , err := strconv .Atoi (pageStr ); err == nil && p > 0 {
75+ page = p
76+ }
77+ }
78+
79+ perPage := 25
80+ if perPageStr := r .URL .Query ().Get ("perPage" ); perPageStr != "" {
81+ if pp , err := strconv .Atoi (perPageStr ); err == nil && pp > 0 {
82+ perPage = pp
83+ }
84+ }
85+
86+ // Get search parameter
87+ search := strings .TrimSpace (r .URL .Query ().Get ("search" ))
88+
4389 var objs []objectWithIcon
4490 opts := minio.ListObjectsOptions {
4591 Recursive : listRecursive ,
@@ -63,16 +109,91 @@ func HandleBucketView(s3 S3, templates fs.FS, allowDelete bool, listRecursive bo
63109 }
64110 objs = append (objs , obj )
65111 }
112+
113+ // Filter objects based on search query
114+ if search != "" {
115+ searchLower := strings .ToLower (search )
116+ filteredObjs := make ([]objectWithIcon , 0 )
117+ for _ , obj := range objs {
118+ // Search in DisplayName and Key (case-insensitive)
119+ if strings .Contains (strings .ToLower (obj .DisplayName ), searchLower ) ||
120+ strings .Contains (strings .ToLower (obj .Key ), searchLower ) {
121+ filteredObjs = append (filteredObjs , obj )
122+ }
123+ }
124+ objs = filteredObjs
125+ }
126+
127+ // Sort objects based on sortBy and sortOrder
128+ sortObjects (objs , sortBy , sortOrder )
129+
130+ // Calculate pagination
131+ totalItems := len (objs )
132+ totalPages := (totalItems + perPage - 1 ) / perPage
133+ if totalPages == 0 {
134+ totalPages = 1
135+ }
136+ if page > totalPages {
137+ page = totalPages
138+ }
139+
140+ // Paginate objects
141+ start := (page - 1 ) * perPage
142+ end := start + perPage
143+ if start < 0 {
144+ start = 0
145+ }
146+ if end > totalItems {
147+ end = totalItems
148+ }
149+ if start < totalItems {
150+ objs = objs [start :end ]
151+ } else {
152+ objs = []objectWithIcon {}
153+ }
154+
66155 data := pageData {
67- RootURL : rootURL ,
68- BucketName : bucketName ,
69- Objects : objs ,
70- AllowDelete : allowDelete ,
71- Paths : removeEmptyStrings (strings .Split (path , "/" )),
72- CurrentPath : path ,
156+ RootURL : rootURL ,
157+ BucketName : bucketName ,
158+ Objects : objs ,
159+ AllowDelete : allowDelete ,
160+ Paths : removeEmptyStrings (strings .Split (path , "/" )),
161+ CurrentPath : path ,
162+ CurrentS3 : nil ,
163+ S3Instances : nil ,
164+ HasError : false ,
165+ ErrorMessage : "" ,
166+ SortBy : sortBy ,
167+ SortOrder : sortOrder ,
168+ Page : page ,
169+ PerPage : perPage ,
170+ TotalItems : totalItems ,
171+ TotalPages : totalPages ,
172+ HasPrevPage : page > 1 ,
173+ HasNextPage : page < totalPages ,
174+ Search : search ,
175+ }
176+
177+ funcMap := template.FuncMap {
178+ "add" : func (a , b int ) int { return a + b },
179+ "sub" : func (a , b int ) int { return a - b },
180+ "mul" : func (a , b int ) int { return a * b },
181+ "min" : func (a , b int ) int {
182+ if a < b {
183+ return a
184+ }
185+ return b
186+ },
187+ "iterate" : func (start , end int ) []int {
188+ result := make ([]int , 0 , end - start )
189+ for i := start ; i < end ; i ++ {
190+ result = append (result , i )
191+ }
192+ return result
193+ },
73194 }
74195
75- t , err := template .ParseFS (templates , "layout.html.tmpl" , "bucket.html.tmpl" )
196+ t , err := template .New ( "" ). Funcs ( funcMap ). ParseFS (templates , "layout.html.tmpl" , "bucket.html.tmpl" )
76197 if err != nil {
77198 handleHTTPError (w , fmt .Errorf ("error parsing template files: %w" , err ))
78199 return
@@ -114,3 +235,27 @@ func removeEmptyStrings(input []string) []string {
114235 }
115236 return result
116237}
238+
239+ // sortObjects sorts the objects based on the specified field and order
240+ func sortObjects (objs []objectWithIcon , sortBy , sortOrder string ) {
241+ sort .Slice (objs , func (i , j int ) bool {
242+ var less bool
243+ switch sortBy {
244+ case "size" :
245+ less = objs [i ].Size < objs [j ].Size
246+ case "owner" :
247+ less = strings .ToLower (objs [i ].Owner ) < strings .ToLower (objs [j ].Owner )
248+ case "lastModified" :
249+ less = objs [i ].LastModified .Before (objs [j ].LastModified )
250+ case "key" :
251+ fallthrough
252+ default :
253+ less = strings .ToLower (objs [i ].DisplayName ) < strings .ToLower (objs [j ].DisplayName )
254+ }
255+
256+ if sortOrder == "desc" {
257+ return ! less
258+ }
259+ return less
260+ })
261+ }
0 commit comments