mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2024-01-19 02:48:24 +00:00
359 lines
11 KiB
HTML
359 lines
11 KiB
HTML
<!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;
|
|
margin-top: 5px;
|
|
}
|
|
|
|
#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;
|
|
margin-left: 2px;
|
|
margin-bottom: 0;
|
|
}
|
|
|
|
label {
|
|
font-weight: normal;
|
|
}
|
|
|
|
.button:hover {
|
|
background: #ddd;
|
|
}
|
|
|
|
#fileElem {
|
|
display: none;
|
|
}
|
|
|
|
td, th {
|
|
vertical-align: bottom;
|
|
}
|
|
|
|
.table-hover > tbody > tr:hover > * > div.operations {
|
|
display: block;
|
|
}
|
|
|
|
.table > tbody > tr {
|
|
height: 39px;
|
|
}
|
|
|
|
div.operations {
|
|
display: none;
|
|
}
|
|
|
|
.footer {
|
|
position: absolute;
|
|
bottom: 0px;
|
|
right: 5%;
|
|
min-width: 25%;
|
|
border-left: 1px solid #ccc;
|
|
border-right: 1px solid #ccc;
|
|
}
|
|
|
|
.add-files {
|
|
font-size: 46px;
|
|
text-align: center;
|
|
border: 1px dashed #999;
|
|
padding-bottom: 9px;
|
|
margin: 0 2px;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="container">
|
|
<div class="page-header">
|
|
<h1>
|
|
<a href="https://github.com/seaweedfs/seaweedfs"><img src="/seaweedfsstatic/seaweed50x50.png"></img></a>
|
|
SeaweedFS Filer
|
|
</h1>
|
|
</div>
|
|
<div class="row">
|
|
<div>
|
|
<div class="btn-group btn-group-sm pull-right" role="group" style="margin-top:3px;">
|
|
<label class="btn btn-default" onclick="handleCreateDir()">
|
|
<span class="glyphicon glyphicon-plus" aria-hidden="true"></span> New Folder
|
|
</label>
|
|
<label class="btn btn-default" for="fileElem">
|
|
<span class="glyphicon glyphicon-cloud-upload" aria-hidden="true"></span> Upload
|
|
</label>
|
|
</div>
|
|
<ol class="breadcrumb">
|
|
{{ range $entry := .Breadcrumbs }}
|
|
<li><a href="{{ printpath $entry.Link }}">
|
|
{{ $entry.Name }}
|
|
</li></a>
|
|
{{ end }}
|
|
</ol>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row" id="drop-area">
|
|
<form class="upload-form">
|
|
<input type="file" id="fileElem" multiple onchange="handleFiles(this.files)">
|
|
|
|
{{ if .EmptyFolder }}
|
|
<div class="row add-files">
|
|
+
|
|
</div>
|
|
{{ else }}
|
|
<table width="100%" class="table table-hover">
|
|
{{ $path := .Path }}
|
|
{{ $showDirDel := .ShowDirectoryDelete }}
|
|
{{ range $entry_index, $entry := .Entries }}
|
|
<tr>
|
|
<td>
|
|
{{ if $entry.IsDirectory }}
|
|
<span class="glyphicon glyphicon-folder-open" aria-hidden="true"></span>
|
|
<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 not $entry.IsDirectory }}
|
|
{{ $entry.Mime }}
|
|
{{ end }}
|
|
</td>
|
|
<td align="right" nowrap>
|
|
{{ if not $entry.IsDirectory }}
|
|
{{ $entry.Size | humanizeBytes }}
|
|
{{ end }}
|
|
</td>
|
|
<td align="right" nowrap>
|
|
{{ $entry.Timestamp.Format "2006-01-02 15:04" }}
|
|
</td>
|
|
<td style="width:75px">
|
|
<div class="btn-group btn-group-xs pull-right operations" role="group">
|
|
<label class="btn" onclick="handleRename('{{ $entry.Name }}', '{{ printpath $path "/" }}')">
|
|
<span class="glyphicon glyphicon-edit" aria-hidden="true"></span>
|
|
</label>
|
|
{{ if and $entry.IsDirectory $showDirDel }}
|
|
<label class="btn" onclick="handleDelete('{{ printpath $path "/" $entry.Name "/" }}')">
|
|
<span class="glyphicon glyphicon-trash" aria-hidden="true"></span>
|
|
</label>
|
|
{{ end }}
|
|
{{ if not $entry.IsDirectory }}
|
|
<label class="btn" onclick="handleDelete('{{ printpath $path "/" $entry.Name }}')">
|
|
<span class="glyphicon glyphicon-trash" aria-hidden="true"></span>
|
|
</label>
|
|
{{ end }}
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
{{ end }}
|
|
</table>
|
|
{{ end }}
|
|
</form>
|
|
</div>
|
|
|
|
{{ if .ShouldDisplayLoadMore }}
|
|
<div class="row">
|
|
<a href={{ print .Path "?limit=" .Limit "&lastFileName=" .LastFileName }} >
|
|
Load more
|
|
</a>
|
|
</div>
|
|
{{ end }}
|
|
|
|
<br/>
|
|
<br/>
|
|
<div id="progress-area" class="footer" style="display: none;">
|
|
</div>
|
|
</div>
|
|
</body>
|
|
<script type="text/javascript">
|
|
// ************************ Drag and drop ***************** //
|
|
let dropArea = document.getElementById("drop-area");
|
|
let progressArea = document.getElementById("progress-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 reloadPage() {
|
|
window.location.reload(true);
|
|
}
|
|
|
|
var uploadList = {};
|
|
|
|
function handleFiles(files) {
|
|
files = [...files];
|
|
files.forEach(startUpload);
|
|
renderProgress();
|
|
files.forEach(uploadFile);
|
|
}
|
|
|
|
function startUpload(file, i) {
|
|
uploadList[file.name] = {'name': file.name, 'percent': 0, 'finish': false};
|
|
}
|
|
|
|
function renderProgress() {
|
|
var values = Object.values(uploadList);
|
|
var html = '<table class="table">\n<tr><th>Uploading</th><\/tr>\n';
|
|
for (let i of values) {
|
|
var progressBarClass = 'progress-bar-striped active';
|
|
if (i.percent >= 100) {
|
|
progressBarClass = 'progress-bar-success';
|
|
}
|
|
html += '<tr>\n<td>\n';
|
|
html += '<div class="progress" style="margin-bottom: 2px;">\n';
|
|
html += '<div class="progress-bar ' + progressBarClass + '" role="progressbar" aria-valuenow="' + '100" aria-valuemin="0" aria-valuemax="100" style="width:' + i.percent + '%;">';
|
|
html += '<span style="margin-right: 10px;">' + i.name + '</span>' + i.percent + '%<\/div>';
|
|
html += '<\/div>\n<\/td>\n<\/tr>\n';
|
|
}
|
|
html += '<\/table>\n';
|
|
progressArea.innerHTML = html;
|
|
if (values.length > 0) {
|
|
progressArea.attributes.style.value = '';
|
|
}
|
|
}
|
|
|
|
function reportProgress(file, percent) {
|
|
var item = uploadList[file]
|
|
item.percent = percent;
|
|
renderProgress();
|
|
}
|
|
|
|
function finishUpload(file) {
|
|
uploadList[file]['finish'] = true;
|
|
renderProgress();
|
|
var allFinish = true;
|
|
for (let i of Object.values(uploadList)) {
|
|
if (!i.finish) {
|
|
allFinish = false;
|
|
break;
|
|
}
|
|
}
|
|
if (allFinish) {
|
|
console.log('All Finish');
|
|
reloadPage();
|
|
}
|
|
}
|
|
|
|
function uploadFile(file, i) {
|
|
var url = window.location.href;
|
|
var xhr = new XMLHttpRequest();
|
|
var fileName = file.name;
|
|
xhr.upload.addEventListener('progress', function(e) {
|
|
if (e.lengthComputable) {
|
|
var percent = Math.ceil((e.loaded / e.total) * 100);
|
|
reportProgress(fileName, percent)
|
|
}
|
|
});
|
|
xhr.upload.addEventListener('loadend', function(e) {
|
|
finishUpload(fileName);
|
|
});
|
|
var formData = new FormData();
|
|
xhr.open('POST', url, true);
|
|
formData.append('file', file);
|
|
xhr.send(formData);
|
|
}
|
|
|
|
function handleCreateDir() {
|
|
var dirName = prompt('Folder Name:', '');
|
|
dirName = dirName.trim();
|
|
if (dirName == null || dirName == '') {
|
|
return;
|
|
}
|
|
var baseUrl = window.location.href;
|
|
if (!baseUrl.endsWith('/')) {
|
|
baseUrl += '/';
|
|
}
|
|
var url = baseUrl + dirName;
|
|
if (!url.endsWith('/')) {
|
|
url += '/';
|
|
}
|
|
var xhr = new XMLHttpRequest();
|
|
xhr.open('POST', url, false);
|
|
xhr.setRequestHeader('Content-Type', '');
|
|
xhr.send();
|
|
reloadPage();
|
|
}
|
|
|
|
function handleRename(originName, basePath) {
|
|
var newName = prompt('New Name:', originName);
|
|
if (newName == null || newName == '') {
|
|
return;
|
|
}
|
|
var url = basePath + newName;
|
|
var originPath = basePath + originName;
|
|
url += '?mv.from=' + originPath;
|
|
var xhr = new XMLHttpRequest();
|
|
xhr.open('POST', url, false);
|
|
xhr.setRequestHeader('Content-Type', '');
|
|
xhr.send();
|
|
reloadPage();
|
|
}
|
|
|
|
function handleDelete(path) {
|
|
if (!confirm('Are you sure to delete ' + path + '?')) {
|
|
return;
|
|
}
|
|
var url = path;
|
|
if (url.endsWith('/')) {
|
|
url += '?recursive=true';
|
|
}
|
|
|
|
var xhr = new XMLHttpRequest();
|
|
xhr.open('DELETE', url, false);
|
|
xhr.send();
|
|
reloadPage();
|
|
}
|
|
</script>
|
|
</html>
|