395 lines
10 KiB
JavaScript
395 lines
10 KiB
JavaScript
/* Xeslint-disable */
|
|
|
|
/////////////////////////////////
|
|
// General utility library
|
|
//
|
|
|
|
const icons = {
|
|
image: "fa-file-image",
|
|
pdf: "fa-file-pdf",
|
|
word: "fa-file-word",
|
|
powerpoint: "fa-file-powerpoint",
|
|
excel: "fa-file-excel",
|
|
csv: "fa-file-csv",
|
|
audio: "fa-file-audio",
|
|
video: "fa-file-video",
|
|
archive: "fa-file-archive",
|
|
code: "fa-file-code",
|
|
text: "fa-file-alt",
|
|
file: "fa-file"
|
|
};
|
|
const mimeTypes = {
|
|
"image/gif": icons.image,
|
|
"image/jpeg": icons.image,
|
|
"image/png": icons.image,
|
|
|
|
"application/pdf": icons.pdf,
|
|
|
|
"application/msword": icons.word,
|
|
"application/vnd.openxmlformats-officedocument.wordprocessingml.document":
|
|
icons.word,
|
|
|
|
"application/mspowerpoint": icons.powerpoint,
|
|
"application/vnd.openxmlformats-officedocument.presentationml.presentation":
|
|
icons.powerpoint,
|
|
|
|
"application/msexcel": icons.excel,
|
|
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet":
|
|
icons.excel,
|
|
|
|
"text/csv": icons.csv,
|
|
|
|
"audio/aac": icons.audio,
|
|
"audio/wav": icons.audio,
|
|
"audio/mpeg": icons.audio,
|
|
"audio/mp4": icons.audio,
|
|
"audio/ogg": icons.audio,
|
|
|
|
"video/x-msvideo": icons.video,
|
|
"video/mpeg": icons.video,
|
|
"video/mp4": icons.video,
|
|
"video/ogg": icons.video,
|
|
"video/quicktime": icons.video,
|
|
"video/webm": icons.video,
|
|
|
|
"application/gzip": icons.archive,
|
|
"application/zip": icons.archive,
|
|
"application/x-tar": icons.archive,
|
|
|
|
"text/css": icons.code,
|
|
"text/html": icons.code,
|
|
"text/javascript": icons.code,
|
|
"application/javascript": icons.code,
|
|
|
|
"text/plain": icons.text,
|
|
"text/richtext": icons.text,
|
|
"text/rtf": icons.text,
|
|
"application/rtf": icons.text,
|
|
"application/json": icons.text
|
|
};
|
|
|
|
const extensions = {
|
|
gif: icons.image,
|
|
jpeg: icons.image,
|
|
jpg: icons.image,
|
|
png: icons.image,
|
|
|
|
pdf: icons.pdf,
|
|
|
|
doc: icons.word,
|
|
docx: icons.word,
|
|
|
|
ppt: icons.powerpoint,
|
|
pptx: icons.powerpoint,
|
|
|
|
xls: icons.excel,
|
|
xlsx: icons.excel,
|
|
|
|
csv: icons.csv,
|
|
|
|
aac: icons.audio,
|
|
mp3: icons.audio,
|
|
ogg: icons.audio,
|
|
|
|
avi: icons.video,
|
|
flv: icons.video,
|
|
mkv: icons.video,
|
|
mp4: icons.video,
|
|
|
|
gz: icons.archive,
|
|
zip: icons.archive,
|
|
tar: icons.archive,
|
|
"7z": icons.archive,
|
|
|
|
css: icons.code,
|
|
html: icons.code,
|
|
js: icons.code,
|
|
|
|
txt: icons.text,
|
|
json: icons.text,
|
|
rtf: icons.text
|
|
};
|
|
|
|
export default {
|
|
///////////////////////////////
|
|
// CLEAN OBJECT
|
|
// Clear all properties from object without resorting to assigning a new object (o={})
|
|
// which can be problematic in some cases (IE bugs, watched data items in forms etc)
|
|
|
|
removeAllPropertiesFromObject: function(o) {
|
|
for (let variableKey in o) {
|
|
if (o.hasOwnProperty(variableKey)) {
|
|
delete o[variableKey];
|
|
}
|
|
}
|
|
},
|
|
/**
|
|
* Copy a string to clipboard
|
|
* @param {String} string The string to be copied to clipboard
|
|
* @return {Boolean} returns a boolean correspondent to the success of the copy operation.
|
|
* Modified from an example here: https://stackoverflow.com/a/53951634/8939
|
|
* Basically a fallback if navigator.clipboard is not available
|
|
*/
|
|
copyToClipboard: function(string) {
|
|
let textarea;
|
|
let result;
|
|
|
|
if (navigator && navigator.clipboard) {
|
|
navigator.clipboard.writeText(string);
|
|
} else {
|
|
try {
|
|
textarea = document.createElement("textarea");
|
|
textarea.setAttribute("readonly", true);
|
|
textarea.setAttribute("contenteditable", true);
|
|
textarea.style.position = "fixed"; // prevent scroll from jumping to the bottom when focus is set.
|
|
textarea.value = string;
|
|
|
|
document.body.appendChild(textarea);
|
|
|
|
textarea.focus();
|
|
textarea.select();
|
|
|
|
const range = document.createRange();
|
|
range.selectNodeContents(textarea);
|
|
|
|
const sel = window.getSelection();
|
|
sel.removeAllRanges();
|
|
sel.addRange(range);
|
|
|
|
textarea.setSelectionRange(0, textarea.value.length);
|
|
result = document.execCommand("copy");
|
|
} catch (err) {
|
|
//console.error(err);
|
|
result = null;
|
|
} finally {
|
|
document.body.removeChild(textarea);
|
|
}
|
|
|
|
// manual copy fallback using prompt
|
|
if (!result) {
|
|
const isMac = navigator.platform.toUpperCase().indexOf("MAC") >= 0;
|
|
const copyHotkey = isMac ? "⌘C" : "CTRL+C";
|
|
result = prompt(`Press ${copyHotkey}`, string);
|
|
if (!result) {
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
},
|
|
///////////////////////////////
|
|
// CLEAN TAG NAME
|
|
// Clean up a tag with same rules as server
|
|
//
|
|
normalizeTag: function(tagName) {
|
|
//kebab case takes care of all the things we need for tags in one go
|
|
tagName = window.$gz._.kebabCase(tagName);
|
|
|
|
//No longer than 255 characters
|
|
tagName = tagName.length > 255 ? tagName.substr(0, 255 - 1) : tagName;
|
|
|
|
return tagName;
|
|
},
|
|
///////////////////////////////
|
|
// Quick hash for trivial purposes
|
|
// not cryptographic
|
|
// https://stackoverflow.com/a/7616484/8939
|
|
//
|
|
quickHash: function(theString) {
|
|
let hash = 0,
|
|
i,
|
|
chr;
|
|
if (theString.length === 0) return hash;
|
|
for (i = 0; i < theString.length; i++) {
|
|
chr = theString.charCodeAt(i);
|
|
hash = (hash << 5) - hash + chr;
|
|
hash |= 0; // Convert to 32bit integer
|
|
}
|
|
return hash;
|
|
},
|
|
///////////////////////////////
|
|
// CONVERT STRING TO BOOLEAN
|
|
// https://stackoverflow.com/a/1414175/8939
|
|
//
|
|
stringToBoolean: function(string) {
|
|
switch (string.toLowerCase().trim()) {
|
|
case "true":
|
|
case "yes":
|
|
case "1":
|
|
return true;
|
|
case "false":
|
|
case "no":
|
|
case "0":
|
|
case null:
|
|
return false;
|
|
default:
|
|
return Boolean(string);
|
|
}
|
|
}, ///////////////////////////////
|
|
// CONVERT STRING TO FLOAT
|
|
// https://stackoverflow.com/a/9409894/8939
|
|
//
|
|
stringToFloat: function(string) {
|
|
//null or empty then zero
|
|
if (!string) {
|
|
return 0;
|
|
}
|
|
|
|
//A number already then parse and return
|
|
if (window.$gz._.isNumber(string)) {
|
|
if (string === NaN) {
|
|
return 0;
|
|
}
|
|
return parseFloat(string);
|
|
}
|
|
|
|
//Not a string at all?
|
|
if (!window.$gz._.isString(string)) {
|
|
return 0;
|
|
}
|
|
|
|
let ret = parseFloat(string.replace(/[^\d.-]/g, ""));
|
|
if (ret == NaN) {
|
|
return 0;
|
|
}
|
|
|
|
return ret;
|
|
},
|
|
///////////////////////////////
|
|
// Splice a string
|
|
//changes the content of a string by removing a range of
|
|
// characters and/or adding new characters.
|
|
//
|
|
// @param {String} source string
|
|
// @param {number} start Index at which to start changing the string.
|
|
// @param {number} delCount An integer indicating the number of old chars to remove.
|
|
// @param {string} newSubStr The String that is spliced in.
|
|
// @return {string} A new string with the spliced substring.
|
|
stringSplice: function(source, start, delCount, newSubStr) {
|
|
if (source == null || source == "") {
|
|
if (newSubStr) {
|
|
return newSubStr;
|
|
}
|
|
return "";
|
|
}
|
|
return (
|
|
source.slice(0, start) +
|
|
newSubStr +
|
|
source.slice(start + Math.abs(delCount))
|
|
);
|
|
},
|
|
///////////////////////////////
|
|
// Format tags for display
|
|
//
|
|
//
|
|
// @param {String} tags raw from server
|
|
// @return {string} A new string with the tags formatted or an empty string if no tags
|
|
formatTags: function(tags) {
|
|
if (tags && tags.length > 0) {
|
|
return tags.join(", ");
|
|
}
|
|
return "";
|
|
},
|
|
///////////////////////////////
|
|
// ICON FOR *ALL* OBJECT TYPES
|
|
//(used for search results and event log / history)
|
|
//NOTE: Any object type could appear in event log, they all need to be supported where possible
|
|
//CoreBizObject add here
|
|
iconForType: function(ayaType) {
|
|
switch (ayaType) {
|
|
case window.$gz.type.NoType:
|
|
return "fa-genderless";
|
|
case window.$gz.type.Global:
|
|
return "fa-globe";
|
|
case window.$gz.type.User:
|
|
return "fa-user";
|
|
case window.$gz.type.Widget:
|
|
return "fa-vial";
|
|
case window.$gz.type.ServerState:
|
|
return "fa-door-open";
|
|
case window.$gz.type.License:
|
|
return "$ayiTicket";
|
|
case window.$gz.type.LogFile:
|
|
return "fa-glasses";
|
|
case window.$gz.type.PickListTemplate:
|
|
return "fa-pencil-ruler";
|
|
case window.$gz.type.ServerJob:
|
|
return "fa-robot";
|
|
case window.$gz.type.AyaNova7Import:
|
|
return "fa-file-import";
|
|
case window.$gz.type.TrialSeeder:
|
|
return "fa-seedling";
|
|
case window.$gz.type.Metrics:
|
|
return "fa-file-medical-alt";
|
|
case window.$gz.type.Translation:
|
|
return "fa-language";
|
|
case window.$gz.type.UserOptions:
|
|
return "$ayiUserCog";
|
|
case window.$gz.type.FileAttachment:
|
|
return "fa-paperclip";
|
|
case window.$gz.type.DataListView:
|
|
return "fa-filter";
|
|
case window.$gz.type.FormCustom:
|
|
return "$ayiCustomize";
|
|
default:
|
|
return null;
|
|
}
|
|
},
|
|
//https://gist.github.com/colemanw/9c9a12aae16a4bfe2678de86b661d922
|
|
iconForFile: function(fileName, mimeType) {
|
|
// List of official MIME Types: http://www.iana.org/assignments/media-types/media-types.xhtml
|
|
|
|
let extension = null;
|
|
if (fileName && fileName.includes(".")) {
|
|
extension = fileName.split(".").pop();
|
|
extension = extension.toLowerCase();
|
|
}
|
|
if (!extension && !mimeType) {
|
|
console.log(
|
|
"gzutil:iconForFile -> No mime or extension for " +
|
|
fileName +
|
|
" " +
|
|
mimeType
|
|
);
|
|
return "fa-file";
|
|
}
|
|
|
|
if (!mimeType) {
|
|
mimeType = "";
|
|
}
|
|
mimeType = mimeType.toLowerCase();
|
|
|
|
let iconFromExtension = extensions[extension];
|
|
let iconFromMIME = mimeTypes[mimeType];
|
|
|
|
if (iconFromMIME) {
|
|
return iconFromMIME;
|
|
}
|
|
if (iconFromExtension) {
|
|
return iconFromExtension;
|
|
}
|
|
|
|
return "fa-file";
|
|
},
|
|
///////////////////////////////////////////////
|
|
// attempt to detect image extension name
|
|
//
|
|
isImageAttachment: function(fileName, mimeType) {
|
|
return this.iconForFile(fileName, mimeType) == "fa-file-image";
|
|
},
|
|
///////////////////////////////////////////////
|
|
// Sleep async
|
|
//
|
|
sleepAsync: function(milliseconds) {
|
|
// eslint-disable-next-line
|
|
return new Promise((resolve) => setTimeout(resolve, milliseconds));
|
|
}
|
|
|
|
/**
|
|
*
|
|
*
|
|
*/
|
|
|
|
//new functions above here
|
|
};
|