| 1 | {{define "browse.html"}}{{template "base.html" .}}{{end}} |
| 2 | {{define "title"}}{{.Bucket}}/{{.Prefix}}{{end}} |
| 3 | {{define "content"}} |
| 4 | <nav class="crumbs"> |
| 5 | <a href="/buckets">buckets</a> |
| 6 | {{range .Crumbs}}<span class="crumb-sep">/</span><a href="{{.Href}}">{{.Label}}</a>{{end}} |
| 7 | <span class="crumb-sep">/</span> |
| 8 | </nav> |
| 9 | |
| 10 | {{if .Error}}<p class="error">{{.Error}}</p>{{end}} |
| 11 | {{if .Success}}<p class="success">{{.Success}}</p>{{end}} |
| 12 | |
| 13 | <div class="search-row"> |
| 14 | <input type="search" id="filter" placeholder="filter folders + files in this view…" autocomplete="off"> |
| 15 | <span class="filter-count" id="filter-count"></span> |
| 16 | </div> |
| 17 | |
| 18 | <div class="actions-row"> |
| 19 | <form method="POST" action="/b/{{.Bucket}}/upload" enctype="multipart/form-data" class="form inline-actions"> |
| 20 | <input type="hidden" name="prefix" value="{{.Prefix}}"> |
| 21 | <label for="file">upload (max {{.MaxUploadMB}}MB, multiple allowed)</label> |
| 22 | <input type="file" id="file" name="file" multiple required> |
| 23 | <button type="submit">upload</button> |
| 24 | </form> |
| 25 | |
| 26 | <form method="POST" action="/b/{{.Bucket}}/mkdir" class="form inline-actions"> |
| 27 | <input type="hidden" name="prefix" value="{{.Prefix}}"> |
| 28 | <label for="name">new folder</label> |
| 29 | <input type="text" id="name" name="name" placeholder="folder-name" required> |
| 30 | <button type="submit">create</button> |
| 31 | </form> |
| 32 | </div> |
| 33 | |
| 34 | {{if and (not .Folders) (not .Files) (not .ParentHref)}} |
| 35 | <p class="empty">empty bucket</p> |
| 36 | {{end}} |
| 37 | |
| 38 | <div class="admin-list" id="entry-list"> |
| 39 | {{if .ParentHref}} |
| 40 | <a href="{{.ParentHref}}" class="admin-list-item" data-parent="1"> |
| 41 | <div class="admin-list-info"> |
| 42 | <span class="admin-list-title">../</span> |
| 43 | </div> |
| 44 | </a> |
| 45 | {{end}} |
| 46 | {{range .Folders}} |
| 47 | <a href="{{.Href}}" class="admin-list-item" data-name="{{.Name}}"> |
| 48 | <div class="admin-list-info"> |
| 49 | <span class="admin-list-title">{{.Name}}/</span> |
| 50 | </div> |
| 51 | </a> |
| 52 | {{end}} |
| 53 | {{range .Files}} |
| 54 | <a href="{{.DetailHref}}" class="admin-list-item" data-name="{{.Name}}"> |
| 55 | {{if .IsImage}}<img src="{{.PreviewSrc}}" class="file-thumbnail" alt="{{.Name}}" loading="lazy">{{end}} |
| 56 | <div class="admin-list-info"> |
| 57 | <span class="admin-list-title">{{.Name}}</span> |
| 58 | <div class="admin-list-meta"> |
| 59 | <span class="admin-list-date">{{.SizeHuman}}</span> |
| 60 | <span class="admin-list-date">{{.LastModified}}</span> |
| 61 | </div> |
| 62 | </div> |
| 63 | </a> |
| 64 | {{end}} |
| 65 | </div> |
| 66 | |
| 67 | <script> |
| 68 | (function () { |
| 69 | var input = document.getElementById('filter'); |
| 70 | var list = document.getElementById('entry-list'); |
| 71 | var count = document.getElementById('filter-count'); |
| 72 | if (!input || !list) return; |
| 73 | var items = list.querySelectorAll('.admin-list-item[data-name]'); |
| 74 | var total = items.length; |
| 75 | function apply() { |
| 76 | var q = input.value.trim().toLowerCase(); |
| 77 | var shown = 0; |
| 78 | items.forEach(function (el) { |
| 79 | var name = (el.getAttribute('data-name') || '').toLowerCase(); |
| 80 | var match = q === '' || name.indexOf(q) !== -1; |
| 81 | el.style.display = match ? '' : 'none'; |
| 82 | if (match) shown++; |
| 83 | }); |
| 84 | count.textContent = q ? shown + ' / ' + total : ''; |
| 85 | } |
| 86 | input.addEventListener('input', apply); |
| 87 | })(); |
| 88 | </script> |
| 89 | {{end}} |