231 lines
6.8 KiB
JavaScript
231 lines
6.8 KiB
JavaScript
let lastMessageHash = 0;
|
|
let lastMessageTimeStamp = new Date();
|
|
|
|
////////////////////////////////////////////////////////
|
|
//
|
|
// translate, Log and optionally display errors
|
|
// return translated message in case caller needs it
|
|
async function dealWithError(msg, vm) {
|
|
//Check if this is the same message again as last time within a short time span to avoid endless looping errors of same message
|
|
//but still allow for user to repeat operation that causes error so they can view it
|
|
const newHash = window.$gz.util.quickHash(msg);
|
|
if (newHash == lastMessageHash) {
|
|
const tsnow = new Date();
|
|
//don't show the same exact message if it was just shown less than 1 second ago
|
|
if (tsnow - lastMessageTimeStamp < 1000) return;
|
|
}
|
|
lastMessageHash = newHash;
|
|
lastMessageTimeStamp = new Date();
|
|
|
|
//translate as necessary
|
|
msg = await window.$gz.translation.translateStringWithMultipleKeysAsync(msg);
|
|
|
|
//In some cases the error may not be translatable, if this is not a debug run then it should show without the ?? that translating puts in keys not found
|
|
//so it's not as weird looking to the user
|
|
//vm may be null here so check window gz for dev
|
|
if (!window.$gz.dev && msg.includes("??")) {
|
|
msg = msg.replace("??", "");
|
|
}
|
|
window.$gz.store.commit("logItem", msg);
|
|
if (window.$gz.dev) {
|
|
const errMsg = "DEV MODE errorHandler.js:: Unexpected error: \r\n" + msg;
|
|
// eslint-disable-next-line no-console
|
|
console.error(errMsg);
|
|
|
|
// eslint-disable-next-line no-debugger
|
|
debugger;
|
|
}
|
|
|
|
//If a form instance was provided (vue instance)
|
|
//and it can display and error then put the error into it
|
|
if (!vm || vm.formState == undefined) {
|
|
//Special work around to not redundantly display errors when AyaNova job fails
|
|
// and Vue decides to throw it's own error into the mix when we've already displayed appropriate message
|
|
if (msg.includes("Vue error") && msg.includes("Job failed")) {
|
|
return;
|
|
}
|
|
|
|
//popup if no place to display it elsewise
|
|
window.$gz.eventBus.$emit("notify-error", msg);
|
|
return;
|
|
}
|
|
|
|
//should be able to display in form...
|
|
if (vm.$ay.dev) {
|
|
//make sure formState.appError is defined on data
|
|
if (!window.$gz.util.has(vm, "formState.appError")) {
|
|
throw new Error(
|
|
"DEV ERROR errorHandler::dealWithError -> formState.appError seems to be missing from form's vue data object"
|
|
);
|
|
}
|
|
}
|
|
vm.formState.appError = msg;
|
|
|
|
//TODO: What is this doing exactly?
|
|
//it's related to server errors but I'm setting appError above
|
|
//why two error properties?
|
|
window.$gz.form.setErrorBoxErrors(vm);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////
|
|
// DECODE ERROR TO TEXT
|
|
// accept an unknown type of error variable
|
|
// and return human readable text
|
|
//
|
|
function decodeError(e, vm) {
|
|
// console.log("decodeError full e object as is: ");
|
|
// console.log(e);
|
|
// console.log("decodeError full e object stringified: ", JSON.stringify(e));
|
|
// console.log("decodeError is typeof:", typeof e);
|
|
// console.log("decodeError e is instanceof Error ", e instanceof Error);
|
|
// console.log(
|
|
// "decodeError e is a string already: ",
|
|
// window.$gz.util.isString(e)
|
|
// );
|
|
|
|
//already a string?
|
|
if (window.$gz.util.isString(e)) {
|
|
return e; //nothing to do here, already a string
|
|
}
|
|
|
|
if (e instanceof Error) {
|
|
//an Error object?
|
|
return `Error - Name:${e.name}, Message:${e.message}`;
|
|
}
|
|
|
|
if (
|
|
e == null ||
|
|
e == "" ||
|
|
(typeof e === "object" && Object.keys(e).length === 0)
|
|
) {
|
|
return `errorHandler::decodeError - Error is unknown / empty (e:${e})`;
|
|
}
|
|
|
|
//API error object or error RESPONSE object?
|
|
if (e.error || e.code) {
|
|
let err = null;
|
|
//could be the error RESPONSE or it could be the error object *inside* the error response so sort out here
|
|
if (e.error) {
|
|
//it's the entire resopnse object
|
|
err = e.error;
|
|
} else {
|
|
//it's the inner error object only
|
|
err = e;
|
|
}
|
|
let msg = "";
|
|
if (err.code) {
|
|
msg += err.code;
|
|
msg += " - ";
|
|
if (vm) {
|
|
msg += vm.$ay.t("ErrorAPI" + err.code);
|
|
}
|
|
msg += "\n";
|
|
}
|
|
if (err.target) {
|
|
msg += err.target;
|
|
msg += "\n";
|
|
}
|
|
|
|
if (err.message && !err.message.startsWith("ErrorAPI")) {
|
|
//errapi already dealt with above no need to repeat it here
|
|
msg += err.message;
|
|
msg += "\n";
|
|
}
|
|
|
|
if (err.details) {
|
|
err.details.forEach(z => {
|
|
let zerror = null;
|
|
if (z.error) {
|
|
zerror = z.error + " - ";
|
|
}
|
|
msg += `${zerror}${z.message}\n`;
|
|
});
|
|
}
|
|
|
|
//console.log("errorhandler:decodeError returning message:", msg);
|
|
|
|
return msg;
|
|
}
|
|
|
|
//Javascript Fetch API Response object?
|
|
if (e instanceof Response) {
|
|
return `http error: ${e.statusText} - ${e.status} Url: ${e.url}`;
|
|
}
|
|
|
|
//last resort
|
|
return JSON.stringify(e);
|
|
}
|
|
export default {
|
|
handleGeneralError(message, source, lineno, colno, error) {
|
|
let msg = "General error: \n" + message;
|
|
if (source) {
|
|
msg += "\nsource: " + source;
|
|
}
|
|
if (lineno) {
|
|
msg += "\nlineno: " + lineno;
|
|
}
|
|
if (colno) {
|
|
msg += "\ncolno: " + colno;
|
|
}
|
|
if (error) {
|
|
if (typeof error === "object") {
|
|
error = JSON.stringify(error);
|
|
}
|
|
msg += "\nerror: " + error;
|
|
}
|
|
dealWithError(msg);
|
|
},
|
|
handleVueError(err, vm, info) {
|
|
let msg = "Vue error: \n" + decodeError(err, vm);
|
|
if (err.fileName) {
|
|
msg += "\nfilename: " + err.fileName;
|
|
}
|
|
if (err.lineNumber) {
|
|
msg += "\nlineNumber: " + err.lineNumber;
|
|
}
|
|
if (info) {
|
|
msg += "\ninfo: " + info;
|
|
}
|
|
if (err.stack) {
|
|
msg += "\nSTACK:\n " + err.stack;
|
|
}
|
|
dealWithError(msg, vm);
|
|
},
|
|
handleVueWarning(wmsg, vm, trace) {
|
|
let msg = "Vue warning: \n" + decodeError(wmsg, vm);
|
|
if (trace) {
|
|
msg += "\ntrace: " + trace;
|
|
}
|
|
dealWithError(msg, vm);
|
|
},
|
|
/////////////////////////////////////////////////
|
|
// translate, log and return error
|
|
//
|
|
handleFormError(err, vm) {
|
|
if (window.$gz.dev) {
|
|
console.trace(err);
|
|
}
|
|
//called inside forms when things go unexpectedly wrong
|
|
dealWithError(decodeError(err, vm), vm);
|
|
},
|
|
/////////////////////////////////////////////////
|
|
// decode error into string suitable to display
|
|
//
|
|
errorToString(err, vm) {
|
|
//called inside forms when things go unexpectedly wrong
|
|
return decodeError(err, vm);
|
|
}
|
|
};
|
|
/*
|
|
ERROR CODES USED:
|
|
Client error codes are all in the range of E16 to E999
|
|
Server error codes are all in the range of E1000 to E1999
|
|
API specific (logic) error codes are all in the range of 2000 to 3000
|
|
|
|
CLIENT ERROR CODES:
|
|
E16 - ErrorUserNotAuthenticated
|
|
E17 - ErrorServerUnresponsive
|
|
E18 - Misc error without a translation key, unexpected throws etc or api error during server call, details in the message / Any error without a translation key defined basically
|
|
|
|
*/
|