From e01e2b226508e134462735b14fb29b58694ca185 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Daniel=20G=C3=B6bel?= <dgoebel@techfak.uni-bielefeld.de>
Date: Tue, 27 Sep 2022 10:15:01 +0200
Subject: [PATCH] Add delete modal to confirm deletion of buckets

#13
---
 src/components/Modals/DeleteModal.vue    | 95 ++++++++++++++++++++++++
 src/views/object-storage/BucketsView.vue | 20 +++++
 2 files changed, 115 insertions(+)
 create mode 100644 src/components/Modals/DeleteModal.vue

diff --git a/src/components/Modals/DeleteModal.vue b/src/components/Modals/DeleteModal.vue
new file mode 100644
index 0000000..108993d
--- /dev/null
+++ b/src/components/Modals/DeleteModal.vue
@@ -0,0 +1,95 @@
+<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>
diff --git a/src/views/object-storage/BucketsView.vue b/src/views/object-storage/BucketsView.vue
index c01d35e..58422c9 100644
--- a/src/views/object-storage/BucketsView.vue
+++ b/src/views/object-storage/BucketsView.vue
@@ -6,8 +6,10 @@ import { BucketPermissionsService, BucketService } from "@/client";
 import { useRoute, useRouter } from "vue-router";
 import BootstrapIcon from "@/components/BootstrapIcon.vue";
 import CreateBucketModal from "@/components/Modals/CreateBucketModal.vue";
+import DeleteModal from "@/components/Modals/DeleteModal.vue";
 import BucketListItem from "@/components/BucketListItem.vue";
 import { useAuthStore } from "@/stores/auth";
+import { Modal } from "bootstrap";
 
 const route = useRoute();
 const router = useRouter();
@@ -16,12 +18,15 @@ const authStore = useAuthStore();
 const bucketsState = reactive({
   buckets: [],
   permissions: {},
+  potentialDeleteBucketName: "",
   loading: true,
 } as {
   buckets: BucketOut[];
   loading: boolean;
   permissions: Record<string, BucketPermission>;
+  potentialDeleteBucketName: string;
 });
+let deleteModal: Modal | null = null;
 
 function fetchBuckets() {
   BucketService.bucketListBuckets()
@@ -63,6 +68,11 @@ function addBucket(bucket: BucketOut) {
 }
 
 function deleteBucket(bucketName: string) {
+  bucketsState.potentialDeleteBucketName = bucketName;
+  deleteModal?.show();
+}
+
+function confirmedDeleteBucket(bucketName: string) {
   BucketService.bucketDeleteBucket(bucketName, true).then(() => {
     bucketDeleted(bucketName);
   });
@@ -78,11 +88,21 @@ function bucketDeleted(bucketName: string) {
 }
 
 onMounted(() => {
+  deleteModal = Modal.getOrCreateInstance("#delete-bucket-modal");
   fetchBuckets();
 });
 </script>
 
 <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="col-12"></div>
     <h1 class="mb-2 text-light">Buckets</h1>
-- 
GitLab