templates.go 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. package master_ui
  2. import (
  3. "github.com/dustin/go-humanize"
  4. "html/template"
  5. "net/url"
  6. "strings"
  7. )
  8. func printpath(parts ...string) string {
  9. concat := strings.Join(parts, "")
  10. escaped := url.PathEscape(concat)
  11. return strings.ReplaceAll(escaped, "%2F", "/")
  12. }
  13. var funcMap = template.FuncMap{
  14. "humanizeBytes": humanize.Bytes,
  15. "printpath": printpath,
  16. }
  17. var StatusTpl = template.Must(template.New("status").Funcs(funcMap).Parse(`<!DOCTYPE html>
  18. <html>
  19. <head>
  20. <title>SeaweedFS Filer</title>
  21. <meta name="viewport" content="width=device-width, initial-scale=1">
  22. <link rel="stylesheet" href="/seaweedfsstatic/bootstrap/3.3.1/css/bootstrap.min.css">
  23. <style>
  24. body { padding-bottom: 128px; }
  25. #drop-area {
  26. border: 1px transparent;
  27. }
  28. #drop-area.highlight {
  29. border-color: purple;
  30. border: 2px dashed #ccc;
  31. }
  32. .button {
  33. display: inline-block;
  34. padding: 2px;
  35. background: #ccc;
  36. cursor: pointer;
  37. border-radius: 2px;
  38. border: 1px solid #ccc;
  39. float: right;
  40. }
  41. .button:hover {
  42. background: #ddd;
  43. }
  44. #fileElem {
  45. display: none;
  46. }
  47. .qrImage {
  48. display: block;
  49. margin-left: auto;
  50. margin-right: auto;
  51. }
  52. </style>
  53. </head>
  54. <body>
  55. <div class="container">
  56. <div class="page-header">
  57. <h1>
  58. <a href="https://github.com/chrislusf/seaweedfs"><img src="/seaweedfsstatic/seaweed50x50.png"></img></a>
  59. SeaweedFS Filer
  60. </h1>
  61. </div>
  62. <div class="row">
  63. <div>
  64. {{ range $entry := .Breadcrumbs }}
  65. <a href="{{ printpath $entry.Link }}" >
  66. {{ $entry.Name }}
  67. </a>
  68. {{ end }}
  69. <label class="button" for="fileElem">Upload</label>
  70. </div>
  71. </div>
  72. <div class="row" id="drop-area">
  73. <form class="upload-form">
  74. <input type="file" id="fileElem" multiple onchange="handleFiles(this.files)">
  75. <table width="90%">
  76. {{$path := .Path }}
  77. {{ range $entry_index, $entry := .Entries }}
  78. <tr>
  79. <td>
  80. {{if $entry.IsDirectory}}
  81. <img src="/seaweedfsstatic/images/folder.gif" width="20" height="23">
  82. <a href="{{ printpath $path "/" $entry.Name "/"}}" >
  83. {{ $entry.Name }}
  84. </a>
  85. {{else}}
  86. <a href="{{ printpath $path "/" $entry.Name }}" >
  87. {{ $entry.Name }}
  88. </a>
  89. {{end}}
  90. </td>
  91. <td align="right" nowrap>
  92. {{if $entry.IsDirectory}}
  93. {{else}}
  94. {{ $entry.Mime }}&nbsp;
  95. {{end}}
  96. </td>
  97. <td align="right" nowrap>
  98. {{if $entry.IsDirectory}}
  99. {{else}}
  100. {{ $entry.Size | humanizeBytes }}&nbsp;
  101. {{end}}
  102. </td>
  103. <td nowrap>
  104. {{ $entry.Timestamp.Format "2006-01-02 15:04" }}
  105. </td>
  106. </tr>
  107. {{ end }}
  108. </table>
  109. </form>
  110. </div>
  111. {{if .ShouldDisplayLoadMore}}
  112. <div class="row">
  113. <a href={{ print .Path "?limit=" .Limit "&lastFileName=" .LastFileName}} >
  114. Load more
  115. </a>
  116. </div>
  117. {{end}}
  118. <br/>
  119. <br/>
  120. <div class="navbar navbar-fixed-bottom">
  121. <img src="data:image/png;base64,{{.QrImage}}" class="qrImage" />
  122. </div>
  123. </div>
  124. </body>
  125. <script type="text/javascript">
  126. // ************************ Drag and drop ***************** //
  127. let dropArea = document.getElementById("drop-area")
  128. // Prevent default drag behaviors
  129. ;['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
  130. dropArea.addEventListener(eventName, preventDefaults, false)
  131. document.body.addEventListener(eventName, preventDefaults, false)
  132. })
  133. // Highlight drop area when item is dragged over it
  134. ;['dragenter', 'dragover'].forEach(eventName => {
  135. dropArea.addEventListener(eventName, highlight, false)
  136. })
  137. ;['dragleave', 'drop'].forEach(eventName => {
  138. dropArea.addEventListener(eventName, unhighlight, false)
  139. })
  140. // Handle dropped files
  141. dropArea.addEventListener('drop', handleDrop, false)
  142. function preventDefaults (e) {
  143. e.preventDefault()
  144. e.stopPropagation()
  145. }
  146. function highlight(e) {
  147. dropArea.classList.add('highlight')
  148. }
  149. function unhighlight(e) {
  150. dropArea.classList.remove('highlight')
  151. }
  152. function handleDrop(e) {
  153. var dt = e.dataTransfer
  154. var files = dt.files
  155. handleFiles(files)
  156. }
  157. function handleFiles(files) {
  158. files = [...files]
  159. files.forEach(uploadFile)
  160. window.location.reload()
  161. }
  162. function uploadFile(file, i) {
  163. var url = window.location.href
  164. var xhr = new XMLHttpRequest()
  165. var formData = new FormData()
  166. xhr.open('POST', url, false)
  167. formData.append('file', file)
  168. xhr.send(formData)
  169. }
  170. </script>
  171. </html>
  172. `))