Skip to content
Snippets Groups Projects
Verified Commit 03b2c146 authored by Daniel Göbel's avatar Daniel Göbel
Browse files

Add create folder model

#15
parent 54d69c57
No related branches found
No related tags found
1 merge request!12Add direct S3 interaction
This commit is part of merge request !12. Comments created here will be created in the context of that merge request.
......@@ -10,6 +10,7 @@ import { Tooltip } from "bootstrap";
import PermissionListModal from "@/components/Modals/PermissionListModal.vue";
import UploadObjectModal from "@/components/Modals/UploadObjectModal.vue";
import PermissionModal from "@/components/Modals/PermissionModal.vue";
import CreateFolderModal from "@/components/Modals/CreateFolderModal.vue";
import { S3Client } from "@aws-sdk/client-s3";
import { awsAuthMiddlewareOptions } from "@aws-sdk/middleware-signing";
......@@ -203,7 +204,7 @@ const visibleObjects: ComputedRef<(S3ObjectWithFolder | S3PseudoFolder)[]> =
} as S3PseudoFolder;
})
);
return arr;
return arr.filter((obj) => !obj.key.endsWith(".s3keep"));
});
const subFolderInUrl: ComputedRef<boolean> = computed(
......@@ -390,7 +391,6 @@ watch(
</button>
<upload-object-modal
:bucket-name="props.bucketName"
:sub-folders="[]"
:s3-client="client"
modalID="upload-object-modal"
modal-label="some-label"
......@@ -402,13 +402,22 @@ watch(
type="button"
class="btn btn-secondary m-2 tooltip-container"
:disabled="errorLoadingObjects"
data-bs-toggle="tooltip"
data-bs-toggle="modal"
data-bs-title="Create Folder"
data-bs-target="#create-folder-modal"
>
<bootstrap-icon icon="plus-lg" :width="16" :height="16" fill="white" />
Folder
<span class="visually-hidden">Add Folder</span>
</button>
<create-folder-modal
:bucket-name="props.bucketName"
:s3-client="client"
modalID="create-folder-modal"
modal-label="some-label"
:key-prefix="currentSubFolders.join('/')"
@folder-created="objectUploaded"
/>
<!-- Add bucket permission button -->
<button
:hidden="props.permission != null"
......
<script setup lang="ts">
import type { S3Client } from "@aws-sdk/client-s3";
import { PutObjectCommand } from "@aws-sdk/client-s3";
import BootstrapModal from "@/components/Modals/BootstrapModal.vue";
import { computed, onMounted, reactive } from "vue";
import type { ComputedRef } from "vue";
import type { S3ObjectMetaInformation } from "@/client";
import dayjs from "dayjs";
import { Modal, Toast } from "bootstrap";
const props = defineProps<{
modalID: string;
modalLabel: string;
bucketName: string;
keyPrefix: string;
s3Client: S3Client;
}>();
const randomIDSuffix = Math.random().toString(16).substr(2, 8);
let uploadModal: Modal | null = null;
let successToast: Toast | null = null;
let errorToast: Toast | null = null;
const currentFolders: ComputedRef<string[]> = computed(() =>
props.keyPrefix.split("/")
);
const emit = defineEmits<{
(e: "folder-created", object: S3ObjectMetaInformation): void;
}>();
const formState = reactive({
folderName: "",
uploading: false,
} as {
folderName: string;
uploading: boolean;
});
function uploadFolder() {
const key =
(props.keyPrefix.length > 0
? props.keyPrefix + "/" + formState.folderName
: formState.folderName) + "/.s3keep";
const command = new PutObjectCommand({
Bucket: props.bucketName,
Body: "",
ContentType: "text/plain",
Key: key,
});
formState.uploading = true;
props.s3Client
.send(command)
.then(() => {
uploadModal?.hide();
successToast?.show();
emit("folder-created", {
key: key,
bucket: props.bucketName,
size: 0,
last_modified: dayjs().toISOString(),
});
formState.folderName = "";
})
.catch((e) => {
console.error(e);
errorToast?.show();
})
.finally(() => {
formState.uploading = false;
});
}
onMounted(() => {
uploadModal = new Modal("#" + props.modalID);
successToast = new Toast("#successToast-" + randomIDSuffix);
errorToast = new Toast("#errorToast-" + randomIDSuffix);
});
</script>
<template>
<div class="toast-container position-fixed top-0 end-0 p-3">
<div
role="alert"
aria-live="assertive"
aria-atomic="true"
class="toast text-bg-success align-items-center border-0"
data-bs-autohide="true"
:id="'successToast-' + randomIDSuffix"
>
<div class="d-flex">
<div class="toast-body">Successfully created Folder</div>
<button
type="button"
class="btn-close btn-close-white me-2 m-auto"
data-bs-dismiss="toast"
aria-label="Close"
></button>
</div>
</div>
</div>
<div class="toast-container position-fixed top-0 end-0 p-3">
<div
role="alert"
aria-live="assertive"
aria-atomic="true"
class="toast text-bg-danger align-items-center border-0"
data-bs-autohide="true"
:id="'errorToast-' + randomIDSuffix"
>
<div class="d-flex">
<div class="toast-body">
There has been some Error.<br />
Try again later
</div>
<button
type="button"
class="btn-close btn-close-white me-2 m-auto"
data-bs-dismiss="toast"
aria-label="Close"
></button>
</div>
</div>
</div>
<bootstrap-modal
:modalID="modalID"
:static-backdrop="true"
:modal-label="modalLabel"
>
<template v-slot:header>
<h4>Create folder in</h4>
<ol class="breadcrumb">
<li class="breadcrumb-item">{{ props.bucketName }}</li>
<li
class="breadcrumb-item"
v-for="folder in currentFolders"
:key="folder"
>
{{ folder }}
</li>
</ol>
</template>
<template v-slot:body>
<div class="container-fluid">
<div class="row">
<form
class="col-7"
:id="'uploadFolderForm' + randomIDSuffix"
@submit.prevent="uploadFolder"
>
<div class="mb-3">
<label :for="'folderName' + randomIDSuffix" class="form-label"
>Folder Name</label
>
<input
type="text"
class="form-control"
:id="'folderName' + randomIDSuffix"
required
v-model="formState.folderName"
/>
</div>
</form>
<div class="col-5">
Note: Delimiters ('/') are allowed in the folder name to place the
new folder into a folder that will be created when the folder is
created (to any depth of folders).
</div>
</div>
</div>
</template>
<template v-slot:footer>
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">
Close
</button>
<button
:disabled="formState.uploading"
type="submit"
:form="'uploadFolderForm' + randomIDSuffix"
class="btn btn-primary"
>
<span
v-if="formState.uploading"
class="spinner-border spinner-border-sm"
role="status"
aria-hidden="true"
></span>
Create
</button>
</template>
</bootstrap-modal>
</template>
<style scoped></style>
......@@ -27,10 +27,8 @@ export default defineConfig({
// Enable esbuild polyfill plugins
plugins: [
NodeGlobalsPolyfillPlugin({
stream: true,
buffer: true,
process: true,
util: true,
}),
NodeModulesPolyfillPlugin(),
],
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment