mirror of
https://github.com/louislam/uptime-kuma.git
synced 2024-11-23 18:06:14 +03:00
Merge pull request #1550 from Computroniks/jsdoc-for-src
JSDoc for src/*/*
This commit is contained in:
commit
a3b94aa532
41 changed files with 543 additions and 31 deletions
|
@ -25,10 +25,12 @@ export default {
|
|||
CertificateInfoRow,
|
||||
},
|
||||
props: {
|
||||
/** Object representing certificate */
|
||||
certInfo: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
/** Is the TLS certificate valid? */
|
||||
valid: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
|
|
|
@ -56,12 +56,19 @@ export default {
|
|||
Datetime,
|
||||
},
|
||||
props: {
|
||||
/** Object representing certificate */
|
||||
cert: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* Format the subject of the certificate
|
||||
* @param {Object} subject Object representing the certificates
|
||||
* subject
|
||||
* @returns {string}
|
||||
*/
|
||||
formatSubject(subject) {
|
||||
if (subject.O && subject.CN && subject.C) {
|
||||
return `${subject.CN} - ${subject.O} (${subject.C})`;
|
||||
|
|
|
@ -29,14 +29,17 @@ import { Modal } from "bootstrap";
|
|||
|
||||
export default {
|
||||
props: {
|
||||
/** Style of button */
|
||||
btnStyle: {
|
||||
type: String,
|
||||
default: "btn-primary",
|
||||
},
|
||||
/** Text to use as yes */
|
||||
yesText: {
|
||||
type: String,
|
||||
default: "Yes", // TODO: No idea what to translate this
|
||||
},
|
||||
/** Text to use as no */
|
||||
noText: {
|
||||
type: String,
|
||||
default: "No",
|
||||
|
@ -50,9 +53,13 @@ export default {
|
|||
this.modal = new Modal(this.$refs.modal);
|
||||
},
|
||||
methods: {
|
||||
/** Show the confirm dialog */
|
||||
show() {
|
||||
this.modal.show();
|
||||
},
|
||||
/**
|
||||
* @emits string "yes" Notify the parent when Yes is pressed
|
||||
*/
|
||||
yes() {
|
||||
this.$emit("yes");
|
||||
},
|
||||
|
|
|
@ -25,33 +25,41 @@ let timeout;
|
|||
|
||||
export default {
|
||||
props: {
|
||||
/** ID of this input */
|
||||
id: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
/** Type of input */
|
||||
type: {
|
||||
type: String,
|
||||
default: "text"
|
||||
},
|
||||
/** The value of the input */
|
||||
modelValue: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
/** A placeholder to use */
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
/** Should the field auto complete */
|
||||
autocomplete: {
|
||||
type: String,
|
||||
default: undefined,
|
||||
},
|
||||
/** Is the input required? */
|
||||
required: {
|
||||
type: Boolean
|
||||
},
|
||||
/** Should the input be read only? */
|
||||
readonly: {
|
||||
type: String,
|
||||
default: undefined,
|
||||
},
|
||||
/** Is the input disabled? */
|
||||
disabled: {
|
||||
type: String,
|
||||
default: undefined,
|
||||
|
@ -79,14 +87,21 @@ export default {
|
|||
},
|
||||
methods: {
|
||||
|
||||
/** Show the input */
|
||||
showInput() {
|
||||
this.visibility = "text";
|
||||
},
|
||||
|
||||
/** Hide the input */
|
||||
hideInput() {
|
||||
this.visibility = "password";
|
||||
},
|
||||
|
||||
/**
|
||||
* Copy the provided text to the users clipboard
|
||||
* @param {string} textToCopy
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
copyToClipboard(textToCopy) {
|
||||
this.icon = "check";
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ import { sleep } from "../util.ts";
|
|||
export default {
|
||||
|
||||
props: {
|
||||
/** Value to count */
|
||||
value: {
|
||||
type: [ String, Number ],
|
||||
default: 0,
|
||||
|
@ -18,6 +19,7 @@ export default {
|
|||
type: Number,
|
||||
default: 0.3,
|
||||
},
|
||||
/** Unit of the value */
|
||||
unit: {
|
||||
type: String,
|
||||
default: "ms",
|
||||
|
@ -43,9 +45,7 @@ export default {
|
|||
let frames = 12;
|
||||
let step = Math.floor(diff / frames);
|
||||
|
||||
if (isNaN(step) || ! this.isNum || (diff > 0 && step < 1) || (diff < 0 && step > 1) || diff === 0) {
|
||||
// Lazy to NOT this condition, hahaha.
|
||||
} else {
|
||||
if (! (isNaN(step) || ! this.isNum || (diff > 0 && step < 1) || (diff < 0 && step > 1) || diff === 0)) {
|
||||
for (let i = 1; i < frames; i++) {
|
||||
this.output += step;
|
||||
await sleep(15);
|
||||
|
|
|
@ -13,10 +13,12 @@ dayjs.extend(relativeTime);
|
|||
|
||||
export default {
|
||||
props: {
|
||||
/** Value of date time */
|
||||
value: {
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
/** Should only the date be displayed? */
|
||||
dateOnly: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
|
|
|
@ -17,14 +17,17 @@
|
|||
|
||||
export default {
|
||||
props: {
|
||||
/** Size of the heartbeat bar */
|
||||
size: {
|
||||
type: String,
|
||||
default: "big",
|
||||
},
|
||||
/** ID of the monitor */
|
||||
monitorId: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
/** Array of the monitors heartbeats */
|
||||
heartbeatList: {
|
||||
type: Array,
|
||||
default: null,
|
||||
|
@ -160,12 +163,19 @@ export default {
|
|||
this.resize();
|
||||
},
|
||||
methods: {
|
||||
/** Resize the heartbeat bar */
|
||||
resize() {
|
||||
if (this.$refs.wrap) {
|
||||
this.maxBeat = Math.floor(this.$refs.wrap.clientWidth / (this.beatWidth + this.beatMargin * 2));
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the title of the beat.
|
||||
* Used as the hover tooltip on the heartbeat bar.
|
||||
* @param {Object} beat Beat to get title from
|
||||
* @returns {string}
|
||||
*/
|
||||
getBeatTitle(beat) {
|
||||
return `${this.$root.datetime(beat.time)}` + ((beat.msg) ? ` - ${beat.msg}` : "");
|
||||
},
|
||||
|
|
|
@ -24,25 +24,31 @@
|
|||
<script>
|
||||
export default {
|
||||
props: {
|
||||
/** The value of the input */
|
||||
modelValue: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
/** A placeholder to use */
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
/** Maximum length of the input */
|
||||
maxlength: {
|
||||
type: Number,
|
||||
default: 255
|
||||
},
|
||||
/** Should the field auto complete */
|
||||
autocomplete: {
|
||||
type: String,
|
||||
default: undefined,
|
||||
},
|
||||
/** Is the input required? */
|
||||
required: {
|
||||
type: Boolean
|
||||
},
|
||||
/** Should the input be read only? */
|
||||
readonly: {
|
||||
type: String,
|
||||
default: undefined,
|
||||
|
@ -68,9 +74,11 @@ export default {
|
|||
|
||||
},
|
||||
methods: {
|
||||
/** Show users input in plain text */
|
||||
showInput() {
|
||||
this.visibility = "text";
|
||||
},
|
||||
/** Censor users input */
|
||||
hideInput() {
|
||||
this.visibility = "password";
|
||||
},
|
||||
|
|
|
@ -55,6 +55,7 @@ export default {
|
|||
};
|
||||
},
|
||||
methods: {
|
||||
/** Submit the user details and attempt to log in */
|
||||
submit() {
|
||||
this.processing = true;
|
||||
|
||||
|
|
|
@ -58,6 +58,7 @@ export default {
|
|||
Tag,
|
||||
},
|
||||
props: {
|
||||
/** Should the scrollbar be shown */
|
||||
scrollbar: {
|
||||
type: Boolean,
|
||||
},
|
||||
|
@ -136,6 +137,7 @@ export default {
|
|||
window.removeEventListener("scroll", this.onScroll);
|
||||
},
|
||||
methods: {
|
||||
/** Handle user scroll */
|
||||
onScroll() {
|
||||
if (window.top.scrollY <= 133) {
|
||||
this.windowTop = window.top.scrollY;
|
||||
|
@ -143,9 +145,15 @@ export default {
|
|||
this.windowTop = 133;
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Get URL of monitor
|
||||
* @param {number} id ID of monitor
|
||||
* @returns {string} Relative URL of monitor
|
||||
*/
|
||||
monitorURL(id) {
|
||||
return getMonitorRelativeURL(id);
|
||||
},
|
||||
/** Clear the search bar */
|
||||
clearSearchText() {
|
||||
this.searchText = "";
|
||||
}
|
||||
|
|
|
@ -125,11 +125,16 @@ export default {
|
|||
},
|
||||
methods: {
|
||||
|
||||
/** Show dialog to confirm deletion */
|
||||
deleteConfirm() {
|
||||
this.modal.hide();
|
||||
this.$refs.confirmDelete.show();
|
||||
},
|
||||
|
||||
/**
|
||||
* Show settings for specified notification
|
||||
* @param {number} notificationID ID of notification to show
|
||||
*/
|
||||
show(notificationID) {
|
||||
if (notificationID) {
|
||||
this.id = notificationID;
|
||||
|
@ -152,6 +157,7 @@ export default {
|
|||
this.modal.show();
|
||||
},
|
||||
|
||||
/** Submit the form to the server */
|
||||
submit() {
|
||||
this.processing = true;
|
||||
this.$root.getSocket().emit("addNotification", this.notification, this.id, (res) => {
|
||||
|
@ -170,6 +176,7 @@ export default {
|
|||
});
|
||||
},
|
||||
|
||||
/** Test the notification endpoint */
|
||||
test() {
|
||||
this.processing = true;
|
||||
this.$root.getSocket().emit("testNotification", this.notification, (res) => {
|
||||
|
@ -178,6 +185,7 @@ export default {
|
|||
});
|
||||
},
|
||||
|
||||
/** Delete the notification endpoint */
|
||||
deleteNotification() {
|
||||
this.processing = true;
|
||||
this.$root.getSocket().emit("deleteNotification", this.id, (res) => {
|
||||
|
@ -190,6 +198,7 @@ export default {
|
|||
});
|
||||
},
|
||||
/**
|
||||
* Get a unique default name for the notification
|
||||
* @param {keyof NotificationFormList} notificationKey
|
||||
* @return {string}
|
||||
*/
|
||||
|
|
|
@ -35,6 +35,7 @@ Chart.register(LineController, BarController, LineElement, PointElement, TimeSca
|
|||
export default {
|
||||
components: { LineChart },
|
||||
props: {
|
||||
/** ID of monitor */
|
||||
monitorId: {
|
||||
type: Number,
|
||||
required: true,
|
||||
|
|
|
@ -130,11 +130,16 @@ export default {
|
|||
},
|
||||
|
||||
methods: {
|
||||
/** Show dialog to confirm deletion */
|
||||
deleteConfirm() {
|
||||
this.modal.hide();
|
||||
this.$refs.confirmDelete.show();
|
||||
},
|
||||
|
||||
/**
|
||||
* Show settings for specified proxy
|
||||
* @param {number} proxyID ID of proxy to show
|
||||
*/
|
||||
show(proxyID) {
|
||||
if (proxyID) {
|
||||
this.id = proxyID;
|
||||
|
@ -163,6 +168,7 @@ export default {
|
|||
this.modal.show();
|
||||
},
|
||||
|
||||
/** Submit form data for saving */
|
||||
submit() {
|
||||
this.processing = true;
|
||||
this.$root.getSocket().emit("addProxy", this.proxy, this.id, (res) => {
|
||||
|
@ -180,6 +186,7 @@ export default {
|
|||
});
|
||||
},
|
||||
|
||||
/** Delete this proxy */
|
||||
deleteProxy() {
|
||||
this.processing = true;
|
||||
this.$root.getSocket().emit("deleteProxy", this.id, (res) => {
|
||||
|
|
|
@ -72,10 +72,12 @@ export default {
|
|||
Tag,
|
||||
},
|
||||
props: {
|
||||
/** Are we in edit mode? */
|
||||
editMode: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
/** Should tags be shown? */
|
||||
showTags: {
|
||||
type: Boolean,
|
||||
}
|
||||
|
@ -94,10 +96,20 @@ export default {
|
|||
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* Remove the specified group
|
||||
* @param {number} index Index of group to remove
|
||||
*/
|
||||
removeGroup(index) {
|
||||
this.$root.publicGroupList.splice(index, 1);
|
||||
},
|
||||
|
||||
/**
|
||||
* Remove a monitor from a group
|
||||
* @param {number} groupIndex Index of group to remove monitor
|
||||
* from
|
||||
* @param {number} index Index of monitor to remove
|
||||
*/
|
||||
removeMonitor(groupIndex, index) {
|
||||
this.$root.publicGroupList[groupIndex].monitorList.splice(index, 1);
|
||||
},
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
<script>
|
||||
export default {
|
||||
props: {
|
||||
/** Current status of monitor */
|
||||
status: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
|
|
|
@ -20,14 +20,20 @@
|
|||
<script>
|
||||
export default {
|
||||
props: {
|
||||
/** Object representing tag */
|
||||
item: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
/** Function to remove tag */
|
||||
remove: {
|
||||
type: Function,
|
||||
default: null,
|
||||
},
|
||||
/**
|
||||
* Size of tag
|
||||
* @values normal, small
|
||||
*/
|
||||
size: {
|
||||
type: String,
|
||||
default: "normal",
|
||||
|
|
|
@ -139,6 +139,7 @@ export default {
|
|||
VueMultiselect,
|
||||
},
|
||||
props: {
|
||||
/** Array of tags to be pre-selected */
|
||||
preSelectedTags: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
|
@ -241,9 +242,11 @@ export default {
|
|||
this.getExistingTags();
|
||||
},
|
||||
methods: {
|
||||
/** Show the add tag dialog */
|
||||
showAddDialog() {
|
||||
this.modal.show();
|
||||
},
|
||||
/** Get all existing tags */
|
||||
getExistingTags() {
|
||||
this.$root.getSocket().emit("getTags", (res) => {
|
||||
if (res.ok) {
|
||||
|
@ -253,6 +256,10 @@ export default {
|
|||
}
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Delete the specified tag
|
||||
* @param {Object} tag Object representing tag to delete
|
||||
*/
|
||||
deleteTag(item) {
|
||||
if (item.new) {
|
||||
// Undo Adding a new Tag
|
||||
|
@ -262,6 +269,13 @@ export default {
|
|||
this.deleteTags.push(item);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Get colour of text inside the tag
|
||||
* @param {Object} option The tag that needs to be displayed.
|
||||
* Defaults to "white" unless the tag has no color, which will
|
||||
* then return the body color (based on application theme)
|
||||
* @returns string
|
||||
*/
|
||||
textColor(option) {
|
||||
if (option.color) {
|
||||
return "white";
|
||||
|
@ -269,6 +283,7 @@ export default {
|
|||
return this.$root.theme === "light" ? "var(--bs-body-color)" : "inherit";
|
||||
}
|
||||
},
|
||||
/** Add a draft tag */
|
||||
addDraftTag() {
|
||||
console.log("Adding Draft Tag: ", this.newDraftTag);
|
||||
if (this.newDraftTag.select != null) {
|
||||
|
@ -296,6 +311,7 @@ export default {
|
|||
}
|
||||
this.clearDraftTag();
|
||||
},
|
||||
/** Remove a draft tag */
|
||||
clearDraftTag() {
|
||||
this.newDraftTag = {
|
||||
name: null,
|
||||
|
@ -307,26 +323,51 @@ export default {
|
|||
};
|
||||
this.modal.hide();
|
||||
},
|
||||
/**
|
||||
* Add a tag asynchronously
|
||||
* @param {Object} newTag Object representing new tag to add
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
addTagAsync(newTag) {
|
||||
return new Promise((resolve) => {
|
||||
this.$root.getSocket().emit("addTag", newTag, resolve);
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Add a tag to a monitor asynchronously
|
||||
* @param {number} tagId ID of tag to add
|
||||
* @param {number} monitorId ID of monitor to add tag to
|
||||
* @param {string} value Value of tag
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
addMonitorTagAsync(tagId, monitorId, value) {
|
||||
return new Promise((resolve) => {
|
||||
this.$root.getSocket().emit("addMonitorTag", tagId, monitorId, value, resolve);
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Delete a tag from a monitor asynchronously
|
||||
* @param {number} tagId ID of tag to remove
|
||||
* @param {number} monitorId ID of monitor to remove tag from
|
||||
* @param {string} value Value of tag
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
deleteMonitorTagAsync(tagId, monitorId, value) {
|
||||
return new Promise((resolve) => {
|
||||
this.$root.getSocket().emit("deleteMonitorTag", tagId, monitorId, value, resolve);
|
||||
});
|
||||
},
|
||||
/** Handle pressing Enter key when inside the modal */
|
||||
onEnter() {
|
||||
if (!this.validateDraftTag.invalid) {
|
||||
this.addDraftTag();
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Submit the form data
|
||||
* @param {number} monitorId ID of monitor this change affects
|
||||
* @returns {void}
|
||||
*/
|
||||
async submit(monitorId) {
|
||||
console.log(`Submitting tag changes for monitor ${monitorId}...`);
|
||||
this.processing = true;
|
||||
|
|
|
@ -29,10 +29,12 @@
|
|||
<script>
|
||||
export default {
|
||||
props: {
|
||||
/** Heading of the section */
|
||||
heading: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
/** Should the section be open by default? */
|
||||
defaultOpen: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
|
|
|
@ -100,18 +100,22 @@ export default {
|
|||
this.getStatus();
|
||||
},
|
||||
methods: {
|
||||
/** Show the dialog */
|
||||
show() {
|
||||
this.modal.show();
|
||||
},
|
||||
|
||||
/** Show dialog to confirm enabling 2FA */
|
||||
confirmEnableTwoFA() {
|
||||
this.$refs.confirmEnableTwoFA.show();
|
||||
},
|
||||
|
||||
/** Show dialog to confirm disabling 2FA */
|
||||
confirmDisableTwoFA() {
|
||||
this.$refs.confirmDisableTwoFA.show();
|
||||
},
|
||||
|
||||
/** Prepare 2FA configuration */
|
||||
prepare2FA() {
|
||||
this.processing = true;
|
||||
|
||||
|
@ -126,6 +130,7 @@ export default {
|
|||
});
|
||||
},
|
||||
|
||||
/** Save the current 2FA configuration */
|
||||
save2FA() {
|
||||
this.processing = true;
|
||||
|
||||
|
@ -143,6 +148,7 @@ export default {
|
|||
});
|
||||
},
|
||||
|
||||
/** Disable 2FA for this user */
|
||||
disable2FA() {
|
||||
this.processing = true;
|
||||
|
||||
|
@ -160,6 +166,7 @@ export default {
|
|||
});
|
||||
},
|
||||
|
||||
/** Verify the token generated by the user */
|
||||
verifyToken() {
|
||||
this.$root.getSocket().emit("verifyToken", this.token, this.currentPassword, (res) => {
|
||||
if (res.ok) {
|
||||
|
@ -170,6 +177,7 @@ export default {
|
|||
});
|
||||
},
|
||||
|
||||
/** Get current status of 2FA */
|
||||
getStatus() {
|
||||
this.$root.getSocket().emit("twoFAStatus", (res) => {
|
||||
if (res.ok) {
|
||||
|
|
|
@ -5,14 +5,17 @@
|
|||
<script>
|
||||
export default {
|
||||
props: {
|
||||
/** Monitor this represents */
|
||||
monitor: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
/** Type of monitor */
|
||||
type: {
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
/** Is this a pill? */
|
||||
pill: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
|
|
|
@ -133,10 +133,15 @@ export default {
|
|||
},
|
||||
|
||||
methods: {
|
||||
/**
|
||||
* Show the confimation dialog confirming the configuration
|
||||
* be imported
|
||||
*/
|
||||
confirmImport() {
|
||||
this.$refs.confirmImport.show();
|
||||
},
|
||||
|
||||
/** Download a backup of the configuration */
|
||||
downloadBackup() {
|
||||
let time = dayjs().format("YYYY_MM_DD-hh_mm_ss");
|
||||
let fileName = `Uptime_Kuma_Backup_${time}.json`;
|
||||
|
@ -157,6 +162,10 @@ export default {
|
|||
downloadItem.click();
|
||||
},
|
||||
|
||||
/**
|
||||
* Import the specified backup file
|
||||
* @returns {?string}
|
||||
*/
|
||||
importBackup() {
|
||||
this.processing = true;
|
||||
let uploadItem = document.getElementById("import-backend").files;
|
||||
|
|
|
@ -178,10 +178,12 @@ export default {
|
|||
},
|
||||
|
||||
methods: {
|
||||
/** Save the settings */
|
||||
saveGeneral() {
|
||||
localStorage.timezone = this.$root.userTimezone;
|
||||
this.saveSettings();
|
||||
},
|
||||
/** Get the base URL of the application */
|
||||
autoGetPrimaryBaseURL() {
|
||||
this.settings.primaryBaseURL = location.protocol + "//" + location.host;
|
||||
},
|
||||
|
|
|
@ -90,6 +90,7 @@ export default {
|
|||
},
|
||||
|
||||
methods: {
|
||||
/** Get the current size of the database */
|
||||
loadDatabaseSize() {
|
||||
log.debug("monitorhistory", "load database size");
|
||||
this.$root.getSocket().emit("getDatabaseSize", (res) => {
|
||||
|
@ -102,6 +103,7 @@ export default {
|
|||
});
|
||||
},
|
||||
|
||||
/** Request that the database is shrunk */
|
||||
shrinkDatabase() {
|
||||
this.$root.getSocket().emit("shrinkDatabase", (res) => {
|
||||
if (res.ok) {
|
||||
|
@ -113,10 +115,12 @@ export default {
|
|||
});
|
||||
},
|
||||
|
||||
/** Show the dialog to confirm clearing stats */
|
||||
confirmClearStatistics() {
|
||||
this.$refs.confirmClearStatistics.show();
|
||||
},
|
||||
|
||||
/** Send the request to clear stats */
|
||||
clearStatistics() {
|
||||
this.$root.clearStatistics((res) => {
|
||||
if (res.ok) {
|
||||
|
|
|
@ -120,14 +120,17 @@ export default {
|
|||
this.$root.getSocket().emit(prefix + "leave");
|
||||
},
|
||||
methods: {
|
||||
/** Start the Cloudflare tunnel */
|
||||
start() {
|
||||
this.$root.getSocket().emit(prefix + "start", this.cloudflareTunnelToken);
|
||||
},
|
||||
/** Stop the Cloudflare tunnel */
|
||||
stop() {
|
||||
this.$root.getSocket().emit(prefix + "stop", this.currentPassword, (res) => {
|
||||
this.$root.toastRes(res);
|
||||
});
|
||||
},
|
||||
/** Remove the token for the Cloudflare tunnel */
|
||||
removeToken() {
|
||||
this.$root.getSocket().emit(prefix + "removeToken");
|
||||
this.cloudflareTunnelToken = "";
|
||||
|
|
|
@ -303,6 +303,7 @@ export default {
|
|||
},
|
||||
|
||||
methods: {
|
||||
/** Check new passwords match before saving them */
|
||||
savePassword() {
|
||||
if (this.password.newPassword !== this.password.repeatNewPassword) {
|
||||
this.invalidPassword = true;
|
||||
|
@ -320,6 +321,7 @@ export default {
|
|||
}
|
||||
},
|
||||
|
||||
/** Disable authentication for web app access */
|
||||
disableAuth() {
|
||||
this.settings.disableAuth = true;
|
||||
|
||||
|
@ -332,6 +334,7 @@ export default {
|
|||
}, this.password.currentPassword);
|
||||
},
|
||||
|
||||
/** Enable authentication for web app access */
|
||||
enableAuth() {
|
||||
this.settings.disableAuth = false;
|
||||
this.saveSettings();
|
||||
|
|
|
@ -18,14 +18,31 @@ export default {
|
|||
},
|
||||
|
||||
methods: {
|
||||
/**
|
||||
* Return a given value in the format YYYY-MM-DD HH:mm:ss
|
||||
* @param {any} value Value to format as date time
|
||||
* @returns {string}
|
||||
*/
|
||||
datetime(value) {
|
||||
return this.datetimeFormat(value, "YYYY-MM-DD HH:mm:ss");
|
||||
},
|
||||
|
||||
/**
|
||||
* Return a given value in the format YYYY-MM-DD
|
||||
* @param {any} value Value to format as date
|
||||
* @returns {string}
|
||||
*/
|
||||
date(value) {
|
||||
return this.datetimeFormat(value, "YYYY-MM-DD");
|
||||
},
|
||||
|
||||
/**
|
||||
* Return a given value in the format HH:mm or if second is set
|
||||
* to true, HH:mm:ss
|
||||
* @param {any} value Value to format
|
||||
* @param {boolean} second Should seconds be included?
|
||||
* @returns {string}
|
||||
*/
|
||||
time(value, second = true) {
|
||||
let secondString;
|
||||
if (second) {
|
||||
|
@ -36,6 +53,12 @@ export default {
|
|||
return this.datetimeFormat(value, "HH:mm" + secondString);
|
||||
},
|
||||
|
||||
/**
|
||||
* Return a value in a custom format
|
||||
* @param {any} value Value to format
|
||||
* @param {any} format Format to return value in
|
||||
* @returns {string}
|
||||
*/
|
||||
datetimeFormat(value, format) {
|
||||
if (value !== undefined && value !== "") {
|
||||
return dayjs.utc(value).tz(this.timezone).format(format);
|
||||
|
|
|
@ -22,6 +22,7 @@ export default {
|
|||
},
|
||||
|
||||
methods: {
|
||||
/** Change the application language */
|
||||
async changeLang(lang) {
|
||||
let message = (await langModules["../languages/" + lang + ".js"]()).default;
|
||||
this.$i18n.setLocaleMessage(lang, message);
|
||||
|
|
|
@ -12,11 +12,13 @@ export default {
|
|||
},
|
||||
|
||||
methods: {
|
||||
/** Handle screen resize */
|
||||
onResize() {
|
||||
this.windowWidth = window.innerWidth;
|
||||
this.updateBody();
|
||||
},
|
||||
|
||||
/** Add css-class "mobile" to body if needed */
|
||||
updateBody() {
|
||||
if (this.isMobile) {
|
||||
document.body.classList.add("mobile");
|
||||
|
|
|
@ -62,6 +62,12 @@ export default {
|
|||
|
||||
methods: {
|
||||
|
||||
/**
|
||||
* Initialize connection to socket server
|
||||
* @param {boolean} [bypass = false] Should the check for if we
|
||||
* are on a status page be bypassed?
|
||||
* @returns {(void|null)}
|
||||
*/
|
||||
initSocketIO(bypass = false) {
|
||||
// No need to re-init
|
||||
if (this.socket.initedSocketIO) {
|
||||
|
@ -258,10 +264,18 @@ export default {
|
|||
socket.on("cloudflared_token", (res) => this.cloudflared.cloudflareTunnelToken = res);
|
||||
},
|
||||
|
||||
/**
|
||||
* The storage currently in use
|
||||
* @returns {Storage}
|
||||
*/
|
||||
storage() {
|
||||
return (this.remember) ? localStorage : sessionStorage;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get payload of JWT cookie
|
||||
* @returns {(Object|undefined)}
|
||||
*/
|
||||
getJWTPayload() {
|
||||
const jwtToken = this.$root.storage().token;
|
||||
|
||||
|
@ -271,10 +285,18 @@ export default {
|
|||
return undefined;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get current socket
|
||||
* @returns {Socket}
|
||||
*/
|
||||
getSocket() {
|
||||
return socket;
|
||||
},
|
||||
|
||||
/**
|
||||
* Show success or error toast dependant on response status code
|
||||
* @param {Object} res Response object
|
||||
*/
|
||||
toastRes(res) {
|
||||
if (res.ok) {
|
||||
toast.success(res.msg);
|
||||
|
@ -283,14 +305,35 @@ export default {
|
|||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Show a success toast
|
||||
* @param {string} msg Message to show
|
||||
*/
|
||||
toastSuccess(msg) {
|
||||
toast.success(msg);
|
||||
},
|
||||
|
||||
/**
|
||||
* Show an error toast
|
||||
* @param {string} msg Message to show
|
||||
*/
|
||||
toastError(msg) {
|
||||
toast.error(msg);
|
||||
},
|
||||
|
||||
/**
|
||||
* Callback for login
|
||||
* @callback loginCB
|
||||
* @param {Object} res Response object
|
||||
*/
|
||||
|
||||
/**
|
||||
* Send request to log user in
|
||||
* @param {string} username Username to log in with
|
||||
* @param {string} password Password to log in with
|
||||
* @param {string} token User token
|
||||
* @param {loginCB} callback Callback to call with result
|
||||
*/
|
||||
login(username, password, token, callback) {
|
||||
socket.emit("login", {
|
||||
username,
|
||||
|
@ -315,6 +358,10 @@ export default {
|
|||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Log in using a token
|
||||
* @param {string} token Token to log in with
|
||||
*/
|
||||
loginByToken(token) {
|
||||
socket.emit("loginByToken", token, (res) => {
|
||||
this.allowLoginDialog = true;
|
||||
|
@ -328,6 +375,7 @@ export default {
|
|||
});
|
||||
},
|
||||
|
||||
/** Log out of the web application */
|
||||
logout() {
|
||||
socket.emit("logout", () => { });
|
||||
this.storage().removeItem("token");
|
||||
|
@ -337,26 +385,54 @@ export default {
|
|||
this.clearData();
|
||||
},
|
||||
|
||||
/**
|
||||
* Callback for general socket requests
|
||||
* @callback socketCB
|
||||
* @param {Object} res Result of operation
|
||||
*/
|
||||
/** Prepare 2FA configuration */
|
||||
prepare2FA(callback) {
|
||||
socket.emit("prepare2FA", callback);
|
||||
},
|
||||
|
||||
/**
|
||||
* Save the current 2FA configuration
|
||||
* @param {any} secret Unused
|
||||
* @param {socketCB} callback
|
||||
*/
|
||||
save2FA(secret, callback) {
|
||||
socket.emit("save2FA", callback);
|
||||
},
|
||||
|
||||
/**
|
||||
* Disable 2FA for this user
|
||||
* @param {socketCB} callback
|
||||
*/
|
||||
disable2FA(callback) {
|
||||
socket.emit("disable2FA", callback);
|
||||
},
|
||||
|
||||
/**
|
||||
* Verify the provided 2FA token
|
||||
* @param {string} token Token to verify
|
||||
* @param {socketCB} callback
|
||||
*/
|
||||
verifyToken(token, callback) {
|
||||
socket.emit("verifyToken", token, callback);
|
||||
},
|
||||
|
||||
/**
|
||||
* Get current 2FA status
|
||||
* @param {socketCB} callback
|
||||
*/
|
||||
twoFAStatus(callback) {
|
||||
socket.emit("twoFAStatus", callback);
|
||||
},
|
||||
|
||||
/**
|
||||
* Get list of monitors
|
||||
* @param {socketCB} callback
|
||||
*/
|
||||
getMonitorList(callback) {
|
||||
if (! callback) {
|
||||
callback = () => { };
|
||||
|
@ -364,36 +440,74 @@ export default {
|
|||
socket.emit("getMonitorList", callback);
|
||||
},
|
||||
|
||||
/**
|
||||
* Add a monitor
|
||||
* @param {Object} monitor Object representing monitor to add
|
||||
* @param {socketCB} callback
|
||||
*/
|
||||
add(monitor, callback) {
|
||||
socket.emit("add", monitor, callback);
|
||||
},
|
||||
|
||||
/**
|
||||
* Delete monitor by ID
|
||||
* @param {number} monitorID ID of monitor to delete
|
||||
* @param {socketCB} callback
|
||||
*/
|
||||
deleteMonitor(monitorID, callback) {
|
||||
socket.emit("deleteMonitor", monitorID, callback);
|
||||
},
|
||||
|
||||
/** Clear the hearbeat list */
|
||||
clearData() {
|
||||
console.log("reset heartbeat list");
|
||||
this.heartbeatList = {};
|
||||
this.importantHeartbeatList = {};
|
||||
},
|
||||
|
||||
/**
|
||||
* Upload the provided backup
|
||||
* @param {string} uploadedJSON JSON to upload
|
||||
* @param {string} importHandle Type of import. If set to
|
||||
* most data in database will be replaced
|
||||
* @param {socketCB} callback
|
||||
*/
|
||||
uploadBackup(uploadedJSON, importHandle, callback) {
|
||||
socket.emit("uploadBackup", uploadedJSON, importHandle, callback);
|
||||
},
|
||||
|
||||
/**
|
||||
* Clear events for a specified monitor
|
||||
* @param {number} monitorID ID of monitor to clear
|
||||
* @param {socketCB} callback
|
||||
*/
|
||||
clearEvents(monitorID, callback) {
|
||||
socket.emit("clearEvents", monitorID, callback);
|
||||
},
|
||||
|
||||
/**
|
||||
* Clear the heartbeats of a specified monitor
|
||||
* @param {number} monitorID Id of monitor to clear
|
||||
* @param {socketCB} callback
|
||||
*/
|
||||
clearHeartbeats(monitorID, callback) {
|
||||
socket.emit("clearHeartbeats", monitorID, callback);
|
||||
},
|
||||
|
||||
/**
|
||||
* Clear all statistics
|
||||
* @param {socketCB} callback
|
||||
*/
|
||||
clearStatistics(callback) {
|
||||
socket.emit("clearStatistics", callback);
|
||||
},
|
||||
|
||||
/**
|
||||
* Get monitor beats for a specific monitor in a time range
|
||||
* @param {number} monitorID ID of monitor to fetch
|
||||
* @param {number} period Time in hours from now
|
||||
* @param {socketCB} callback
|
||||
*/
|
||||
getMonitorBeats(monitorID, period, callback) {
|
||||
socket.emit("getMonitorBeats", monitorID, period, callback);
|
||||
}
|
||||
|
|
|
@ -75,6 +75,7 @@ export default {
|
|||
},
|
||||
|
||||
methods: {
|
||||
/** Update the theme color meta tag */
|
||||
updateThemeColorMeta() {
|
||||
if (this.theme === "dark") {
|
||||
document.querySelector("#theme-color").setAttribute("content", "#161B22");
|
||||
|
|
|
@ -51,6 +51,7 @@ export default {
|
|||
};
|
||||
},
|
||||
methods: {
|
||||
/** Submit form data to add new status page */
|
||||
async submit() {
|
||||
this.processing = true;
|
||||
|
||||
|
|
|
@ -289,39 +289,47 @@ export default {
|
|||
|
||||
},
|
||||
methods: {
|
||||
/** Request a test notification be sent for this monitor */
|
||||
testNotification() {
|
||||
this.$root.getSocket().emit("testNotification", this.monitor.id);
|
||||
toast.success("Test notification is requested.");
|
||||
},
|
||||
|
||||
/** Show dialog to confirm pause */
|
||||
pauseDialog() {
|
||||
this.$refs.confirmPause.show();
|
||||
},
|
||||
|
||||
/** Resume this monitor */
|
||||
resumeMonitor() {
|
||||
this.$root.getSocket().emit("resumeMonitor", this.monitor.id, (res) => {
|
||||
this.$root.toastRes(res);
|
||||
});
|
||||
},
|
||||
|
||||
/** Request that this monitor is paused */
|
||||
pauseMonitor() {
|
||||
this.$root.getSocket().emit("pauseMonitor", this.monitor.id, (res) => {
|
||||
this.$root.toastRes(res);
|
||||
});
|
||||
},
|
||||
|
||||
/** Show dialog to confirm deletion */
|
||||
deleteDialog() {
|
||||
this.$refs.confirmDelete.show();
|
||||
},
|
||||
|
||||
/** Show dialog to confirm clearing events */
|
||||
clearEventsDialog() {
|
||||
this.$refs.confirmClearEvents.show();
|
||||
},
|
||||
|
||||
/** Show dialog to confirm clearing heartbeats */
|
||||
clearHeartbeatsDialog() {
|
||||
this.$refs.confirmClearHeartbeats.show();
|
||||
},
|
||||
|
||||
/** Request that this monitor is deleted */
|
||||
deleteMonitor() {
|
||||
this.$root.deleteMonitor(this.monitor.id, (res) => {
|
||||
if (res.ok) {
|
||||
|
@ -333,6 +341,7 @@ export default {
|
|||
});
|
||||
},
|
||||
|
||||
/** Request that this monitors events are cleared */
|
||||
clearEvents() {
|
||||
this.$root.clearEvents(this.monitor.id, (res) => {
|
||||
if (! res.ok) {
|
||||
|
@ -341,6 +350,7 @@ export default {
|
|||
});
|
||||
},
|
||||
|
||||
/** Request that this monitors heartbeats are cleared */
|
||||
clearHeartbeats() {
|
||||
this.$root.clearHeartbeats(this.monitor.id, (res) => {
|
||||
if (! res.ok) {
|
||||
|
@ -349,6 +359,11 @@ export default {
|
|||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Return the correct title for the ping stat
|
||||
* @param {boolean} [average=false] Is the statistic an average?
|
||||
* @returns {string} Title formated dependant on monitor type
|
||||
*/
|
||||
pingTitle(average = false) {
|
||||
let translationPrefix = "";
|
||||
if (average) {
|
||||
|
|
|
@ -573,6 +573,7 @@ export default {
|
|||
this.dnsresolvetypeOptions = dnsresolvetypeOptions;
|
||||
},
|
||||
methods: {
|
||||
/** Initialize the edit monitor form */
|
||||
init() {
|
||||
if (this.isAdd) {
|
||||
|
||||
|
@ -631,6 +632,10 @@ export default {
|
|||
|
||||
},
|
||||
|
||||
/**
|
||||
* Validate form input
|
||||
* @returns {boolean} Is the form input valid?
|
||||
*/
|
||||
isInputValid() {
|
||||
if (this.monitor.body) {
|
||||
try {
|
||||
|
@ -651,6 +656,10 @@ export default {
|
|||
return true;
|
||||
},
|
||||
|
||||
/**
|
||||
* Submit the form data for processing
|
||||
* @returns {void}
|
||||
*/
|
||||
async submit() {
|
||||
this.processing = true;
|
||||
|
||||
|
@ -695,14 +704,20 @@ export default {
|
|||
}
|
||||
},
|
||||
|
||||
// Added a Notification Event
|
||||
// Enable it if the notification is added in EditMonitor.vue
|
||||
/**
|
||||
* Added a Notification Event
|
||||
* Enable it if the notification is added in EditMonitor.vue
|
||||
* @param {number} id ID of notification to add
|
||||
*/
|
||||
addedNotification(id) {
|
||||
this.monitor.notificationIDList[id] = true;
|
||||
},
|
||||
|
||||
// Added a Proxy Event
|
||||
// Enable it if the proxy is added in EditMonitor.vue
|
||||
/**
|
||||
* Added a Proxy Event
|
||||
* Enable it if the proxy is added in EditMonitor.vue
|
||||
* @param {number} id ID of proxy to add
|
||||
*/
|
||||
addedProxy(id) {
|
||||
this.monitor.proxyId = id;
|
||||
},
|
||||
|
|
|
@ -51,6 +51,11 @@ export default {
|
|||
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* Get the correct URL for the icon
|
||||
* @param {string} icon Path for icon
|
||||
* @returns {string} Correctly formatted path including port numbers
|
||||
*/
|
||||
icon(icon) {
|
||||
if (icon === "/icon.svg") {
|
||||
return icon;
|
||||
|
|
|
@ -45,6 +45,7 @@ export default {
|
|||
|
||||
},
|
||||
methods: {
|
||||
/** Go back 1 in browser history */
|
||||
goBack() {
|
||||
history.back();
|
||||
}
|
||||
|
|
|
@ -118,13 +118,17 @@ export default {
|
|||
|
||||
methods: {
|
||||
|
||||
// For desktop only, mobile do nothing
|
||||
/**
|
||||
* Load the general settings page
|
||||
* For desktop only, on mobile do nothing
|
||||
*/
|
||||
loadGeneralPage() {
|
||||
if (!this.currentPage && !this.$root.isMobile) {
|
||||
this.$router.push("/settings/general");
|
||||
}
|
||||
},
|
||||
|
||||
/** Load settings from server */
|
||||
loadSettings() {
|
||||
this.$root.getSocket().emit("getSettings", (res) => {
|
||||
this.settings = res.data;
|
||||
|
@ -153,9 +157,16 @@ export default {
|
|||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Callback for saving settings
|
||||
* @callback saveSettingsCB
|
||||
* @param {Object} res Result of operation
|
||||
*/
|
||||
|
||||
/**
|
||||
* Save Settings
|
||||
* @param currentPassword (Optional) Only need for disableAuth to true
|
||||
* @param {saveSettingsCB} [callback]
|
||||
* @param {string} [currentPassword] Only need for disableAuth to true
|
||||
*/
|
||||
saveSettings(callback, currentPassword) {
|
||||
this.$root.getSocket().emit("setSettings", this.settings, currentPassword, (res) => {
|
||||
|
|
|
@ -71,6 +71,10 @@ export default {
|
|||
});
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* Submit form data for processing
|
||||
* @returns {void}
|
||||
*/
|
||||
submit() {
|
||||
this.processing = true;
|
||||
|
||||
|
|
|
@ -332,6 +332,7 @@ export default {
|
|||
},
|
||||
|
||||
props: {
|
||||
/** Override for the status page slug */
|
||||
overrideSlug: {
|
||||
type: String,
|
||||
required: false,
|
||||
|
@ -587,10 +588,16 @@ export default {
|
|||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Provide syntax highlighting for CSS
|
||||
* @param {string} code Text to highlight
|
||||
* @returns {string}
|
||||
*/
|
||||
highlighter(code) {
|
||||
return highlight(code, languages.css);
|
||||
},
|
||||
|
||||
/** Update the heartbeat list and update favicon if neccessary */
|
||||
updateHeartbeatList() {
|
||||
// If editMode, it will use the data from websocket.
|
||||
if (! this.editMode) {
|
||||
|
@ -619,6 +626,7 @@ export default {
|
|||
}
|
||||
},
|
||||
|
||||
/** Enable editing mode */
|
||||
edit() {
|
||||
if (this.hasToken) {
|
||||
this.$root.initSocketIO(true);
|
||||
|
@ -630,6 +638,7 @@ export default {
|
|||
}
|
||||
},
|
||||
|
||||
/** Save the status page */
|
||||
save() {
|
||||
let startTime = new Date();
|
||||
this.config.slug = this.config.slug.trim().toLowerCase();
|
||||
|
@ -657,10 +666,12 @@ export default {
|
|||
});
|
||||
},
|
||||
|
||||
/** Show dialog confirming deletion */
|
||||
deleteDialog() {
|
||||
this.$refs.confirmDelete.show();
|
||||
},
|
||||
|
||||
/** Request deletion of this status page */
|
||||
deleteStatusPage() {
|
||||
this.$root.getSocket().emit("deleteStatusPage", this.slug, (res) => {
|
||||
if (res.ok) {
|
||||
|
@ -672,10 +683,16 @@ export default {
|
|||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns label for a specifed monitor
|
||||
* @param {Object} monitor Object representing monitor
|
||||
* @returns {string}
|
||||
*/
|
||||
monitorSelectorLabel(monitor) {
|
||||
return `${monitor.name}`;
|
||||
},
|
||||
|
||||
/** Add a group to the status page */
|
||||
addGroup() {
|
||||
let groupName = this.$t("Untitled Group");
|
||||
|
||||
|
@ -689,27 +706,32 @@ export default {
|
|||
});
|
||||
},
|
||||
|
||||
/** Add a domain to the status page */
|
||||
addDomainField() {
|
||||
this.config.domainNameList.push("");
|
||||
},
|
||||
|
||||
/** Discard changes to status page */
|
||||
discard() {
|
||||
location.href = "/status/" + this.slug;
|
||||
},
|
||||
|
||||
/**
|
||||
* Crop Success
|
||||
* Set URL of new image after successful crop operation
|
||||
* @param {string} imgDataUrl URL of image in data:// format
|
||||
*/
|
||||
cropSuccess(imgDataUrl) {
|
||||
this.imgDataUrl = imgDataUrl;
|
||||
},
|
||||
|
||||
/** Show image crop dialog if in edit mode */
|
||||
showImageCropUploadMethod() {
|
||||
if (this.editMode) {
|
||||
this.showImageCropUpload = true;
|
||||
}
|
||||
},
|
||||
|
||||
/** Create an incident for this status page */
|
||||
createIncident() {
|
||||
this.enableEditIncidentMode = true;
|
||||
|
||||
|
@ -724,6 +746,7 @@ export default {
|
|||
};
|
||||
},
|
||||
|
||||
/** Post the incident to the status page */
|
||||
postIncident() {
|
||||
if (this.incident.title === "" || this.incident.content === "") {
|
||||
toast.error(this.$t("Please input title and content"));
|
||||
|
@ -743,14 +766,13 @@ export default {
|
|||
|
||||
},
|
||||
|
||||
/**
|
||||
* Click Edit Button
|
||||
*/
|
||||
/** Click Edit Button */
|
||||
editIncident() {
|
||||
this.enableEditIncidentMode = true;
|
||||
this.previousIncident = Object.assign({}, this.incident);
|
||||
},
|
||||
|
||||
/** Cancel creation or editing of incident */
|
||||
cancelIncident() {
|
||||
this.enableEditIncidentMode = false;
|
||||
|
||||
|
@ -760,16 +782,25 @@ export default {
|
|||
}
|
||||
},
|
||||
|
||||
/** Unpin the incident */
|
||||
unpinIncident() {
|
||||
this.$root.getSocket().emit("unpinIncident", this.slug, () => {
|
||||
this.incident = null;
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the relative time difference of a date from now
|
||||
* @returns {string}
|
||||
*/
|
||||
dateFromNow(date) {
|
||||
return dayjs.utc(date).fromNow();
|
||||
},
|
||||
|
||||
/**
|
||||
* Remove a domain from the status page
|
||||
* @param {number} index Index of domain to remove
|
||||
*/
|
||||
removeDomain(index) {
|
||||
this.config.domainNameList.splice(index, 1);
|
||||
},
|
||||
|
|
|
@ -26,8 +26,8 @@ function getTimezoneOffset(timeZone) {
|
|||
|
||||
/**
|
||||
* Returns a list of timezones sorted by their offset from UTC.
|
||||
* @param {Array} timezones - An array of timezone objects.
|
||||
* @returns {Array} A list of the given timezones sorted by their offset from UTC.
|
||||
* @param {Object[]} timezones An array of timezone objects.
|
||||
* @returns {Object[]} A list of the given timezones sorted by their offset from UTC.
|
||||
*
|
||||
* Generated by Trelent
|
||||
*/
|
||||
|
@ -63,6 +63,7 @@ export function timezoneList() {
|
|||
return result;
|
||||
}
|
||||
|
||||
/** Set the locale of the HTML page */
|
||||
export function setPageLocale() {
|
||||
const html = document.documentElement;
|
||||
html.setAttribute("lang", currentLocale() );
|
||||
|
@ -70,7 +71,9 @@ export function setPageLocale() {
|
|||
}
|
||||
|
||||
/**
|
||||
* Get the base URL
|
||||
* Mainly used for dev, because the backend and the frontend are in different ports.
|
||||
* @returns {string}
|
||||
*/
|
||||
export function getResBaseURL() {
|
||||
const env = process.env.NODE_ENV;
|
||||
|
|
70
src/util.js
70
src/util.js
|
@ -18,6 +18,7 @@ exports.PENDING = 2;
|
|||
exports.STATUS_PAGE_ALL_DOWN = 0;
|
||||
exports.STATUS_PAGE_ALL_UP = 1;
|
||||
exports.STATUS_PAGE_PARTIAL_DOWN = 2;
|
||||
/** Flip the status of s */
|
||||
function flipStatus(s) {
|
||||
if (s === exports.UP) {
|
||||
return exports.DOWN;
|
||||
|
@ -28,6 +29,10 @@ function flipStatus(s) {
|
|||
return s;
|
||||
}
|
||||
exports.flipStatus = flipStatus;
|
||||
/**
|
||||
* Delays for specified number of seconds
|
||||
* @param ms Number of milliseconds to sleep for
|
||||
*/
|
||||
function sleep(ms) {
|
||||
return new Promise(resolve => setTimeout(resolve, ms));
|
||||
}
|
||||
|
@ -83,6 +88,12 @@ class Logger {
|
|||
this.debug("server", this.hideLog);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Write a message to the log
|
||||
* @param module The module the log comes from
|
||||
* @param msg Message to write
|
||||
* @param level Log level. One of INFO, WARN, ERROR, DEBUG or can be customized.
|
||||
*/
|
||||
log(module, msg, level) {
|
||||
if (this.hideLog[level] && this.hideLog[level].includes(module)) {
|
||||
return;
|
||||
|
@ -109,18 +120,44 @@ class Logger {
|
|||
console.log(formattedMessage);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Log an INFO message
|
||||
* @param module Module log comes from
|
||||
* @param msg Message to write
|
||||
*/
|
||||
info(module, msg) {
|
||||
this.log(module, msg, "info");
|
||||
}
|
||||
/**
|
||||
* Log a WARN message
|
||||
* @param module Module log comes from
|
||||
* @param msg Message to write
|
||||
*/
|
||||
warn(module, msg) {
|
||||
this.log(module, msg, "warn");
|
||||
}
|
||||
/**
|
||||
* Log an ERROR message
|
||||
* @param module Module log comes from
|
||||
* @param msg Message to write
|
||||
*/
|
||||
error(module, msg) {
|
||||
this.log(module, msg, "error");
|
||||
}
|
||||
/**
|
||||
* Log a DEBUG message
|
||||
* @param module Module log comes from
|
||||
* @param msg Message to write
|
||||
*/
|
||||
debug(module, msg) {
|
||||
this.log(module, msg, "debug");
|
||||
}
|
||||
/**
|
||||
* Log an exeption as an ERROR
|
||||
* @param module Module log comes from
|
||||
* @param exception The exeption to include
|
||||
* @param msg The message to write
|
||||
*/
|
||||
exception(module, exception, msg) {
|
||||
let finalMessage = exception;
|
||||
if (msg) {
|
||||
|
@ -130,13 +167,13 @@ class Logger {
|
|||
}
|
||||
}
|
||||
exports.log = new Logger();
|
||||
/**
|
||||
* String.prototype.replaceAll() polyfill
|
||||
* https://gomakethings.com/how-to-replace-a-section-of-a-string-with-another-one-with-vanilla-js/
|
||||
* @author Chris Ferdinandi
|
||||
* @license MIT
|
||||
*/
|
||||
function polyfill() {
|
||||
/**
|
||||
* String.prototype.replaceAll() polyfill
|
||||
* https://gomakethings.com/how-to-replace-a-section-of-a-string-with-another-one-with-vanilla-js/
|
||||
* @author Chris Ferdinandi
|
||||
* @license MIT
|
||||
*/
|
||||
if (!String.prototype.replaceAll) {
|
||||
String.prototype.replaceAll = function (str, newStr) {
|
||||
// If a regex pattern
|
||||
|
@ -153,6 +190,10 @@ class TimeLogger {
|
|||
constructor() {
|
||||
this.startTime = dayjs().valueOf();
|
||||
}
|
||||
/**
|
||||
* Output time since start of monitor
|
||||
* @param name Name of monitor
|
||||
*/
|
||||
print(name) {
|
||||
if (exports.isDev && process.env.TIMELOGGER === "1") {
|
||||
console.log(name + ": " + (dayjs().valueOf() - this.startTime) + "ms");
|
||||
|
@ -201,6 +242,13 @@ let getRandomBytes = ((typeof window !== 'undefined' && window.crypto)
|
|||
: function () {
|
||||
return require("crypto").randomBytes;
|
||||
})();
|
||||
/**
|
||||
* Get a random integer suitable for use in cryptography between upper
|
||||
* and lower bounds.
|
||||
* @param min Minimum value of integer
|
||||
* @param max Maximum value of integer
|
||||
* @returns Cryptographically suitable random integer
|
||||
*/
|
||||
function getCryptoRandomInt(min, max) {
|
||||
// synchronous version of: https://github.com/joepie91/node-random-number-csprng
|
||||
const range = max - min;
|
||||
|
@ -231,6 +279,11 @@ function getCryptoRandomInt(min, max) {
|
|||
}
|
||||
}
|
||||
exports.getCryptoRandomInt = getCryptoRandomInt;
|
||||
/**
|
||||
* Generate a secret
|
||||
* @param length Lenght of secret to generate
|
||||
* @returns
|
||||
*/
|
||||
function genSecret(length = 64) {
|
||||
let secret = "";
|
||||
const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||
|
@ -241,6 +294,11 @@ function genSecret(length = 64) {
|
|||
return secret;
|
||||
}
|
||||
exports.genSecret = genSecret;
|
||||
/**
|
||||
* Get the path of a monitor
|
||||
* @param id ID of monitor
|
||||
* @returns Formatted relative path
|
||||
*/
|
||||
function getMonitorRelativeURL(id) {
|
||||
return "/dashboard/" + id;
|
||||
}
|
||||
|
|
76
src/util.ts
76
src/util.ts
|
@ -19,7 +19,7 @@ export const STATUS_PAGE_ALL_DOWN = 0;
|
|||
export const STATUS_PAGE_ALL_UP = 1;
|
||||
export const STATUS_PAGE_PARTIAL_DOWN = 2;
|
||||
|
||||
|
||||
/** Flip the status of s */
|
||||
export function flipStatus(s: number) {
|
||||
if (s === UP) {
|
||||
return DOWN;
|
||||
|
@ -32,6 +32,10 @@ export function flipStatus(s: number) {
|
|||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delays for specified number of seconds
|
||||
* @param ms Number of milliseconds to sleep for
|
||||
*/
|
||||
export function sleep(ms: number) {
|
||||
return new Promise(resolve => setTimeout(resolve, ms));
|
||||
}
|
||||
|
@ -94,6 +98,12 @@ class Logger {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a message to the log
|
||||
* @param module The module the log comes from
|
||||
* @param msg Message to write
|
||||
* @param level Log level. One of INFO, WARN, ERROR, DEBUG or can be customized.
|
||||
*/
|
||||
log(module: string, msg: any, level: string) {
|
||||
if (this.hideLog[level] && this.hideLog[level].includes(module)) {
|
||||
return;
|
||||
|
@ -120,22 +130,48 @@ class Logger {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Log an INFO message
|
||||
* @param module Module log comes from
|
||||
* @param msg Message to write
|
||||
*/
|
||||
info(module: string, msg: any) {
|
||||
this.log(module, msg, "info");
|
||||
}
|
||||
|
||||
/**
|
||||
* Log a WARN message
|
||||
* @param module Module log comes from
|
||||
* @param msg Message to write
|
||||
*/
|
||||
warn(module: string, msg: any) {
|
||||
this.log(module, msg, "warn");
|
||||
}
|
||||
|
||||
error(module: string, msg: any) {
|
||||
/**
|
||||
* Log an ERROR message
|
||||
* @param module Module log comes from
|
||||
* @param msg Message to write
|
||||
*/
|
||||
error(module: string, msg: any) {
|
||||
this.log(module, msg, "error");
|
||||
}
|
||||
|
||||
debug(module: string, msg: any) {
|
||||
/**
|
||||
* Log a DEBUG message
|
||||
* @param module Module log comes from
|
||||
* @param msg Message to write
|
||||
*/
|
||||
debug(module: string, msg: any) {
|
||||
this.log(module, msg, "debug");
|
||||
}
|
||||
|
||||
/**
|
||||
* Log an exeption as an ERROR
|
||||
* @param module Module log comes from
|
||||
* @param exception The exeption to include
|
||||
* @param msg The message to write
|
||||
*/
|
||||
exception(module: string, exception: any, msg: any) {
|
||||
let finalMessage = exception
|
||||
|
||||
|
@ -151,13 +187,13 @@ export const log = new Logger();
|
|||
|
||||
declare global { interface String { replaceAll(str: string, newStr: string): string; } }
|
||||
|
||||
/**
|
||||
* String.prototype.replaceAll() polyfill
|
||||
* https://gomakethings.com/how-to-replace-a-section-of-a-string-with-another-one-with-vanilla-js/
|
||||
* @author Chris Ferdinandi
|
||||
* @license MIT
|
||||
*/
|
||||
export function polyfill() {
|
||||
/**
|
||||
* String.prototype.replaceAll() polyfill
|
||||
* https://gomakethings.com/how-to-replace-a-section-of-a-string-with-another-one-with-vanilla-js/
|
||||
* @author Chris Ferdinandi
|
||||
* @license MIT
|
||||
*/
|
||||
if (!String.prototype.replaceAll) {
|
||||
String.prototype.replaceAll = function (str: string, newStr: string) {
|
||||
// If a regex pattern
|
||||
|
@ -177,7 +213,10 @@ export class TimeLogger {
|
|||
constructor() {
|
||||
this.startTime = dayjs().valueOf();
|
||||
}
|
||||
|
||||
/**
|
||||
* Output time since start of monitor
|
||||
* @param name Name of monitor
|
||||
*/
|
||||
print(name: string) {
|
||||
if (isDev && process.env.TIMELOGGER === "1") {
|
||||
console.log(name + ": " + (dayjs().valueOf() - this.startTime) + "ms")
|
||||
|
@ -231,6 +270,13 @@ let getRandomBytes = (
|
|||
}
|
||||
)();
|
||||
|
||||
/**
|
||||
* Get a random integer suitable for use in cryptography between upper
|
||||
* and lower bounds.
|
||||
* @param min Minimum value of integer
|
||||
* @param max Maximum value of integer
|
||||
* @returns Cryptographically suitable random integer
|
||||
*/
|
||||
export function getCryptoRandomInt(min: number, max: number):number {
|
||||
|
||||
// synchronous version of: https://github.com/joepie91/node-random-number-csprng
|
||||
|
@ -267,6 +313,11 @@ export function getCryptoRandomInt(min: number, max: number):number {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a random alphanumeric string of fixed length
|
||||
* @param length Length of string to generate
|
||||
* @returns string
|
||||
*/
|
||||
export function genSecret(length = 64) {
|
||||
let secret = "";
|
||||
const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||
|
@ -277,6 +328,11 @@ export function genSecret(length = 64) {
|
|||
return secret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the path of a monitor
|
||||
* @param id ID of monitor
|
||||
* @returns Formatted relative path
|
||||
*/
|
||||
export function getMonitorRelativeURL(id: string) {
|
||||
return "/dashboard/" + id;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue