diff --git a/client/package.json b/client/package.json
index 1d0b902aa40..6e013cd412a 100644
--- a/client/package.json
+++ b/client/package.json
@@ -142,7 +142,9 @@
"@babel/preset-typescript": "^7.18.6",
"@cerner/duplicate-package-checker-webpack-plugin": "^2.3.0",
"@testing-library/jest-dom": "^5.16.4",
+ "@types/jquery": "^3.5.16",
"@types/markdown-it": "^12.2.3",
+ "@types/underscore": "^1.11.4",
"@typescript-eslint/eslint-plugin": "^5.51.0",
"@typescript-eslint/parser": "^5.51.0",
"@vue/test-utils": "^1.3.4",
diff --git a/client/src/utils/utils.js b/client/src/utils/utils.ts
similarity index 77%
rename from client/src/utils/utils.js
rename to client/src/utils/utils.ts
index 3e3a9981f48..e19d013424b 100644
--- a/client/src/utils/utils.js
+++ b/client/src/utils/utils.ts
@@ -5,21 +5,21 @@
import _ from "underscore";
import $ from "jquery";
-import { getAppRoot } from "onload/loadConfig";
-import { getGalaxyInstance } from "app";
-import _l from "utils/localization";
+import { getAppRoot } from "@/onload/loadConfig";
+import { getGalaxyInstance } from "@/app";
+import _l from "@/utils/localization";
/** Builds a basic iframe */
-export function iframe(src) {
+export function iframe(src: string) {
return ``;
}
/** Traverse through json */
-export function deepeach(dict, callback) {
- for (var i in dict) {
- var d = dict[i];
+export function deepeach(dict: any, callback: any): void {
+ for (const i in dict) {
+ const d = dict[i];
if (_.isObject(d)) {
- var new_dict = callback(d);
+ const new_dict = callback(d);
if (new_dict) {
dict[i] = new_dict;
}
@@ -29,29 +29,26 @@ export function deepeach(dict, callback) {
}
/** Identifies urls and replaces them with anchors */
-export function linkify(inputText) {
- var replacedText;
- var replacePattern1;
- var replacePattern2;
- var replacePattern3;
+export function linkify(inputText: string): string {
+ let replacedText;
// URLs starting with http://, https://, or ftp://
- replacePattern1 = /(\b(https?|ftp):\/\/[-A-Z0-9+&@#/%?=~_|!:,.;]*[-A-Z0-9+&@#/%=~_|])/gim;
+ const replacePattern1 = /(\b(https?|ftp):\/\/[-A-Z0-9+&@#/%?=~_|!:,.;]*[-A-Z0-9+&@#/%=~_|])/gim;
replacedText = inputText.replace(replacePattern1, '$1');
// URLs starting with "www." (without // before it, or it'd re-link the ones done above).
- replacePattern2 = /(^|[^/])(www\.[\S]+(\b|$))/gim;
+ const replacePattern2 = /(^|[^/])(www\.[\S]+(\b|$))/gim;
replacedText = replacedText.replace(replacePattern2, '$1$2');
// Change email addresses to mailto:: links.
- replacePattern3 = /(([a-zA-Z0-9\-_.])+@[a-zA-Z_]+?(\.[a-zA-Z]{2,6})+)/gim;
+ const replacePattern3 = /(([a-zA-Z0-9\-_.])+@[a-zA-Z_]+?(\.[a-zA-Z]{2,6})+)/gim;
replacedText = replacedText.replace(replacePattern3, '$1');
return replacedText;
}
/** Clone */
-export function clone(obj) {
+export function clone(obj: T): T {
return JSON.parse(JSON.stringify(obj) || null);
}
@@ -59,7 +56,7 @@ export function clone(obj) {
* Check if a string is a json string
* @param{String} text - Content to be validated
*/
-export function isJSON(text) {
+export function isJSON(text: string): boolean {
return /^[\],:{}\s]*$/.test(
text
.replace(/\\["\\/bfnrtu]/g, "@")
@@ -72,7 +69,7 @@ export function isJSON(text) {
* Sanitize/escape a string
* @param{String} content - Content to be sanitized
*/
-export function sanitize(content) {
+export function sanitize(content: string): string {
return $("").text(content).html();
}
@@ -81,14 +78,14 @@ export function sanitize(content) {
* usually used for selectable options
* @param{String} value - Value or list to be validated
*/
-export function isEmpty(value) {
+export function isEmpty(value: any | any[]) {
if (!(value instanceof Array)) {
value = [value];
}
if (value.length === 0) {
return true;
}
- for (var i in value) {
+ for (const i in value) {
if (["__null__", "__undefined__", null, undefined].indexOf(value[i]) > -1) {
return true;
}
@@ -100,10 +97,10 @@ export function isEmpty(value) {
* Convert list to pretty string
* @param{String} lst - List of strings to be converted in human readable list sentence
*/
-export function textify(lst) {
+export function textify(lst: string[] | string): string {
if ($.isArray(lst)) {
lst = lst.toString().replace(/,/g, ", ");
- var pos = lst.lastIndexOf(", ");
+ const pos = lst.lastIndexOf(", ");
if (pos != -1) {
lst = `${lst.substr(0, pos)} or ${lst.substr(pos + 2)}`;
}
@@ -121,7 +118,7 @@ export function textify(lst) {
*/
export function get(options) {
top.__utils__get__ = top.__utils__get__ || {};
- var cache_key = JSON.stringify(options);
+ const cache_key = JSON.stringify(options);
if (options.cache && top.__utils__get__[cache_key]) {
if (options.success) {
options.success(top.__utils__get__[cache_key]);
@@ -154,9 +151,18 @@ export function get(options) {
* @param{Function} success - Callback on success
* @param{Function} error - Callback on error
*/
-export function request(options) {
+interface requestOptions {
+ type: "GET" | "POST" | "DELETE" | "PUT";
+ url: string;
+ data: any;
+ success: (response: any) => void;
+ error: (response: any, status: any) => void;
+ complete: (response: any, status: any) => void;
+}
+
+export function request(options: requestOptions) {
// prepare ajax
- var ajaxConfig = {
+ const ajaxConfig = {
contentType: "application/json",
type: options.type || "GET",
data: options.data || {},
@@ -190,7 +196,7 @@ export function request(options) {
}
})
.fail((response) => {
- var response_text = null;
+ let response_text = null;
try {
response_text = $.parseJSON(response.responseText);
} catch (e) {
@@ -212,10 +218,10 @@ export function request(options) {
* @param{String} classname - CSS class
* @param{String} name - CSS property
*/
-export function cssGetAttribute(classname, name) {
- var el = $(``);
+export function cssGetAttribute(classname: string, name: string): string {
+ const el = $(``);
el.appendTo(":eq(0)");
- var value = el.css(name);
+ const value = el.css(name);
el.remove();
return value;
}
@@ -224,7 +230,7 @@ export function cssGetAttribute(classname, name) {
* Load a CSS file
* @param{String} url - Url of CSS file
*/
-export function cssLoadFile(url) {
+export function cssLoadFile(url: string): void{
if (!$(`link[href^="${url}"]`).length) {
$(``).appendTo("head");
}
@@ -244,33 +250,33 @@ export function merge(options, optionsDefault) {
}
/**
- * Round floaing point 'number' to 'numPlaces' number of decimal places.
- * @param{Object} number a floaing point number
- * @param{Object} numPlaces number of decimal places
+ * Round floating point 'number' to 'numPlaces' number of decimal places.
+ * @param{number} number a floaing point number
+ * @param{number} numPlaces number of decimal places
*/
-export function roundToDecimalPlaces(number, numPlaces) {
- var placesMultiplier = 1;
- for (var i = 0; i < numPlaces; i++) {
+export function roundToDecimalPlaces(number: number, numPlaces: number) {
+ let placesMultiplier = 1;
+ for (const i = 0; i < numPlaces; i++) {
placesMultiplier *= 10;
}
return Math.round(number * placesMultiplier) / placesMultiplier;
}
// calculate on import
-var kb = 1024;
-var mb = kb * kb;
-var gb = mb * kb;
-var tb = gb * kb;
+const kb = 1024;
+const mb = kb * kb;
+const gb = mb * kb;
+const tb = gb * kb;
/**
* Format byte size to string with units
* @param{Integer} size - Size in bytes
* @param{Boolean} normal_font - Switches font between normal and bold
*/
-export function bytesToString(size, normal_font, numberPlaces) {
+export function bytesToString(size: number, normal_font: boolean, numberPlaces: number) {
numberPlaces = numberPlaces !== undefined ? numberPlaces : 1;
// identify unit
- var unit = "";
+ let unit = "";
if (size >= tb) {
size = size / tb;
unit = "TB";
@@ -289,7 +295,7 @@ export function bytesToString(size, normal_font, numberPlaces) {
return normal_font ? "0 b" : "-";
}
// return formatted string
- var rounded = unit == "b" ? size : roundToDecimalPlaces(size, numberPlaces);
+ const rounded = unit == "b" ? size : roundToDecimalPlaces(size, numberPlaces);
if (normal_font) {
return `${rounded} ${unit}`;
} else {
@@ -298,16 +304,16 @@ export function bytesToString(size, normal_font, numberPlaces) {
}
/** Create a unique id */
-export function uid() {
+export function uid(): string {
top.__utils__uid__ = top.__utils__uid__ || 0;
return `uid-${top.__utils__uid__++}`;
}
/** Create a time stamp */
-export function time() {
- var d = new Date();
- var hours = (d.getHours() < 10 ? "0" : "") + d.getHours();
- var minutes = (d.getMinutes() < 10 ? "0" : "") + d.getMinutes();
+export function time(): string {
+ const d = new Date();
+ const hours = (d.getHours() < 10 ? "0" : "") + d.getHours();
+ const minutes = (d.getMinutes() < 10 ? "0" : "") + d.getMinutes();
return `${d.getDate()}/${d.getMonth() + 1}/${d.getFullYear()}, ${hours}:${minutes}`;
}
@@ -324,7 +330,7 @@ export function appendScriptStyle(data) {
}
/** Get querystrings from url */
-export function getQueryString(key) {
+export function getQueryString(key: string): string {
return decodeURIComponent(
window.location.search.replace(
new RegExp(`^(?:.*[&\\?]${encodeURIComponent(key).replace(/[.+*]/g, "\\$&")}(?:\\=([^&]*))?)?.*$`, "i"),
@@ -333,7 +339,7 @@ export function getQueryString(key) {
);
}
-export function setWindowTitle(title) {
+export function setWindowTitle(title: string): void {
const Galaxy = getGalaxyInstance();
if (title) {
window.document.title = `Galaxy ${Galaxy.config.brand ? ` | ${Galaxy.config.brand}` : ""} | ${_l(title)}`;
@@ -350,12 +356,10 @@ export function setWindowTitle(title) {
* @param {string} str the input value
* @returns {integer}
*/
-export function hashFnv32a(str) {
- var i;
- var l;
- var hval = 0x811c9dc5;
+export function hashFnv32a(str: string): number {
+ let hval = 0x811c9dc5;
- for (i = 0, l = str.length; i < l; i++) {
+ for (const i = 0, l = str.length; i < l; i++) {
hval ^= str.charCodeAt(i);
hval += (hval << 1) + (hval << 4) + (hval << 7) + (hval << 8) + (hval << 24);
}
@@ -376,9 +380,9 @@ export async function waitForElementToBePresent(selector) {
/**
* Delays the next operation the specified amount of time.
- * @param {Number} delayInMilliseconds The amount of time to wait in milliseconds
+ * @param {number} delayInMilliseconds The amount of time to wait in milliseconds
*/
-export async function delay(delayInMilliseconds) {
+export async function delay(delayInMilliseconds: number) {
if (delayInMilliseconds > 0) {
await new Promise((r) => setTimeout(r, delayInMilliseconds));
}
diff --git a/client/yarn.lock b/client/yarn.lock
index 1255f88aa4b..0abe3f6abc9 100644
--- a/client/yarn.lock
+++ b/client/yarn.lock
@@ -2334,6 +2334,13 @@
jest-matcher-utils "^28.0.0"
pretty-format "^28.0.0"
+"@types/jquery@^3.5.16":
+ version "3.5.16"
+ resolved "https://registry.yarnpkg.com/@types/jquery/-/jquery-3.5.16.tgz#632131baf30951915b0317d48c98e9890bdf051d"
+ integrity sha512-bsI7y4ZgeMkmpG9OM710RRzDFp+w4P1RGiIt30C1mSBT+ExCleeh4HObwgArnDFELmRrOpXgSYN9VF1hj+f1lw==
+ dependencies:
+ "@types/sizzle" "*"
+
"@types/jsdom@^20.0.0":
version "20.0.1"
resolved "https://registry.yarnpkg.com/@types/jsdom/-/jsdom-20.0.1.tgz#07c14bc19bd2f918c1929541cdaacae894744808"
@@ -2436,6 +2443,11 @@
"@types/mime" "*"
"@types/node" "*"
+"@types/sizzle@*":
+ version "2.3.3"
+ resolved "https://registry.yarnpkg.com/@types/sizzle/-/sizzle-2.3.3.tgz#ff5e2f1902969d305225a047c8a0fd5c915cebef"
+ integrity sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ==
+
"@types/sockjs@^0.3.33":
version "0.3.33"
resolved "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.33.tgz"
@@ -2475,6 +2487,11 @@
resolved "https://registry.yarnpkg.com/@types/tough-cookie/-/tough-cookie-4.0.2.tgz#6286b4c7228d58ab7866d19716f3696e03a09397"
integrity sha512-Q5vtl1W5ue16D+nIaW8JWebSSraJVlK+EthKn7e7UcD4KWsaSJ8BqGPXNaPghgtcn/fhvrN17Tv8ksUsQpiplw==
+"@types/underscore@^1.11.4":
+ version "1.11.4"
+ resolved "https://registry.yarnpkg.com/@types/underscore/-/underscore-1.11.4.tgz#62e393f8bc4bd8a06154d110c7d042a93751def3"
+ integrity sha512-uO4CD2ELOjw8tasUrAhvnn2W4A0ZECOvMjCivJr4gA9pGgjv+qxKWY9GLTMVEK8ej85BxQOocUyE7hImmSQYcg==
+
"@types/web-bluetooth@^0.0.16":
version "0.0.16"
resolved "https://registry.yarnpkg.com/@types/web-bluetooth/-/web-bluetooth-0.0.16.tgz#1d12873a8e49567371f2a75fe3e7f7edca6662d8"