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

Add ability to delete a permission in the permission modal

#19
parent f8b25b6b
No related branches found
No related tags found
1 merge request!11View / Edit Bucket Permissions
...@@ -17,7 +17,8 @@ const props = defineProps<{ ...@@ -17,7 +17,8 @@ const props = defineProps<{
const tooltipID = Math.random().toString(16).substr(2, 8); const tooltipID = Math.random().toString(16).substr(2, 8);
const emit = defineEmits<{ const emit = defineEmits<{
(e: "delete-bucket", bucket_name: string): void; (e: "delete-bucket", bucketName: string): void;
(e: "permission-deleted", bucketName: string): void;
}>(); }>();
onMounted(() => { onMounted(() => {
...@@ -37,6 +38,8 @@ onMounted(() => { ...@@ -37,6 +38,8 @@ onMounted(() => {
:edit-user-permission="props.permission" :edit-user-permission="props.permission"
:readonly="true" :readonly="true"
:editable="false" :editable="false"
:deletable="true"
@permission-deleted="(bucketName) => emit('permission-deleted', bucketName)"
/> />
<div class="mt-2 mb-2"> <div class="mt-2 mb-2">
<div <div
...@@ -72,9 +75,9 @@ onMounted(() => { ...@@ -72,9 +75,9 @@ onMounted(() => {
</router-link> </router-link>
<div <div
:hidden="!props.active" :hidden="!props.active"
class="ps-2 rounded-bottom bg-light text-bg-light" class="ps-2 pe-2 rounded-bottom bg-light text-bg-light border border-3 border-top-0 border-primary"
> >
<table class="table table-sm table-borderless"> <table class="table table-sm table-borderless mb-0">
<tbody> <tbody>
<tr> <tr>
<th scope="row" class="fw-bold">Created:</th> <th scope="row" class="fw-bold">Created:</th>
......
...@@ -364,6 +364,7 @@ watch( ...@@ -364,6 +364,7 @@ watch(
:edit-user-permission="undefined" :edit-user-permission="undefined"
:editable="false" :editable="false"
:readonly="false" :readonly="false"
:deletable="false"
/> />
<!-- Add folder button --> <!-- Add folder button -->
<button <button
......
<script setup lang="ts"> <script setup lang="ts">
import { onMounted, reactive, watch, computed } from "vue"; import { onMounted, reactive, watch, ref, computed, defineEmits } from "vue";
import BootstrapModal from "@/components/BootstrapModal.vue"; import BootstrapModal from "@/components/BootstrapModal.vue";
import { Modal } from "bootstrap"; import { Modal } from "bootstrap";
import dayjs from "dayjs"; import dayjs from "dayjs";
...@@ -8,7 +8,7 @@ import type { ...@@ -8,7 +8,7 @@ import type {
S3ObjectMetaInformation, S3ObjectMetaInformation,
BucketPermissionParameters, BucketPermissionParameters,
} from "@/client"; } from "@/client";
import type { ComputedRef } from "vue"; import type { ComputedRef, Ref } from "vue";
import { PermissionEnum, BucketPermissionsService } from "@/client"; import { PermissionEnum, BucketPermissionsService } from "@/client";
import { Toast } from "bootstrap"; import { Toast } from "bootstrap";
import BootstrapIcon from "@/components/BootstrapIcon.vue"; import BootstrapIcon from "@/components/BootstrapIcon.vue";
...@@ -35,12 +35,13 @@ const props = defineProps<{ ...@@ -35,12 +35,13 @@ const props = defineProps<{
editUserPermission: BucketPermission | undefined; editUserPermission: BucketPermission | undefined;
readonly: boolean; readonly: boolean;
editable: boolean; editable: boolean;
deletable: boolean;
}>(); }>();
// Variables // Variables
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
const toastID = Math.random().toString(16).substr(2, 8); const toastID = Math.random().toString(16).substr(2, 8);
let createPermissionModal: Modal | null = null; let permissionModal: Modal | null = null;
let successToast: Toast | null = null; let successToast: Toast | null = null;
// Reactive State // Reactive State
...@@ -64,6 +65,8 @@ const permission = reactive({ ...@@ -64,6 +65,8 @@ const permission = reactive({
bucket_name: props.bucketName, bucket_name: props.bucketName,
} as BucketPermission); } as BucketPermission);
const permissionDeleted: Ref<boolean> = ref(false);
// Computes Properties // Computes Properties
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
const editPermission: ComputedRef<boolean> = computed( const editPermission: ComputedRef<boolean> = computed(
...@@ -93,6 +96,12 @@ watch( ...@@ -93,6 +96,12 @@ watch(
() => updatePermission() () => updatePermission()
); );
// Events
// -----------------------------------------------------------------------------
const emit = defineEmits<{
(e: "permission-deleted", bucket_name: string): void;
}>();
// Functions // Functions
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
/** /**
...@@ -107,7 +116,14 @@ function modalClosed() { ...@@ -107,7 +116,14 @@ function modalClosed() {
} }
/** /**
* Check if a input should be visible based on its state * Callback when the toast is hidden again.
*/
function toastHidden() {
permissionDeleted.value = false;
}
/**
* Check if an input should be visible based on its state
* @param input Input which visibility should be determined. * @param input Input which visibility should be determined.
*/ */
function inputVisible(input: string | undefined): boolean { function inputVisible(input: string | undefined): boolean {
...@@ -204,12 +220,39 @@ function formSubmit() { ...@@ -204,12 +220,39 @@ function formSubmit() {
); );
serverAnswerPromise serverAnswerPromise
.then(() => { .then(() => {
createPermissionModal?.hide(); permissionModal?.hide();
successToast?.show();
updatePermission();
})
.catch(() => {
formState.error = true;
})
.finally(() => {
formState.loading = false;
});
}
}
/**
* Delete a permission for a bucket user combination
* @param bucketName Bucket to delete
* @param uid ID of grantee of the permission
*/
function deletePermission(bucketName: string, uid: string) {
if (!formState.loading) {
formState.loading = true;
BucketPermissionsService.bucketPermissionsDeletePermissionForBucket(
bucketName,
uid
)
.then(() => {
permissionDeleted.value = true;
permissionModal?.hide();
successToast?.show(); successToast?.show();
emit("permission-deleted", bucketName);
}) })
.catch((err) => { .catch(() => {
formState.error = true; formState.error = true;
console.error(err);
}) })
.finally(() => { .finally(() => {
formState.loading = false; formState.loading = false;
...@@ -220,7 +263,7 @@ function formSubmit() { ...@@ -220,7 +263,7 @@ function formSubmit() {
// Lifecycle Hooks // Lifecycle Hooks
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
onMounted(() => { onMounted(() => {
createPermissionModal = new Modal("#" + props.modalID); permissionModal = new Modal("#" + props.modalID);
successToast = new Toast("#" + "toast-" + toastID, { autohide: true }); successToast = new Toast("#" + "toast-" + toastID, { autohide: true });
updatePermission(); updatePermission();
}); });
...@@ -235,12 +278,14 @@ onMounted(() => { ...@@ -235,12 +278,14 @@ onMounted(() => {
class="toast text-bg-success align-items-center border-0" class="toast text-bg-success align-items-center border-0"
data-bs-autohide="false" data-bs-autohide="false"
:id="'toast-' + toastID" :id="'toast-' + toastID"
v-on="{ 'hidden.bs.toast': toastHidden }"
> >
<div class="d-flex"> <div class="d-flex">
<div class="toast-body"> <div class="toast-body">
Successfully Successfully
<span v-if="editPermission">created</span> <span v-if="permissionDeleted">deleted</span>
<span v-else>edited</span> <span v-else-if="editPermission">edited</span>
<span v-else>created</span>
Permission Permission
</div> </div>
<button <button
...@@ -265,8 +310,19 @@ onMounted(() => { ...@@ -265,8 +310,19 @@ onMounted(() => {
>Edit Permission >Edit Permission
</template> </template>
<template v-slot:header v-else> Create new Permission </template> <template v-slot:header v-else> Create new Permission </template>
<template v-slot:extra-button v-if="formState.readonly && props.editable"> <template v-slot:extra-button>
<bootstrap-icon
v-if="props.deletable"
icon="trash-fill"
:height="15"
:width="15"
fill="currentColor"
class="me-2"
:class="{ 'delete-icon': !formState.loading }"
@click="deletePermission(permission.bucket_name, permission.uid)"
/>
<bootstrap-icon <bootstrap-icon
v-if="formState.readonly && props.editable"
icon="pencil-fill" icon="pencil-fill"
:height="15" :height="15"
:width="15" :width="15"
...@@ -438,4 +494,12 @@ onMounted(() => { ...@@ -438,4 +494,12 @@ onMounted(() => {
.pseudo-link:hover { .pseudo-link:hover {
color: var(--bs-primary); color: var(--bs-primary);
} }
.delete-icon {
color: var(--bs-secondary);
cursor: pointer;
}
.delete-icon:hover {
color: var(--bs-danger);
}
</style> </style>
...@@ -56,13 +56,19 @@ function addBucket(bucket: BucketOut) { ...@@ -56,13 +56,19 @@ function addBucket(bucket: BucketOut) {
function deleteBucket(bucketName: string) { function deleteBucket(bucketName: string) {
BucketService.bucketDeleteBucket(bucketName).then(() => { BucketService.bucketDeleteBucket(bucketName).then(() => {
router.push({ name: "buckets" }); bucketDeleted(bucketName);
bucketsState.buckets = bucketsState.buckets.filter(
(bucket) => bucket.name !== bucketName
);
}); });
} }
function bucketDeleted(bucketName: string) {
if (bucketsState.buckets.map((bucket) => bucket.name).includes(bucketName)) {
router.push({ name: "buckets" });
}
bucketsState.buckets = bucketsState.buckets.filter(
(bucket) => bucket.name !== bucketName
);
}
onMounted(() => { onMounted(() => {
fetchBuckets(); fetchBuckets();
}); });
...@@ -113,7 +119,7 @@ onMounted(() => { ...@@ -113,7 +119,7 @@ onMounted(() => {
/> />
</div> </div>
<div class="list-group overflow-scroll mt-3"> <div class="list-group mt-3">
<div v-if="!bucketsState.loading"> <div v-if="!bucketsState.loading">
<bucket-list-item <bucket-list-item
v-for="bucket in bucketsState.buckets" v-for="bucket in bucketsState.buckets"
...@@ -126,6 +132,7 @@ onMounted(() => { ...@@ -126,6 +132,7 @@ onMounted(() => {
:loading="false" :loading="false"
:permission="bucketsState.permissions[bucket.name]" :permission="bucketsState.permissions[bucket.name]"
@delete-bucket="deleteBucket" @delete-bucket="deleteBucket"
@permission-deleted="(bucketName) => bucketDeleted(bucketName)"
/> />
</div> </div>
<div v-else> <div v-else>
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment