Added confirmation box to backend delete back.

This commit is contained in:
Abdulmhsen B. A. A.
2024-06-28 21:49:11 +03:00
parent dc4452d7b2
commit f60a5b869a
4 changed files with 136 additions and 34 deletions

View File

@@ -0,0 +1,74 @@
<template>
<div ref="targetEl" :style="`min-height:${fixedMinHeight ? fixedMinHeight : (minHeight ?? min_height)}px`">
<slot v-if="shouldRender"/>
</div>
</template>
<script>
import {nextTick, ref} from 'vue'
import {useIntersectionObserver} from '@vueuse/core'
function onIdle(cb = () => {
}) {
if ("requestIdleCallback" in window) {
window.requestIdleCallback(cb);
} else {
setTimeout(() => nextTick(cb), 300);
}
}
export default {
props: {
renderOnIdle: Boolean,
unrender: Boolean,
minHeight: Number,
unrenderDelay: {
type: Number,
default: 6000,
},
},
setup(props) {
const shouldRender = ref(false);
const targetEl = ref();
const fixedMinHeight = ref(0);
let unrenderTimer;
let renderTimer;
const {stop} = useIntersectionObserver(targetEl, ([{isIntersecting}]) => {
if (isIntersecting) {
// perhaps the user re-scrolled to a component that was set to unrender. In that case stop the un-rendering timer
clearTimeout(unrenderTimer);
// if we're dealing underrndering lets add a waiting period of 200ms before rendering.
// If a component enters the viewport and also leaves it within 200ms it will not render at all.
// This saves work and improves performance when user scrolls very fast
renderTimer = setTimeout(() => (shouldRender.value = true), props.unrender ? 200 : 0);
shouldRender.value = true;
if (!props.unrender) {
stop();
}
} else if (props.unrender) {
// if the component was set to render, cancel that
clearTimeout(renderTimer);
unrenderTimer = setTimeout(() => {
fixedMinHeight.value = targetEl.value.clientHeight;
shouldRender.value = false;
}, props.unrenderDelay);
}
}, {
rootMargin: "600px",
}
);
if (props.renderOnIdle) {
onIdle(() => {
shouldRender.value = true;
if (!props.unrender) {
stop();
}
});
}
return {targetEl, shouldRender, fixedMinHeight};
},
};
</script>

View File

@@ -51,31 +51,46 @@
</ul>
<p>There is no undo operation. This action is irreversible.</p>
<p class="is-bold">
Depending on your hardware speed, the delete operation might take long time. do not interrupt the process,
or close the browser tab. You will be redirected to the backends page automatically once the process is
complete. Otherwise, you might end up with a corrupted database.
</p>
</Message>
<div class="columns is-mobile">
<div class="column is-6">
<p class="control " v-if="!isDeleting">
<NuxtLink to="/backends" class="button is-fullwidth is-primary">
<form @submit.prevent="deleteBackend()">
<div class="card">
<header class="card-header">
<p class="card-header-title">Delete backend</p>
<p class="card-header-icon"><span class="icon"><i class="fas fa-trash"></i></span></p>
</header>
<div class="card-content">
<div class="field">
<label class="label">
To confirm, please write '<code>{{ random_secret }}</code>' in the box below.
</label>
<div class="control">
<input class="input" type="text" v-model="user_secret" placeholder="Enter the secret key"/>
</div>
<p class="help">
<span class="icon has-text-warning"><i class="fas fa-info-circle"></i></span>
Depending on your hardware speed, the delete operation might take long time. do not interrupt the
process, or close the browser tab. You will be redirected to the backends page automatically once the
process is complete. Otherwise, you might end up with a corrupted database.
</p>
</div>
</div>
<footer class="card-footer">
<div class="card-footer-item">
<NuxtLink to="/backends/" class="button is-fullwidth is-primary">
<span class="icon"><i class="fas fa-cancel"></i></span>
<span>Cancel</span>
</NuxtLink>
</p>
</div>
<div class="column">
<p class="control">
<button class="button is-danger is-fullwidth" @click="deleteBackend">
<span class="icon"><i class="fas fa-trash"></i></span>
<span>Yes, Delete it!</span>
</div>
<div class="card-footer-item">
<button class="button is-danger is-fullwidth" type="submit" :disabled="user_secret !== random_secret">
<span class="icon"><i class="fas fa-redo"></i></span>
<span>Proceed</span>
</button>
</p>
</div>
</div>
</footer>
</div>
</Message>
</form>
</div>
</template>
</div>
@@ -83,14 +98,17 @@
<script setup>
import 'assets/css/bulma-switch.css'
import request from '~/utils/request.js'
import Message from "~/components/Message.vue";
import request from '~/utils/request'
import Message from "~/components/Message"
import {makeSecret, notification} from '~/utils/index'
const id = useRoute().params.backend
const error = ref()
const type = ref('')
const isLoading = ref(false)
const isDeleting = ref(false)
const random_secret = ref('')
const user_secret = ref('')
const loadBackend = async () => {
isLoading.value = true
@@ -128,6 +146,11 @@ const loadBackend = async () => {
}
const deleteBackend = async () => {
if (user_secret.value !== random_secret.value) {
notification('error', 'Error', 'Invalid secret key. Please try again.')
return
}
if (!confirm('Last chance! Are you sure you want to delete the backend?')) {
return
}
@@ -170,5 +193,8 @@ const deleteBackend = async () => {
}
}
onMounted(async () => await loadBackend())
onMounted(async () => {
await loadBackend()
random_secret.value = makeSecret(8)
})
</script>

View File

@@ -98,7 +98,7 @@
import 'assets/css/bulma-switch.css'
import request from '~/utils/request'
import Message from '~/components/Message'
import {notification} from '~/utils/index'
import {makeSecret, notification} from '~/utils/index'
const error = ref()
const isResetting = ref(false)
@@ -152,16 +152,6 @@ const resetSystem = async () => {
}
onMounted(() => {
const strLength = 8;
let result = '';
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
let counter = 0;
while (counter < strLength) {
result += characters.charAt(Math.floor(Math.random() * characters.length));
counter += 1;
}
random_secret.value = result
random_secret.value = makeSecret(8)
})
</script>

View File

@@ -404,6 +404,17 @@ const makePagination = (current, last, delta = 5) => {
return pagination;
}
const makeSecret = (len = 8) => {
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
let result = '';
let counter = 0;
while (counter < len) {
result += characters.charAt(Math.floor(Math.random() * characters.length));
counter += 1;
}
return result;
}
export {
r,
ag_set,
@@ -422,4 +433,5 @@ export {
makeName,
makePagination,
TOOLTIP_DATE_FORMAT,
makeSecret,
}