mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2024-01-19 02:48:24 +00:00
extract embed html of master/volume/filer ui to separate files
This commit is contained in:
parent
5dbbe19c8b
commit
44a2538f67
182
weed/server/filer_ui/filer.html
Normal file
182
weed/server/filer_ui/filer.html
Normal file
|
@ -0,0 +1,182 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>SeaweedFS Filer</title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<link rel="stylesheet" href="/seaweedfsstatic/bootstrap/3.3.1/css/bootstrap.min.css">
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
padding-bottom: 128px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#drop-area {
|
||||||
|
border: 1px transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
#drop-area.highlight {
|
||||||
|
border-color: purple;
|
||||||
|
border: 2px dashed #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 2px;
|
||||||
|
background: #ccc;
|
||||||
|
cursor: pointer;
|
||||||
|
border-radius: 2px;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button:hover {
|
||||||
|
background: #ddd;
|
||||||
|
}
|
||||||
|
|
||||||
|
#fileElem {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qrImage {
|
||||||
|
display: block;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<div class="page-header">
|
||||||
|
<h1>
|
||||||
|
<a href="https://github.com/chrislusf/seaweedfs"><img src="/seaweedfsstatic/seaweed50x50.png"></img></a>
|
||||||
|
SeaweedFS Filer
|
||||||
|
</h1>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div>
|
||||||
|
{{ range $entry := .Breadcrumbs }}
|
||||||
|
<a href="{{ printpath $entry.Link }}">
|
||||||
|
{{ $entry.Name }}
|
||||||
|
</a>
|
||||||
|
{{ end }}
|
||||||
|
<label class="button" for="fileElem">Upload</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row" id="drop-area">
|
||||||
|
<form class="upload-form">
|
||||||
|
<input type="file" id="fileElem" multiple onchange="handleFiles(this.files)">
|
||||||
|
|
||||||
|
<table width="90%">
|
||||||
|
{{$path := .Path }}
|
||||||
|
{{ range $entry_index, $entry := .Entries }}
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
{{if $entry.IsDirectory}}
|
||||||
|
<img src="/seaweedfsstatic/images/folder.gif" width="20" height="23">
|
||||||
|
<a href="{{ printpath $path "/" $entry.Name "/"}}" >
|
||||||
|
{{ $entry.Name }}
|
||||||
|
</a>
|
||||||
|
{{else}}
|
||||||
|
<a href="{{ printpath $path "/" $entry.Name }}" >
|
||||||
|
{{ $entry.Name }}
|
||||||
|
</a>
|
||||||
|
{{end}}
|
||||||
|
</td>
|
||||||
|
<td align="right" nowrap>
|
||||||
|
{{if $entry.IsDirectory}}
|
||||||
|
{{else}}
|
||||||
|
{{ $entry.Mime }}
|
||||||
|
{{end}}
|
||||||
|
</td>
|
||||||
|
<td align="right" nowrap>
|
||||||
|
{{if $entry.IsDirectory}}
|
||||||
|
{{else}}
|
||||||
|
{{ $entry.Size | humanizeBytes }}
|
||||||
|
{{end}}
|
||||||
|
</td>
|
||||||
|
<td nowrap>
|
||||||
|
{{ $entry.Timestamp.Format "2006-01-02 15:04" }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
</table>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{if .ShouldDisplayLoadMore}}
|
||||||
|
<div class="row">
|
||||||
|
<a href={{ print .Path "?limit=" .Limit "&lastFileName=" .LastFileName}} >
|
||||||
|
Load more
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
{{end}}
|
||||||
|
|
||||||
|
<br/>
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
<div class="navbar navbar-fixed-bottom">
|
||||||
|
<img src="data:image/png;base64,{{.QrImage}}" class="qrImage"/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
<script type="text/javascript">
|
||||||
|
// ************************ Drag and drop ***************** //
|
||||||
|
let dropArea = document.getElementById("drop-area")
|
||||||
|
|
||||||
|
// Prevent default drag behaviors
|
||||||
|
;['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
|
||||||
|
dropArea.addEventListener(eventName, preventDefaults, false)
|
||||||
|
document.body.addEventListener(eventName, preventDefaults, false)
|
||||||
|
})
|
||||||
|
|
||||||
|
// Highlight drop area when item is dragged over it
|
||||||
|
;['dragenter', 'dragover'].forEach(eventName => {
|
||||||
|
dropArea.addEventListener(eventName, highlight, false)
|
||||||
|
})
|
||||||
|
|
||||||
|
;['dragleave', 'drop'].forEach(eventName => {
|
||||||
|
dropArea.addEventListener(eventName, unhighlight, false)
|
||||||
|
})
|
||||||
|
|
||||||
|
// Handle dropped files
|
||||||
|
dropArea.addEventListener('drop', handleDrop, false)
|
||||||
|
|
||||||
|
function preventDefaults(e) {
|
||||||
|
e.preventDefault()
|
||||||
|
e.stopPropagation()
|
||||||
|
}
|
||||||
|
|
||||||
|
function highlight(e) {
|
||||||
|
dropArea.classList.add('highlight')
|
||||||
|
}
|
||||||
|
|
||||||
|
function unhighlight(e) {
|
||||||
|
dropArea.classList.remove('highlight')
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleDrop(e) {
|
||||||
|
var dt = e.dataTransfer
|
||||||
|
var files = dt.files
|
||||||
|
|
||||||
|
handleFiles(files)
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleFiles(files) {
|
||||||
|
files = [...files]
|
||||||
|
files.forEach(uploadFile)
|
||||||
|
window.location.reload()
|
||||||
|
}
|
||||||
|
|
||||||
|
function uploadFile(file, i) {
|
||||||
|
var url = window.location.href
|
||||||
|
var xhr = new XMLHttpRequest()
|
||||||
|
var formData = new FormData()
|
||||||
|
xhr.open('POST', url, false)
|
||||||
|
|
||||||
|
formData.append('file', file)
|
||||||
|
xhr.send(formData)
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</html>
|
|
@ -1,6 +1,7 @@
|
||||||
package filer_ui
|
package filer_ui
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
_ "embed"
|
||||||
"github.com/dustin/go-humanize"
|
"github.com/dustin/go-humanize"
|
||||||
"html/template"
|
"html/template"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
@ -18,178 +19,7 @@ var funcMap = template.FuncMap{
|
||||||
"printpath": printpath,
|
"printpath": printpath,
|
||||||
}
|
}
|
||||||
|
|
||||||
var StatusTpl = template.Must(template.New("status").Funcs(funcMap).Parse(`<!DOCTYPE html>
|
//go:embed filer.html
|
||||||
<html>
|
var filerHtml string
|
||||||
<head>
|
|
||||||
<title>SeaweedFS Filer</title>
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
<link rel="stylesheet" href="/seaweedfsstatic/bootstrap/3.3.1/css/bootstrap.min.css">
|
|
||||||
<style>
|
|
||||||
body { padding-bottom: 128px; }
|
|
||||||
#drop-area {
|
|
||||||
border: 1px transparent;
|
|
||||||
}
|
|
||||||
#drop-area.highlight {
|
|
||||||
border-color: purple;
|
|
||||||
border: 2px dashed #ccc;
|
|
||||||
}
|
|
||||||
.button {
|
|
||||||
display: inline-block;
|
|
||||||
padding: 2px;
|
|
||||||
background: #ccc;
|
|
||||||
cursor: pointer;
|
|
||||||
border-radius: 2px;
|
|
||||||
border: 1px solid #ccc;
|
|
||||||
float: right;
|
|
||||||
}
|
|
||||||
.button:hover {
|
|
||||||
background: #ddd;
|
|
||||||
}
|
|
||||||
#fileElem {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
.qrImage {
|
|
||||||
display: block;
|
|
||||||
margin-left: auto;
|
|
||||||
margin-right: auto;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class="container">
|
|
||||||
<div class="page-header">
|
|
||||||
<h1>
|
|
||||||
<a href="https://github.com/chrislusf/seaweedfs"><img src="/seaweedfsstatic/seaweed50x50.png"></img></a>
|
|
||||||
SeaweedFS Filer
|
|
||||||
</h1>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<div>
|
|
||||||
{{ range $entry := .Breadcrumbs }}
|
|
||||||
<a href="{{ printpath $entry.Link }}" >
|
|
||||||
{{ $entry.Name }}
|
|
||||||
</a>
|
|
||||||
{{ end }}
|
|
||||||
<label class="button" for="fileElem">Upload</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="row" id="drop-area">
|
var StatusTpl = template.Must(template.New("status").Funcs(funcMap).Parse(filerHtml))
|
||||||
<form class="upload-form">
|
|
||||||
<input type="file" id="fileElem" multiple onchange="handleFiles(this.files)">
|
|
||||||
|
|
||||||
<table width="90%">
|
|
||||||
{{$path := .Path }}
|
|
||||||
{{ range $entry_index, $entry := .Entries }}
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
{{if $entry.IsDirectory}}
|
|
||||||
<img src="/seaweedfsstatic/images/folder.gif" width="20" height="23">
|
|
||||||
<a href="{{ printpath $path "/" $entry.Name "/"}}" >
|
|
||||||
{{ $entry.Name }}
|
|
||||||
</a>
|
|
||||||
{{else}}
|
|
||||||
<a href="{{ printpath $path "/" $entry.Name }}" >
|
|
||||||
{{ $entry.Name }}
|
|
||||||
</a>
|
|
||||||
{{end}}
|
|
||||||
</td>
|
|
||||||
<td align="right" nowrap>
|
|
||||||
{{if $entry.IsDirectory}}
|
|
||||||
{{else}}
|
|
||||||
{{ $entry.Mime }}
|
|
||||||
{{end}}
|
|
||||||
</td>
|
|
||||||
<td align="right" nowrap>
|
|
||||||
{{if $entry.IsDirectory}}
|
|
||||||
{{else}}
|
|
||||||
{{ $entry.Size | humanizeBytes }}
|
|
||||||
{{end}}
|
|
||||||
</td>
|
|
||||||
<td nowrap>
|
|
||||||
{{ $entry.Timestamp.Format "2006-01-02 15:04" }}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{{ end }}
|
|
||||||
|
|
||||||
</table>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{{if .ShouldDisplayLoadMore}}
|
|
||||||
<div class="row">
|
|
||||||
<a href={{ print .Path "?limit=" .Limit "&lastFileName=" .LastFileName}} >
|
|
||||||
Load more
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
{{end}}
|
|
||||||
|
|
||||||
<br/>
|
|
||||||
<br/>
|
|
||||||
|
|
||||||
<div class="navbar navbar-fixed-bottom">
|
|
||||||
<img src="data:image/png;base64,{{.QrImage}}" class="qrImage" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
<script type="text/javascript">
|
|
||||||
// ************************ Drag and drop ***************** //
|
|
||||||
let dropArea = document.getElementById("drop-area")
|
|
||||||
|
|
||||||
// Prevent default drag behaviors
|
|
||||||
;['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
|
|
||||||
dropArea.addEventListener(eventName, preventDefaults, false)
|
|
||||||
document.body.addEventListener(eventName, preventDefaults, false)
|
|
||||||
})
|
|
||||||
|
|
||||||
// Highlight drop area when item is dragged over it
|
|
||||||
;['dragenter', 'dragover'].forEach(eventName => {
|
|
||||||
dropArea.addEventListener(eventName, highlight, false)
|
|
||||||
})
|
|
||||||
|
|
||||||
;['dragleave', 'drop'].forEach(eventName => {
|
|
||||||
dropArea.addEventListener(eventName, unhighlight, false)
|
|
||||||
})
|
|
||||||
|
|
||||||
// Handle dropped files
|
|
||||||
dropArea.addEventListener('drop', handleDrop, false)
|
|
||||||
|
|
||||||
function preventDefaults (e) {
|
|
||||||
e.preventDefault()
|
|
||||||
e.stopPropagation()
|
|
||||||
}
|
|
||||||
|
|
||||||
function highlight(e) {
|
|
||||||
dropArea.classList.add('highlight')
|
|
||||||
}
|
|
||||||
|
|
||||||
function unhighlight(e) {
|
|
||||||
dropArea.classList.remove('highlight')
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleDrop(e) {
|
|
||||||
var dt = e.dataTransfer
|
|
||||||
var files = dt.files
|
|
||||||
|
|
||||||
handleFiles(files)
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleFiles(files) {
|
|
||||||
files = [...files]
|
|
||||||
files.forEach(uploadFile)
|
|
||||||
window.location.reload()
|
|
||||||
}
|
|
||||||
|
|
||||||
function uploadFile(file, i) {
|
|
||||||
var url = window.location.href
|
|
||||||
var xhr = new XMLHttpRequest()
|
|
||||||
var formData = new FormData()
|
|
||||||
xhr.open('POST', url, false)
|
|
||||||
|
|
||||||
formData.append('file', file)
|
|
||||||
xhr.send(formData)
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
</html>
|
|
||||||
`))
|
|
||||||
|
|
110
weed/server/master_ui/master.html
Normal file
110
weed/server/master_ui/master.html
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>SeaweedFS {{ .Version }}</title>
|
||||||
|
<link rel="stylesheet" href="/seaweedfsstatic/bootstrap/3.3.1/css/bootstrap.min.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<div class="page-header">
|
||||||
|
<h1>
|
||||||
|
<a href="https://github.com/chrislusf/seaweedfs"><img src="/seaweedfsstatic/seaweed50x50.png"></img></a>
|
||||||
|
SeaweedFS <small>{{ .Version }}</small>
|
||||||
|
</h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-6">
|
||||||
|
<h2>Cluster status</h2>
|
||||||
|
<table class="table table-condensed table-striped">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<th>Volume Size Limit</th>
|
||||||
|
<td>{{ .VolumeSizeLimitMB }}MB</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Free</th>
|
||||||
|
<td>{{ .Topology.Free }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Max</th>
|
||||||
|
<td>{{ .Topology.Max }}</td>
|
||||||
|
</tr>
|
||||||
|
{{ with .RaftServer }}
|
||||||
|
<tr>
|
||||||
|
<th>Leader</th>
|
||||||
|
<td><a href="http://{{ .Leader }}">{{ .Leader }}</a></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Other Masters</th>
|
||||||
|
<td class="col-sm-5">
|
||||||
|
<ul class="list-unstyled">
|
||||||
|
{{ range $k, $p := .Peers }}
|
||||||
|
<li><a href="http://{{ $p.Name }}/ui/index.html">{{ $p.Name }}</a></li>
|
||||||
|
{{ end }}
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{{ end }}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-sm-6">
|
||||||
|
<h2>System Stats</h2>
|
||||||
|
<table class="table table-condensed table-striped">
|
||||||
|
<tr>
|
||||||
|
<th>Concurrent Connections</th>
|
||||||
|
<td>{{ .Counters.Connections.WeekCounter.Sum }}</td>
|
||||||
|
</tr>
|
||||||
|
{{ range $key, $val := .Stats }}
|
||||||
|
<tr>
|
||||||
|
<th>{{ $key }}</th>
|
||||||
|
<td>{{ $val }}</td>
|
||||||
|
</tr>
|
||||||
|
{{ end }}
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<h2>Topology</h2>
|
||||||
|
<table class="table table-striped">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Data Center</th>
|
||||||
|
<th>Rack</th>
|
||||||
|
<th>RemoteAddr</th>
|
||||||
|
<th>#Volumes</th>
|
||||||
|
<th>Volume Ids</th>
|
||||||
|
<th>#ErasureCodingShards</th>
|
||||||
|
<th>Max</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{{ range $dc_index, $dc := .Topology.DataCenters }}
|
||||||
|
{{ range $rack_index, $rack := $dc.Racks }}
|
||||||
|
{{ range $dn_index, $dn := $rack.DataNodes }}
|
||||||
|
<tr>
|
||||||
|
<td><code>{{ $dc.Id }}</code></td>
|
||||||
|
<td>{{ $rack.Id }}</td>
|
||||||
|
<td><a href="http://{{ $dn.Url }}/ui/index.html">{{ $dn.Url }}</a>
|
||||||
|
{{ if ne $dn.PublicUrl $dn.Url }}
|
||||||
|
/ <a href="http://{{ $dn.PublicUrl }}/ui/index.html">{{ $dn.PublicUrl }}</a>
|
||||||
|
{{ end }}
|
||||||
|
</td>
|
||||||
|
<td>{{ $dn.Volumes }}</td>
|
||||||
|
<td>{{ $dn.VolumeIds}}</td>
|
||||||
|
<td>{{ $dn.EcShards }}</td>
|
||||||
|
<td>{{ $dn.Max }}</td>
|
||||||
|
</tr>
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -1,115 +1,11 @@
|
||||||
package master_ui
|
package master_ui
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
_ "embed"
|
||||||
"html/template"
|
"html/template"
|
||||||
)
|
)
|
||||||
|
|
||||||
var StatusTpl = template.Must(template.New("status").Parse(`<!DOCTYPE html>
|
//go:embed master.html
|
||||||
<html>
|
var masterHtml string
|
||||||
<head>
|
|
||||||
<title>SeaweedFS {{ .Version }}</title>
|
|
||||||
<link rel="stylesheet" href="/seaweedfsstatic/bootstrap/3.3.1/css/bootstrap.min.css">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class="container">
|
|
||||||
<div class="page-header">
|
|
||||||
<h1>
|
|
||||||
<a href="https://github.com/chrislusf/seaweedfs"><img src="/seaweedfsstatic/seaweed50x50.png"></img></a>
|
|
||||||
SeaweedFS <small>{{ .Version }}</small>
|
|
||||||
</h1>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="row">
|
var StatusTpl = template.Must(template.New("status").Parse(masterHtml))
|
||||||
<div class="col-sm-6">
|
|
||||||
<h2>Cluster status</h2>
|
|
||||||
<table class="table table-condensed table-striped">
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<th>Volume Size Limit</th>
|
|
||||||
<td>{{ .VolumeSizeLimitMB }}MB</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Free</th>
|
|
||||||
<td>{{ .Topology.Free }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Max</th>
|
|
||||||
<td>{{ .Topology.Max }}</td>
|
|
||||||
</tr>
|
|
||||||
{{ with .RaftServer }}
|
|
||||||
<tr>
|
|
||||||
<th>Leader</th>
|
|
||||||
<td><a href="http://{{ .Leader }}">{{ .Leader }}</a></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Other Masters</th>
|
|
||||||
<td class="col-sm-5"><ul class="list-unstyled">
|
|
||||||
{{ range $k, $p := .Peers }}
|
|
||||||
<li><a href="http://{{ $p.Name }}/ui/index.html">{{ $p.Name }}</a></li>
|
|
||||||
{{ end }}
|
|
||||||
</ul></td>
|
|
||||||
</tr>
|
|
||||||
{{ end }}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="col-sm-6">
|
|
||||||
<h2>System Stats</h2>
|
|
||||||
<table class="table table-condensed table-striped">
|
|
||||||
<tr>
|
|
||||||
<th>Concurrent Connections</th>
|
|
||||||
<td>{{ .Counters.Connections.WeekCounter.Sum }}</td>
|
|
||||||
</tr>
|
|
||||||
{{ range $key, $val := .Stats }}
|
|
||||||
<tr>
|
|
||||||
<th>{{ $key }}</th>
|
|
||||||
<td>{{ $val }}</td>
|
|
||||||
</tr>
|
|
||||||
{{ end }}
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="row">
|
|
||||||
<h2>Topology</h2>
|
|
||||||
<table class="table table-striped">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Data Center</th>
|
|
||||||
<th>Rack</th>
|
|
||||||
<th>RemoteAddr</th>
|
|
||||||
<th>#Volumes</th>
|
|
||||||
<th>Volume Ids</th>
|
|
||||||
<th>#ErasureCodingShards</th>
|
|
||||||
<th>Max</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{{ range $dc_index, $dc := .Topology.DataCenters }}
|
|
||||||
{{ range $rack_index, $rack := $dc.Racks }}
|
|
||||||
{{ range $dn_index, $dn := $rack.DataNodes }}
|
|
||||||
<tr>
|
|
||||||
<td><code>{{ $dc.Id }}</code></td>
|
|
||||||
<td>{{ $rack.Id }}</td>
|
|
||||||
<td><a href="http://{{ $dn.Url }}/ui/index.html">{{ $dn.Url }}</a>
|
|
||||||
{{ if ne $dn.PublicUrl $dn.Url }}
|
|
||||||
/ <a href="http://{{ $dn.PublicUrl }}/ui/index.html">{{ $dn.PublicUrl }}</a>
|
|
||||||
{{ end }}
|
|
||||||
</td>
|
|
||||||
<td>{{ $dn.Volumes }}</td>
|
|
||||||
<td>{{ $dn.VolumeIds}}</td>
|
|
||||||
<td>{{ $dn.EcShards }}</td>
|
|
||||||
<td>{{ $dn.Max }}</td>
|
|
||||||
</tr>
|
|
||||||
{{ end }}
|
|
||||||
{{ end }}
|
|
||||||
{{ end }}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
`))
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package volume_server_ui
|
package volume_server_ui
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
_ "embed"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/chrislusf/seaweedfs/weed/util"
|
"github.com/chrislusf/seaweedfs/weed/util"
|
||||||
"html/template"
|
"html/template"
|
||||||
|
@ -26,191 +27,7 @@ var funcMap = template.FuncMap{
|
||||||
"percentFrom": percentFrom,
|
"percentFrom": percentFrom,
|
||||||
}
|
}
|
||||||
|
|
||||||
var StatusTpl = template.Must(template.New("status").Funcs(funcMap).Parse(`<!DOCTYPE html>
|
//go:embed volume.html
|
||||||
<html>
|
var volumeHtml string
|
||||||
<head>
|
|
||||||
<title>SeaweedFS {{ .Version }}</title>
|
|
||||||
<link rel="stylesheet" href="/seaweedfsstatic/bootstrap/3.3.1/css/bootstrap.min.css">
|
|
||||||
<script type="text/javascript" src="/seaweedfsstatic/javascript/jquery-3.6.0.min.js"></script>
|
|
||||||
<script type="text/javascript" src="/seaweedfsstatic/javascript/jquery-sparklines/2.1.2/jquery.sparkline.min.js"></script>
|
|
||||||
<script type="text/javascript">
|
|
||||||
$(function() {
|
|
||||||
var periods = ['second', 'minute', 'hour', 'day'];
|
|
||||||
for (i = 0; i < periods.length; i++) {
|
|
||||||
var period = periods[i];
|
|
||||||
$('.inlinesparkline-'+period).sparkline('html', {
|
|
||||||
type: 'line',
|
|
||||||
barColor: 'red',
|
|
||||||
tooltipSuffix:' request per '+period,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
<style>
|
|
||||||
#jqstooltip{
|
|
||||||
height: 28px !important;
|
|
||||||
width: 150px !important;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class="container">
|
|
||||||
<div class="page-header">
|
|
||||||
<h1>
|
|
||||||
<a href="https://github.com/chrislusf/seaweedfs"><img src="/seaweedfsstatic/seaweed50x50.png"></img></a>
|
|
||||||
SeaweedFS <small>{{ .Version }}</small>
|
|
||||||
</h1>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="row">
|
var StatusTpl = template.Must(template.New("status").Funcs(funcMap).Parse(volumeHtml))
|
||||||
<div class="col-sm-6">
|
|
||||||
<h2>Disk Stats</h2>
|
|
||||||
<table class="table table-striped">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Path</th>
|
|
||||||
<th>Disk</th>
|
|
||||||
<th>Total</th>
|
|
||||||
<th>Free</th>
|
|
||||||
<th>Usage</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{{ range .DiskStatuses }}
|
|
||||||
<tr>
|
|
||||||
<td>{{ .Dir }}</td>
|
|
||||||
<td>{{ .DiskType }}</td>
|
|
||||||
<td>{{ bytesToHumanReadable .All }}</td>
|
|
||||||
<td>{{ bytesToHumanReadable .Free }}</td>
|
|
||||||
<td>{{ percentFrom .All .Used}}%</td>
|
|
||||||
</tr>
|
|
||||||
{{ end }}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="col-sm-6">
|
|
||||||
<h2>System Stats</h2>
|
|
||||||
<table class="table table-condensed table-striped">
|
|
||||||
<tr>
|
|
||||||
<th>Masters</th>
|
|
||||||
<td>{{.Masters}}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Weekly # ReadRequests</th>
|
|
||||||
<td><span class="inlinesparkline-day">{{ .Counters.ReadRequests.WeekCounter.ToList | join }}</span></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Daily # ReadRequests</th>
|
|
||||||
<td><span class="inlinesparkline-hour">{{ .Counters.ReadRequests.DayCounter.ToList | join }}</span></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Hourly # ReadRequests</th>
|
|
||||||
<td><span class="inlinesparkline-minute">{{ .Counters.ReadRequests.HourCounter.ToList | join }}</span></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Last Minute # ReadRequests</th>
|
|
||||||
<td><span class="inlinesparkline-second">{{ .Counters.ReadRequests.MinuteCounter.ToList | join }}</span></td>
|
|
||||||
</tr>
|
|
||||||
{{ range $key, $val := .Stats }}
|
|
||||||
<tr>
|
|
||||||
<th>{{ $key }}</th>
|
|
||||||
<td>{{ $val }}</td>
|
|
||||||
</tr>
|
|
||||||
{{ end }}
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="row">
|
|
||||||
<h2>Volumes</h2>
|
|
||||||
<table class="table table-striped">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Id</th>
|
|
||||||
<th>Collection</th>
|
|
||||||
<th>Disk</th>
|
|
||||||
<th>Data Size</th>
|
|
||||||
<th>Files</th>
|
|
||||||
<th>Trash</th>
|
|
||||||
<th>TTL</th>
|
|
||||||
<th>ReadOnly</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{{ range .Volumes }}
|
|
||||||
<tr>
|
|
||||||
<td><code>{{ .Id }}</code></td>
|
|
||||||
<td>{{ .Collection }}</td>
|
|
||||||
<td>{{ .DiskType }}</td>
|
|
||||||
<td>{{ bytesToHumanReadable .Size }}</td>
|
|
||||||
<td>{{ .FileCount }}</td>
|
|
||||||
<td>{{ .DeleteCount }} / {{bytesToHumanReadable .DeletedByteCount}}</td>
|
|
||||||
<td>{{ .Ttl }}</td>
|
|
||||||
<td>{{ .ReadOnly }}</td>
|
|
||||||
</tr>
|
|
||||||
{{ end }}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="row">
|
|
||||||
<h2>Remote Volumes</h2>
|
|
||||||
<table class="table table-striped">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Id</th>
|
|
||||||
<th>Collection</th>
|
|
||||||
<th>Size</th>
|
|
||||||
<th>Files</th>
|
|
||||||
<th>Trash</th>
|
|
||||||
<th>Remote</th>
|
|
||||||
<th>Key</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{{ range .RemoteVolumes }}
|
|
||||||
<tr>
|
|
||||||
<td><code>{{ .Id }}</code></td>
|
|
||||||
<td>{{ .Collection }}</td>
|
|
||||||
<td>{{ bytesToHumanReadable .Size }}</td>
|
|
||||||
<td>{{ .FileCount }}</td>
|
|
||||||
<td>{{ .DeleteCount }} / {{bytesToHumanReadable .DeletedByteCount}}</td>
|
|
||||||
<td>{{ .RemoteStorageName }}</td>
|
|
||||||
<td>{{ .RemoteStorageKey }}</td>
|
|
||||||
</tr>
|
|
||||||
{{ end }}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="row">
|
|
||||||
<h2>Erasure Coding Shards</h2>
|
|
||||||
<table class="table table-striped">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Id</th>
|
|
||||||
<th>Collection</th>
|
|
||||||
<th>Shard Size</th>
|
|
||||||
<th>Shards</th>
|
|
||||||
<th>CreatedAt</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{{ range .EcVolumes }}
|
|
||||||
<tr>
|
|
||||||
<td><code>{{ .VolumeId }}</code></td>
|
|
||||||
<td>{{ .Collection }}</td>
|
|
||||||
<td>{{ bytesToHumanReadable .ShardSize }}</td>
|
|
||||||
<td>{{ .ShardIdList }}</td>
|
|
||||||
<td>{{ .CreatedAt.Format "02 Jan 06 15:04 -0700" }}</td>
|
|
||||||
</tr>
|
|
||||||
{{ end }}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
`))
|
|
||||||
|
|
194
weed/server/volume_server_ui/volume.html
Normal file
194
weed/server/volume_server_ui/volume.html
Normal file
|
@ -0,0 +1,194 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>SeaweedFS {{ .Version }}</title>
|
||||||
|
<link rel="stylesheet" href="/seaweedfsstatic/bootstrap/3.3.1/css/bootstrap.min.css">
|
||||||
|
<script type="text/javascript" src="/seaweedfsstatic/javascript/jquery-3.6.0.min.js"></script>
|
||||||
|
<script type="text/javascript"
|
||||||
|
src="/seaweedfsstatic/javascript/jquery-sparklines/2.1.2/jquery.sparkline.min.js"></script>
|
||||||
|
<script type="text/javascript">
|
||||||
|
$(function () {
|
||||||
|
var periods = ['second', 'minute', 'hour', 'day'];
|
||||||
|
for (i = 0; i < periods.length; i++) {
|
||||||
|
var period = periods[i];
|
||||||
|
$('.inlinesparkline-' + period).sparkline('html', {
|
||||||
|
type: 'line',
|
||||||
|
barColor: 'red',
|
||||||
|
tooltipSuffix: ' request per ' + period,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
<style>
|
||||||
|
#jqstooltip {
|
||||||
|
height: 28px !important;
|
||||||
|
width: 150px !important;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<div class="page-header">
|
||||||
|
<h1>
|
||||||
|
<a href="https://github.com/chrislusf/seaweedfs"><img src="/seaweedfsstatic/seaweed50x50.png"></img></a>
|
||||||
|
SeaweedFS <small>{{ .Version }}</small>
|
||||||
|
</h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-6">
|
||||||
|
<h2>Disk Stats</h2>
|
||||||
|
<table class="table table-striped">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Path</th>
|
||||||
|
<th>Disk</th>
|
||||||
|
<th>Total</th>
|
||||||
|
<th>Free</th>
|
||||||
|
<th>Usage</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{{ range .DiskStatuses }}
|
||||||
|
<tr>
|
||||||
|
<td>{{ .Dir }}</td>
|
||||||
|
<td>{{ .DiskType }}</td>
|
||||||
|
<td>{{ bytesToHumanReadable .All }}</td>
|
||||||
|
<td>{{ bytesToHumanReadable .Free }}</td>
|
||||||
|
<td>{{ percentFrom .All .Used}}%</td>
|
||||||
|
</tr>
|
||||||
|
{{ end }}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-sm-6">
|
||||||
|
<h2>System Stats</h2>
|
||||||
|
<table class="table table-condensed table-striped">
|
||||||
|
<tr>
|
||||||
|
<th>Masters</th>
|
||||||
|
<td>{{.Masters}}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Weekly # ReadRequests</th>
|
||||||
|
<td><span class="inlinesparkline-day">{{ .Counters.ReadRequests.WeekCounter.ToList | join }}</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Daily # ReadRequests</th>
|
||||||
|
<td><span class="inlinesparkline-hour">{{ .Counters.ReadRequests.DayCounter.ToList | join }}</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Hourly # ReadRequests</th>
|
||||||
|
<td><span
|
||||||
|
class="inlinesparkline-minute">{{ .Counters.ReadRequests.HourCounter.ToList | join }}</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Last Minute # ReadRequests</th>
|
||||||
|
<td><span
|
||||||
|
class="inlinesparkline-second">{{ .Counters.ReadRequests.MinuteCounter.ToList | join }}</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{{ range $key, $val := .Stats }}
|
||||||
|
<tr>
|
||||||
|
<th>{{ $key }}</th>
|
||||||
|
<td>{{ $val }}</td>
|
||||||
|
</tr>
|
||||||
|
{{ end }}
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<h2>Volumes</h2>
|
||||||
|
<table class="table table-striped">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Id</th>
|
||||||
|
<th>Collection</th>
|
||||||
|
<th>Disk</th>
|
||||||
|
<th>Data Size</th>
|
||||||
|
<th>Files</th>
|
||||||
|
<th>Trash</th>
|
||||||
|
<th>TTL</th>
|
||||||
|
<th>ReadOnly</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{{ range .Volumes }}
|
||||||
|
<tr>
|
||||||
|
<td><code>{{ .Id }}</code></td>
|
||||||
|
<td>{{ .Collection }}</td>
|
||||||
|
<td>{{ .DiskType }}</td>
|
||||||
|
<td>{{ bytesToHumanReadable .Size }}</td>
|
||||||
|
<td>{{ .FileCount }}</td>
|
||||||
|
<td>{{ .DeleteCount }} / {{bytesToHumanReadable .DeletedByteCount}}</td>
|
||||||
|
<td>{{ .Ttl }}</td>
|
||||||
|
<td>{{ .ReadOnly }}</td>
|
||||||
|
</tr>
|
||||||
|
{{ end }}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<h2>Remote Volumes</h2>
|
||||||
|
<table class="table table-striped">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Id</th>
|
||||||
|
<th>Collection</th>
|
||||||
|
<th>Size</th>
|
||||||
|
<th>Files</th>
|
||||||
|
<th>Trash</th>
|
||||||
|
<th>Remote</th>
|
||||||
|
<th>Key</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{{ range .RemoteVolumes }}
|
||||||
|
<tr>
|
||||||
|
<td><code>{{ .Id }}</code></td>
|
||||||
|
<td>{{ .Collection }}</td>
|
||||||
|
<td>{{ bytesToHumanReadable .Size }}</td>
|
||||||
|
<td>{{ .FileCount }}</td>
|
||||||
|
<td>{{ .DeleteCount }} / {{bytesToHumanReadable .DeletedByteCount}}</td>
|
||||||
|
<td>{{ .RemoteStorageName }}</td>
|
||||||
|
<td>{{ .RemoteStorageKey }}</td>
|
||||||
|
</tr>
|
||||||
|
{{ end }}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<h2>Erasure Coding Shards</h2>
|
||||||
|
<table class="table table-striped">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Id</th>
|
||||||
|
<th>Collection</th>
|
||||||
|
<th>Shard Size</th>
|
||||||
|
<th>Shards</th>
|
||||||
|
<th>CreatedAt</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{{ range .EcVolumes }}
|
||||||
|
<tr>
|
||||||
|
<td><code>{{ .VolumeId }}</code></td>
|
||||||
|
<td>{{ .Collection }}</td>
|
||||||
|
<td>{{ bytesToHumanReadable .ShardSize }}</td>
|
||||||
|
<td>{{ .ShardIdList }}</td>
|
||||||
|
<td>{{ .CreatedAt.Format "02 Jan 06 15:04 -0700" }}</td>
|
||||||
|
</tr>
|
||||||
|
{{ end }}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
Reference in a new issue