Skip to content
Snippets Groups Projects
Commit 4d07ae0a authored by Daniel Göbel's avatar Daniel Göbel
Browse files

Add modal to confirm deletion

parent 8cd83921
No related branches found
No related tags found
2 merge requests!22Version 1.0.0,!13Add modal to confirm deletion
...@@ -17,6 +17,7 @@ import CopyObjectModal from "@/components/Modals/CopyObjectModal.vue"; ...@@ -17,6 +17,7 @@ import CopyObjectModal from "@/components/Modals/CopyObjectModal.vue";
import PermissionModal from "@/components/Modals/PermissionModal.vue"; import PermissionModal from "@/components/Modals/PermissionModal.vue";
import ObjectDetailModal from "@/components/Modals/ObjectDetailModal.vue"; import ObjectDetailModal from "@/components/Modals/ObjectDetailModal.vue";
import CreateFolderModal from "@/components/Modals/CreateFolderModal.vue"; import CreateFolderModal from "@/components/Modals/CreateFolderModal.vue";
import DeleteModal from "@/components/Modals/DeleteModal.vue"
import { import {
S3Client, S3Client,
DeleteObjectCommand, DeleteObjectCommand,
...@@ -121,6 +122,8 @@ const objectState = reactive({ ...@@ -121,6 +122,8 @@ const objectState = reactive({
createdPermission: undefined, createdPermission: undefined,
deletedItem: "", deletedItem: "",
editObjectKey: "", editObjectKey: "",
potentialObjectToDelete: "",
deleteFolder: true,
copyObject: { copyObject: {
key: "", key: "",
size: 0, size: 0,
...@@ -141,6 +144,8 @@ const objectState = reactive({ ...@@ -141,6 +144,8 @@ const objectState = reactive({
createdPermission: undefined | BucketPermission; createdPermission: undefined | BucketPermission;
deletedItem: string; deletedItem: string;
editObjectKey: string; editObjectKey: string;
potentialObjectToDelete: string;
deleteFolder: boolean;
copyObject: S3ObjectMetaInformation; copyObject: S3ObjectMetaInformation;
viewDetailObject: S3ObjectMetaInformation; viewDetailObject: S3ObjectMetaInformation;
}); });
...@@ -388,11 +393,16 @@ function objectCopied(copiedObject: S3ObjectMetaInformation) { ...@@ -388,11 +393,16 @@ function objectCopied(copiedObject: S3ObjectMetaInformation) {
} }
} }
function deleteObject(key: string) {
objectState.potentialObjectToDelete = key;
objectState.deleteFolder = false;
}
/** /**
* Delete an Object in the current folder * Delete an Object in the current folder
* @param key Key of the Object * @param key Key of the Object
*/ */
function deleteObject(key: string) { function confirmedDeleteObject(key: string) {
const command = new DeleteObjectCommand({ const command = new DeleteObjectCommand({
Bucket: props.bucketName, Bucket: props.bucketName,
Key: key, Key: key,
...@@ -432,11 +442,16 @@ async function downloadObject(key: string, bucket: string) { ...@@ -432,11 +442,16 @@ async function downloadObject(key: string, bucket: string) {
document.body.removeChild(element); document.body.removeChild(element);
} }
function deleteFolder(folderPath: string) {
objectState.potentialObjectToDelete = folderPath;
objectState.deleteFolder = true;
}
/** /**
* Delete a folder in the current Bucket * Delete a folder in the current Bucket
* @param folderPath Path to the folder with a trailing "/", e.g. some/path/to/a/folder/ * @param folderPath Path to the folder with a trailing "/", e.g. some/path/to/a/folder/
*/ */
function deleteFolder(folderPath: string) { function confirmedDeleteFolder(folderPath: string) {
const command = new DeleteObjectsCommand({ const command = new DeleteObjectsCommand({
Bucket: props.bucketName, Bucket: props.bucketName,
Delete: { Delete: {
...@@ -506,6 +521,13 @@ watch( ...@@ -506,6 +521,13 @@ watch(
</div> </div>
</div> </div>
</div> </div>
<DeleteModal
modalID="delete-object-modal"
modal-label="some-label"
:object-name-delete="objectState.potentialObjectToDelete"
:back-modal-id="undefined"
@confirm-delete="objectState.deleteFolder ? confirmedDeleteFolder(objectState.potentialObjectToDelete) : confirmedDeleteObject(objectState.potentialObjectToDelete)"
/>
<!-- Navbar Breadcrumb --> <!-- Navbar Breadcrumb -->
<nav aria-label="breadcrumb" class="fs-2"> <nav aria-label="breadcrumb" class="fs-2">
<ol class="breadcrumb"> <ol class="breadcrumb">
...@@ -805,6 +827,8 @@ watch( ...@@ -805,6 +827,8 @@ watch(
class="dropdown-item text-danger align-middle" class="dropdown-item text-danger align-middle"
type="button" type="button"
@click="deleteObject(obj.key)" @click="deleteObject(obj.key)"
data-bs-toggle="modal"
data-bs-target="#delete-object-modal"
:disabled="!writeS3Permission" :disabled="!writeS3Permission"
> >
<bootstrap-icon <bootstrap-icon
...@@ -825,6 +849,8 @@ watch( ...@@ -825,6 +849,8 @@ watch(
type="button" type="button"
class="btn btn-danger btn-sm align-middle" class="btn btn-danger btn-sm align-middle"
:disabled="!writeS3Permission" :disabled="!writeS3Permission"
data-bs-toggle="modal"
data-bs-target="#delete-object-modal"
@click=" @click="
deleteFolder( deleteFolder(
obj.parentFolder.concat(['']).join('/') + obj.name + '/' obj.parentFolder.concat(['']).join('/') + obj.name + '/'
......
<script setup lang="ts">
import { onMounted, ref } from "vue";
import type { Ref } from "vue";
import { Modal } from "bootstrap";
import BootstrapModal from "@/components/Modals/BootstrapModal.vue";
const props = defineProps<{
modalID: string;
modalLabel: string;
objectNameDelete: string;
backModalId: string | undefined;
}>();
const confirmDelete: Ref<boolean> = ref(false);
const emit = defineEmits<{
(e: "confirm-delete"): void;
}>();
let deleteModal: Modal | null = null;
const randomIDSuffix = Math.random().toString(16).substr(2, 8);
function modalClosed() {
confirmDelete.value = false;
}
function deleteObject() {
emit("confirm-delete");
deleteModal?.hide();
confirmDelete.value = false;
}
onMounted(() => {
deleteModal = Modal.getOrCreateInstance("#" + props.modalID);
});
</script>
<template>
<bootstrap-modal
:modalID="props.modalID"
:static-backdrop="true"
:modal-label="props.modalLabel"
v-on="{ 'hidden.bs.modal': modalClosed }"
>
<template v-slot:header> Delete {{ props.objectNameDelete }}</template>
<template v-slot:body>
<p>
Are you sure you want to delete
<strong>{{ props.objectNameDelete }}</strong>
</p>
<div class="form-check">
<input
class="form-check-input"
type="checkbox"
v-model="confirmDelete"
:id="'checkConfirmDelete' + randomIDSuffix"
/>
<label
class="form-check-label"
:for="'checkConfirmDelete' + randomIDSuffix"
>
<strong>Yes</strong>, I am sure.
</label>
</div>
</template>
<template v-slot:footer>
<button
v-if="backModalId !== undefined"
type="button"
class="btn btn-secondary"
:data-bs-target="'#' + props.backModalId"
data-bs-toggle="modal"
>
Back
</button>
<button
v-else
type="button"
class="btn btn-secondary"
data-bs-dismiss="modal"
>
Close
</button>
<button
type="button"
class="btn btn-danger"
:disabled="!confirmDelete"
@click="deleteObject"
>
Delete
</button>
</template>
</bootstrap-modal>
</template>
<style scoped></style>
<script setup lang="ts"> <script setup lang="ts">
import { onMounted, reactive, watch, ref, computed } from "vue"; import { onMounted, reactive, watch, ref, computed } from "vue";
import BootstrapModal from "@/components/Modals/BootstrapModal.vue"; import BootstrapModal from "@/components/Modals/BootstrapModal.vue";
import DeleteModal from "@/components/Modals/DeleteModal.vue";
import { Modal } from "bootstrap"; import { Modal } from "bootstrap";
import dayjs from "dayjs"; import dayjs from "dayjs";
import type { import type {
...@@ -248,7 +249,7 @@ function formSubmit() { ...@@ -248,7 +249,7 @@ function formSubmit() {
* @param bucketName Bucket to delete * @param bucketName Bucket to delete
* @param uid ID of grantee of the permission * @param uid ID of grantee of the permission
*/ */
function deletePermission(bucketName: string, uid: string) { function confirmedDeletePermission(bucketName: string, uid: string) {
if (!formState.loading) { if (!formState.loading) {
formState.loading = true; formState.loading = true;
BucketPermissionsService.bucketPermissionsDeletePermissionForBucket( BucketPermissionsService.bucketPermissionsDeletePermissionForBucket(
...@@ -280,6 +281,15 @@ onMounted(() => { ...@@ -280,6 +281,15 @@ onMounted(() => {
</script> </script>
<template> <template>
<DeleteModal
:modalID="'delete-permission-modal' + randomIDSuffix"
modal-label="some-label"
object-name-delete="permission"
:back-modal-id="modalID"
@confirm-delete="
confirmedDeletePermission(permission.bucket_name, permission.uid)
"
/>
<div class="toast-container position-fixed top-0 end-0 p-3"> <div class="toast-container position-fixed top-0 end-0 p-3">
<div <div
role="alert" role="alert"
...@@ -329,7 +339,8 @@ onMounted(() => { ...@@ -329,7 +339,8 @@ onMounted(() => {
fill="currentColor" fill="currentColor"
class="me-2" class="me-2"
:class="{ 'delete-icon': !formState.loading }" :class="{ 'delete-icon': !formState.loading }"
@click="deletePermission(permission.bucket_name, permission.uid)" data-bs-toggle="modal"
:data-bs-target="'#delete-permission-modal' + randomIDSuffix"
/> />
<bootstrap-icon <bootstrap-icon
v-if="formState.readonly && props.editable" v-if="formState.readonly && props.editable"
......
...@@ -6,8 +6,10 @@ import { BucketPermissionsService, BucketService } from "@/client"; ...@@ -6,8 +6,10 @@ import { BucketPermissionsService, BucketService } from "@/client";
import { useRoute, useRouter } from "vue-router"; import { useRoute, useRouter } from "vue-router";
import BootstrapIcon from "@/components/BootstrapIcon.vue"; import BootstrapIcon from "@/components/BootstrapIcon.vue";
import CreateBucketModal from "@/components/Modals/CreateBucketModal.vue"; import CreateBucketModal from "@/components/Modals/CreateBucketModal.vue";
import DeleteModal from "@/components/Modals/DeleteModal.vue";
import BucketListItem from "@/components/BucketListItem.vue"; import BucketListItem from "@/components/BucketListItem.vue";
import { useAuthStore } from "@/stores/auth"; import { useAuthStore } from "@/stores/auth";
import { Modal } from "bootstrap";
const route = useRoute(); const route = useRoute();
const router = useRouter(); const router = useRouter();
...@@ -16,12 +18,15 @@ const authStore = useAuthStore(); ...@@ -16,12 +18,15 @@ const authStore = useAuthStore();
const bucketsState = reactive({ const bucketsState = reactive({
buckets: [], buckets: [],
permissions: {}, permissions: {},
potentialDeleteBucketName: "",
loading: true, loading: true,
} as { } as {
buckets: BucketOut[]; buckets: BucketOut[];
loading: boolean; loading: boolean;
permissions: Record<string, BucketPermission>; permissions: Record<string, BucketPermission>;
potentialDeleteBucketName: string;
}); });
let deleteModal: Modal | null = null;
function fetchBuckets() { function fetchBuckets() {
BucketService.bucketListBuckets() BucketService.bucketListBuckets()
...@@ -63,6 +68,11 @@ function addBucket(bucket: BucketOut) { ...@@ -63,6 +68,11 @@ function addBucket(bucket: BucketOut) {
} }
function deleteBucket(bucketName: string) { function deleteBucket(bucketName: string) {
bucketsState.potentialDeleteBucketName = bucketName;
deleteModal?.show();
}
function confirmedDeleteBucket(bucketName: string) {
BucketService.bucketDeleteBucket(bucketName, true).then(() => { BucketService.bucketDeleteBucket(bucketName, true).then(() => {
bucketDeleted(bucketName); bucketDeleted(bucketName);
}); });
...@@ -78,11 +88,21 @@ function bucketDeleted(bucketName: string) { ...@@ -78,11 +88,21 @@ function bucketDeleted(bucketName: string) {
} }
onMounted(() => { onMounted(() => {
deleteModal = Modal.getOrCreateInstance("#delete-bucket-modal");
fetchBuckets(); fetchBuckets();
}); });
</script> </script>
<template> <template>
<DeleteModal
modalID="delete-bucket-modal"
modal-label="some-label"
:object-name-delete="bucketsState.potentialDeleteBucketName"
:back-modal-id="undefined"
@confirm-delete="
confirmedDeleteBucket(bucketsState.potentialDeleteBucketName)
"
/>
<div class="row m-2 border-bottom border-light mt-4"> <div class="row m-2 border-bottom border-light mt-4">
<div class="col-12"></div> <div class="col-12"></div>
<h1 class="mb-2 text-light">Buckets</h1> <h1 class="mb-2 text-light">Buckets</h1>
......
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