Improve upload for subdirectory
This commit is contained in:
parent
c6ce282520
commit
1982236804
3 changed files with 112 additions and 14 deletions
|
@ -30,6 +30,7 @@ func HandleBucketView(s3 S3, templates fs.FS, allowDelete bool, listRecursive bo
|
|||
Objects []objectWithIcon
|
||||
AllowDelete bool
|
||||
Paths []string
|
||||
CurrentPath string
|
||||
}
|
||||
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
|
@ -68,6 +69,7 @@ func HandleBucketView(s3 S3, templates fs.FS, allowDelete bool, listRecursive bo
|
|||
Objects: objs,
|
||||
AllowDelete: allowDelete,
|
||||
Paths: removeEmptyStrings(strings.Split(path, "/")),
|
||||
CurrentPath: path,
|
||||
}
|
||||
|
||||
t, err := template.ParseFS(templates, "layout.html.tmpl", "bucket.html.tmpl")
|
||||
|
|
|
@ -22,6 +22,7 @@ func HandleCreateObject(s3 S3, sseInfo SSEType) http.HandlerFunc {
|
|||
return
|
||||
}
|
||||
file, header, err := r.FormFile("file")
|
||||
path := r.FormValue("path")
|
||||
if err != nil {
|
||||
handleHTTPError(w, fmt.Errorf("error getting file from form: %w", err))
|
||||
return
|
||||
|
@ -50,7 +51,8 @@ func HandleCreateObject(s3 S3, sseInfo SSEType) http.HandlerFunc {
|
|||
}
|
||||
}
|
||||
|
||||
_, err = s3.PutObject(r.Context(), bucketName, header.Filename, file, -1, opts)
|
||||
objectName := fmt.Sprintf("%s%s", path, header.Filename)
|
||||
_, err = s3.PutObject(r.Context(), bucketName, objectName, file, -1, opts)
|
||||
if err != nil {
|
||||
handleHTTPError(w, fmt.Errorf("error putting object: %w", err))
|
||||
return
|
||||
|
|
|
@ -1,7 +1,13 @@
|
|||
{{ define "content" }}
|
||||
<style>
|
||||
.breadcrumb:before {
|
||||
content: '/';
|
||||
content: '/';
|
||||
}
|
||||
#notifications {
|
||||
top: 20px;
|
||||
right: 30px;
|
||||
position: fixed;
|
||||
z-index: 2
|
||||
}
|
||||
</style>
|
||||
|
||||
|
@ -32,7 +38,7 @@
|
|||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="section" style="margin: 10px;">
|
||||
<div class="section" style="margin: 10px; position: relative;">
|
||||
{{ if .Objects }}
|
||||
<table class="striped">
|
||||
<thead>
|
||||
|
@ -59,16 +65,18 @@
|
|||
<td>{{ $object.Owner }}</td>
|
||||
<td>{{ $object.LastModified }}</td>
|
||||
<td>
|
||||
<button class="dropdown-trigger waves-effect waves-teal btn" data-target="actions-dropdown-{{ $index }}">
|
||||
Actions <i class="material-icons right">arrow_drop_down</i>
|
||||
</button>
|
||||
<!-- Dropdown Structure -->
|
||||
<ul id="actions-dropdown-{{ $index }}" class="dropdown-content">
|
||||
<li><a target="_blank" href="/api/buckets/{{ $.BucketName }}/objects/{{ $object.Key }}">Download</a></li>
|
||||
{{- if $.AllowDelete }}
|
||||
<li><a href="#" onclick="deleteObject({{ $.BucketName }}, {{ $object.Key }})">Delete</a></li>
|
||||
{{- end }}
|
||||
</ul>
|
||||
{{ if not $object.IsFolder }}
|
||||
<button class="dropdown-trigger waves-effect waves-teal btn" data-target="actions-dropdown-{{ $index }}">
|
||||
Actions <i class="material-icons right">arrow_drop_down</i>
|
||||
</button>
|
||||
<!-- Dropdown Structure -->
|
||||
<ul id="actions-dropdown-{{ $index }}" class="dropdown-content">
|
||||
<li><a target="_blank" href="/api/buckets/{{ $.BucketName }}/objects/{{ $object.Key }}">Download</a></li>
|
||||
{{- if $.AllowDelete }}
|
||||
<li><a href="#" onclick="deleteObject({{ $.BucketName }}, {{ $object.Key }})">Delete</a></li>
|
||||
{{- end }}
|
||||
</ul>
|
||||
{{ end }}
|
||||
</td>
|
||||
</tr>
|
||||
{{ end }}
|
||||
|
@ -77,15 +85,30 @@
|
|||
{{ end }}
|
||||
|
||||
{{ if not .Objects }}
|
||||
<p style="text-align:center;margin-top:2em;color:gray;">No objects in <strong>{{ .BucketName }}</strong> yet</p>
|
||||
<p style="text-align:center;margin-top:2em;color:gray;">No objects in <strong>{{ .BucketName }}/{{ .CurrentPath }}</strong> yet</p>
|
||||
{{ end }}
|
||||
|
||||
<div id="notifications">
|
||||
<div id="notification-template" class="card" style="display: none;">
|
||||
<div class="card-content" style="padding: 12px">
|
||||
<span class="card-title">Uploading</span>
|
||||
<p> I am a very simple card </p>
|
||||
<div class="progress">
|
||||
<div class="indeterminate"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="fixed-action-btn">
|
||||
<button type="button" class="btn-floating btn-large red modal-trigger" data-target="modal-create-object">
|
||||
<i class="large material-icons">add</i>
|
||||
</button>
|
||||
|
||||
<button type="button" class="btn-floating btn-large red modal-trigger" data-target="modal-create-folder">
|
||||
<i class="large material-icons">create_new_folder</i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div id="modal-create-object" class="modal">
|
||||
|
@ -104,6 +127,7 @@
|
|||
<div class="file-path-wrapper">
|
||||
<input class="file-path validate" type="text">
|
||||
</div>
|
||||
<input type="hidden" name="path" value="{{ $.CurrentPath }}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -117,6 +141,30 @@
|
|||
</form>
|
||||
</div>
|
||||
|
||||
<div id="modal-create-folder" class="modal">
|
||||
<form id="create-folder-form" enctype="multipart/form-data">
|
||||
|
||||
<div class="modal-content">
|
||||
<h4>Create Folder</h4>
|
||||
<br>
|
||||
<div class="row">
|
||||
<div class="col s6">
|
||||
<div class="input-field">
|
||||
<input name="new-path" id="new-path" type="text">
|
||||
<label for="new-path">Path</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="modal-close waves-effect waves-green btn-flat">Cancel</button>
|
||||
<button type="submit" class="modal-close waves-effect waves-green btn">Create</button>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function deleteObject(bucketName, objectName) {
|
||||
$.ajax({
|
||||
|
@ -132,5 +180,51 @@ function deleteBucket(bucketName) {
|
|||
success: function () { window.location.replace('/buckets'); }
|
||||
})
|
||||
}
|
||||
|
||||
function handleCreateFolder(event) {
|
||||
event.preventDefault();
|
||||
|
||||
const form = event.target;
|
||||
const formData = new FormData(form);
|
||||
const newPath = formData.get("new-path")
|
||||
|
||||
let newHref = window.location.href + newPath
|
||||
if(!newHref.endsWith("/")) {
|
||||
newHref = newHref + "/"
|
||||
}
|
||||
|
||||
window.location.href = newHref
|
||||
}
|
||||
|
||||
function handleCreateObject(event) {
|
||||
event.preventDefault();
|
||||
|
||||
const form = event.target;
|
||||
const url = new URL(form.action);
|
||||
const formData = new FormData(form);
|
||||
createNotification(formData.get("file").name)
|
||||
fetch(url, {
|
||||
method: "POST",
|
||||
body: formData
|
||||
}).then(response => {
|
||||
window.location.reload();
|
||||
})
|
||||
}
|
||||
|
||||
function createNotification(fileName) {
|
||||
notificationTemplate = document.getElementById('notification-template');
|
||||
notification = notificationTemplate.cloneNode(true)
|
||||
notification.getElementsByTagName('p')[0].setHTML(fileName)
|
||||
notification.removeAttribute("id")
|
||||
notification.removeAttribute("style")
|
||||
|
||||
notifications = document.getElementById('notifications');
|
||||
notifications.appendChild(notification)
|
||||
}
|
||||
|
||||
window.onload = (event) => {
|
||||
document.getElementById('create-folder-form').addEventListener('submit', handleCreateFolder);
|
||||
document.getElementById('create-object-form').addEventListener('submit', handleCreateObject);
|
||||
};
|
||||
</script>
|
||||
{{ end }}
|
||||
|
|
Loading…
Reference in a new issue