Added confirmation dialog for low interval

A prompt has been added to confirm with the user that they wish to
reduce the interval value to possibly unstable values. A random (pseudo
random) code is generated which they must input in order to confirm
their descision. Failiure to confirm their descision will result in an
error when saving.
As not to annoy the user too much, the promt is only required when it is
detected that the interval value has been changed.

Signed-off-by: Matthew Nickson <mnickson@sidingsmedia.com>
This commit is contained in:
Matthew Nickson 2022-10-01 19:09:24 +01:00
parent dcd723b9ac
commit 8a163eaede
No known key found for this signature in database
GPG key ID: BF229DCFD4748E05
2 changed files with 75 additions and 1 deletions

View file

@ -526,4 +526,10 @@ export default {
"Go back to the previous page.": "Go back to the previous page.",
"Coming Soon": "Coming Soon",
wayToGetClickSendSMSToken: "You can get API Username and API Key from {0} .",
lowIntervalWarning: "Are you sure want to set the interval value below 20 seconds? This is NOT supported and may make Uptime Kuma unstable.",
"Please use this option carefully!": "Please use this option carefully!",
enterConfirmationString: "To confirm, please enter the following: {0}",
confirmLowIntervalRequired: "You must confirm you want to use such a low interval before saving.",
errCodeMismatch: "Confirmation code did not match",
"Confirmed": "Confirmed",
};

View file

@ -160,7 +160,16 @@
<!-- Interval -->
<div class="my-3">
<label for="interval" class="form-label">{{ $t("Heartbeat Interval") }} ({{ $t("checkEverySecond", [ monitor.interval ]) }})</label>
<input id="interval" v-model="monitor.interval" type="number" class="form-control" required min="1" step="1">
<input
id="interval"
v-model="monitor.interval"
type="number"
class="form-control"
required
min="1" step="1"
@focus="lowIntervalConfirmation.editedValue=true"
@blur="checkIntervalValue"
>
<div v-if="monitor.interval < 20" class="form-text">
{{ $t("minimumIntervalWarning") }}
</div>
@ -371,6 +380,24 @@
<NotificationDialog ref="notificationDialog" @added="addedNotification" />
<ProxyDialog ref="proxyDialog" @added="addedProxy" />
<Confirm ref="confirmLowIntervalValue" btn-style="btn-danger" :yes-text="$t('Confirm')" :no-text="$t('Cancel')" @yes="validateConfirmationString">
<p>{{ $t("lowIntervalWarning") }}</p>
<p>{{ $t("Please use this option carefully!") }}</p>
<div class="mb-3">
<i18n-t tag="label" keypath="enterConfirmationString" for="confirmation-string" class="form-label user-select-none">
{{ lowIntervalConfirmation.testString }}
</i18n-t>
<input
id="confirmation-string"
v-model="lowIntervalConfirmation.userString"
type="text"
class="form-control"
required
/>
</div>
</Confirm>
</div>
</transition>
</template>
@ -379,6 +406,7 @@
import VueMultiselect from "vue-multiselect";
import { useToast } from "vue-toastification";
import CopyableInput from "../components/CopyableInput.vue";
import Confirm from "../components/Confirm.vue";
import NotificationDialog from "../components/NotificationDialog.vue";
import ProxyDialog from "../components/ProxyDialog.vue";
import TagsManager from "../components/TagsManager.vue";
@ -390,6 +418,7 @@ export default {
components: {
ProxyDialog,
CopyableInput,
Confirm,
NotificationDialog,
TagsManager,
VueMultiselect,
@ -404,6 +433,12 @@ export default {
},
acceptedStatusCodeOptions: [],
dnsresolvetypeOptions: [],
lowIntervalConfirmation: {
testString: "",
userString: "",
confirmed: false,
editedValue: false,
},
// Source: https://digitalfortress.tech/tips/top-15-commonly-used-regex/
ipRegexPattern: "((^\\s*((([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))\\s*$)|(^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:)))(%.+)?\\s*$))",
@ -526,6 +561,7 @@ export default {
this.acceptedStatusCodeOptions = acceptedStatusCodeOptions;
this.dnsresolvetypeOptions = dnsresolvetypeOptions;
this.lowIntervalConfirmation.testString = Math.random().toString(36).substring(2, 9);
},
methods: {
init() {
@ -604,6 +640,28 @@ export default {
return true;
},
/**
* Show popup if the interval value is less than 20
*/
checkIntervalValue() {
if (this.monitor.interval < 20) {
this.$refs.confirmLowIntervalValue.show();
}
},
/**
* Check that the user inputed code is correct
*/
validateConfirmationString() {
if (this.lowIntervalConfirmation.testString === this.lowIntervalConfirmation.userString) {
this.lowIntervalConfirmation.confirmed = true;
toast.success(this.$t("Confirmed"));
} else {
this.lowIntervalConfirmation.confirmed = false;
toast.error(this.$t("errCodeMismatch"));
}
},
async submit() {
this.processing = true;
@ -612,6 +670,16 @@ export default {
return;
}
// Check user has confirmed use of low interval value. Only
// do this if the interval value has changed since last save
if (this.lowIntervalConfirmation.editedValue && this.monitor.interval < 20 && !this.lowIntervalConfirmation.confirmed) {
toast.error(this.$t("confirmLowIntervalRequired"));
this.processing = false;
return;
}
this.lowIntervalConfirmation.confirmed = false;
this.lowIntervalConfirmation.editedValue = false;
// Beautify the JSON format
if (this.monitor.body) {
this.monitor.body = JSON.stringify(JSON.parse(this.monitor.body), null, 4);