feat: Updates to dashboard and delete confirmations
All checks were successful
Build and Push App Image / build-and-push (push) Successful in 34s
All checks were successful
Build and Push App Image / build-and-push (push) Successful in 34s
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<teleport to="body">
|
||||
<teleport v-if="!showDeleteConfirmModal" to="body">
|
||||
<div class="modal fade show d-block" tabindex="-1" role="dialog" aria-modal="true" @click.self="emit('close')">
|
||||
<div class="modal-dialog modal-lg modal-dialog-centered" role="document">
|
||||
<div class="modal-content">
|
||||
@@ -76,13 +76,17 @@
|
||||
|
||||
<template v-if="canDeleteSpace">
|
||||
<hr />
|
||||
<div class="border border-danger rounded p-3 mt-3">
|
||||
<h6 class="text-danger mb-1">Danger Zone</h6>
|
||||
<p class="text-muted small mb-3">Permanently delete this space and all its notes, categories, and members. This cannot be undone.</p>
|
||||
<button class="btn btn-danger btn-sm" :disabled="deleting" @click="deleteSpace">
|
||||
<DangerZonePanel
|
||||
class="mt-4"
|
||||
title-id="danger-zone-title"
|
||||
title="Danger Zone"
|
||||
description="Permanently delete this space and all its notes, categories, and members. This cannot be undone."
|
||||
>
|
||||
<button class="btn btn-danger" type="button" :disabled="deleting" @click="requestDeleteSpace">
|
||||
<i class="mdi mdi-delete-outline me-1" aria-hidden="true"></i>
|
||||
{{ deleting ? "Deleting..." : "Delete Space" }}
|
||||
</button>
|
||||
</div>
|
||||
</DangerZonePanel>
|
||||
</template>
|
||||
|
||||
<div v-if="error" class="alert alert-danger mt-3 mb-0">{{ error }}</div>
|
||||
@@ -93,12 +97,23 @@
|
||||
</div>
|
||||
<div class="modal-backdrop fade show"></div>
|
||||
</teleport>
|
||||
|
||||
<ConfirmActionModal
|
||||
:visible="showDeleteConfirmModal"
|
||||
:title="deleteConfirmTitle"
|
||||
:message="deleteConfirmMessage"
|
||||
:busy="deleteConfirmBusy"
|
||||
@close="closeDeleteConfirmModal"
|
||||
@confirm="confirmDeleteAction"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed, ref, watch } from "vue";
|
||||
import apiClient from "../services/apiClient";
|
||||
import { useAuthStore } from "../stores/authStore";
|
||||
import ConfirmActionModal from "./ConfirmActionModal.vue";
|
||||
import DangerZonePanel from "./DangerZonePanel.vue";
|
||||
|
||||
const props = defineProps({
|
||||
space: {
|
||||
@@ -130,6 +145,20 @@ const success = ref("");
|
||||
const memberForm = ref({ user_id: "" });
|
||||
const canViewMembers = computed(() => authStore.hasSpacePermission(props.space, "settings.member.view"));
|
||||
const canManageMembers = computed(() => authStore.hasSpacePermission(props.space, "settings.member.manage"));
|
||||
const showDeleteConfirmModal = ref(false);
|
||||
const deleteConfirmBusy = ref(false);
|
||||
const deleteConfirmIntent = ref({
|
||||
type: "",
|
||||
payload: null,
|
||||
});
|
||||
const deleteConfirmTitle = computed(() => (deleteConfirmIntent.value.type === "member" ? "Remove Member" : "Delete Space"));
|
||||
const deleteConfirmMessage = computed(() => {
|
||||
if (deleteConfirmIntent.value.type === "member") {
|
||||
const memberName = deleteConfirmIntent.value.payload?.username || deleteConfirmIntent.value.payload?.user_id || "this member";
|
||||
return `Remove member "${memberName}" from this space?`;
|
||||
}
|
||||
return `Permanently delete space "${props.space.name}"? All notes, categories, and members will be removed. This cannot be undone.`;
|
||||
});
|
||||
|
||||
watch(
|
||||
() => props.space,
|
||||
@@ -224,13 +253,24 @@ const addMember = async () => {
|
||||
}
|
||||
};
|
||||
|
||||
const removeMember = async (member) => {
|
||||
const removeMember = (member) => {
|
||||
if (!canManageMembers.value) {
|
||||
return;
|
||||
}
|
||||
|
||||
const memberName = member?.username || member?.user_id;
|
||||
if (!member?.user_id || !confirm(`Remove member "${memberName}" from this space?`)) {
|
||||
if (!member?.user_id) {
|
||||
return;
|
||||
}
|
||||
|
||||
deleteConfirmIntent.value = {
|
||||
type: "member",
|
||||
payload: member,
|
||||
};
|
||||
showDeleteConfirmModal.value = true;
|
||||
};
|
||||
|
||||
const removeMemberConfirmed = async (member) => {
|
||||
if (!member?.user_id) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -251,10 +291,15 @@ if (canViewMembers.value) {
|
||||
Promise.all([loadMembers(), loadUserOptions()]);
|
||||
}
|
||||
|
||||
const deleteSpace = async () => {
|
||||
if (!confirm(`Permanently delete space "${props.space.name}"? All notes, categories, and members will be removed. This cannot be undone.`)) {
|
||||
return;
|
||||
}
|
||||
const requestDeleteSpace = () => {
|
||||
deleteConfirmIntent.value = {
|
||||
type: "space",
|
||||
payload: props.space,
|
||||
};
|
||||
showDeleteConfirmModal.value = true;
|
||||
};
|
||||
|
||||
const deleteSpaceConfirmed = async () => {
|
||||
deleting.value = true;
|
||||
clearMessages();
|
||||
try {
|
||||
@@ -262,8 +307,49 @@ const deleteSpace = async () => {
|
||||
emit("deleted", props.space);
|
||||
} catch (e) {
|
||||
error.value = e.response?.data || "Failed to delete space.";
|
||||
throw e;
|
||||
} finally {
|
||||
deleting.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
const closeDeleteConfirmModal = () => {
|
||||
if (deleteConfirmBusy.value) {
|
||||
return;
|
||||
}
|
||||
|
||||
showDeleteConfirmModal.value = false;
|
||||
deleteConfirmIntent.value = {
|
||||
type: "",
|
||||
payload: null,
|
||||
};
|
||||
};
|
||||
|
||||
const confirmDeleteAction = async () => {
|
||||
if (deleteConfirmBusy.value) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { type, payload } = deleteConfirmIntent.value;
|
||||
if (!type) {
|
||||
return;
|
||||
}
|
||||
|
||||
deleteConfirmBusy.value = true;
|
||||
try {
|
||||
if (type === "member") {
|
||||
await removeMemberConfirmed(payload);
|
||||
} else if (type === "space") {
|
||||
await deleteSpaceConfirmed();
|
||||
}
|
||||
|
||||
showDeleteConfirmModal.value = false;
|
||||
deleteConfirmIntent.value = {
|
||||
type: "",
|
||||
payload: null,
|
||||
};
|
||||
} finally {
|
||||
deleteConfirmBusy.value = false;
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user