diff --git a/index.html b/index.html
index f5eea84..c4ecfdc 100644
--- a/index.html
+++ b/index.html
@@ -11,7 +11,7 @@
-
+
@@ -52,7 +52,7 @@
c2.769,0.502,5.056,1.75,6.865,3.751c1.807,1.999,2.71,4.539,2.71,7.616C254.326,269.095,253.684,271.288,252.394,273.174z">
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/package-lock.json b/package-lock.json
index 727384e..90f6607 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -13,6 +13,7 @@
"@isic/client": "^0.6.2",
"aws-sdk": "^2.910.0",
"axios": "^1.6.1",
+ "core-js": "^3.38.0",
"data-collection": "^1.1.6",
"file-saver": "^1.3.8",
"hint.css": "^2.6.0",
@@ -44,7 +45,7 @@
"eslint-import-resolver-alias": "^1.1.2",
"eslint-import-resolver-webpack": "^0.13.1",
"eslint-plugin-import": "^2.25.1",
- "html-loader": "^0.5.1",
+ "html-loader": "^5.0.0",
"html-webpack-plugin": "^5.3.2",
"jest": "^27.2.5",
"less": "^3.13.1",
@@ -1917,6 +1918,13 @@
"regenerator-runtime": "^0.13.4"
}
},
+ "node_modules/@babel/polyfill/node_modules/core-js": {
+ "version": "2.6.12",
+ "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz",
+ "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==",
+ "deprecated": "core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.",
+ "hasInstallScript": true
+ },
"node_modules/@babel/preset-env": {
"version": "7.15.8",
"resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.15.8.tgz",
@@ -2926,6 +2934,12 @@
"@jridgewell/sourcemap-codec": "1.4.14"
}
},
+ "node_modules/@leichtgewicht/ip-codec": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz",
+ "integrity": "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==",
+ "dev": true
+ },
"node_modules/@nodelib/fs.scandir": {
"version": "2.1.4",
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz",
@@ -3163,9 +3177,9 @@
"dev": true
},
"node_modules/@types/http-proxy": {
- "version": "1.17.8",
- "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.8.tgz",
- "integrity": "sha512-5kPLG5BKpWYkw/LVOGWpiq3nEVqxiN32rTgI53Sk12/xHFQ2rG3ehI9IO+O3W2QoKeyB92dJkoka8SUm6BX1pA==",
+ "version": "1.17.14",
+ "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.14.tgz",
+ "integrity": "sha512-SSrD0c1OQzlFX7pGu1eXxSEjemej64aaNPRhhVYUGqXh0BtldAAx37MG8btcumvpgKyZp1F5Gn3JkktdxiFv6w==",
"dev": true,
"dependencies": {
"@types/node": "*"
@@ -3227,6 +3241,15 @@
"integrity": "sha512-dxcOx8801kMo3KlU+C+/ctWrzREAH7YvoF3aoVpRdqgs+Kf7flp+PJDN/EX5bME3suDUZHsxes9hpvBmzYlWbA==",
"dev": true
},
+ "node_modules/@types/node-forge": {
+ "version": "1.3.11",
+ "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.11.tgz",
+ "integrity": "sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==",
+ "dev": true,
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
"node_modules/@types/prettier": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.4.1.tgz",
@@ -3298,9 +3321,9 @@
"dev": true
},
"node_modules/@types/ws": {
- "version": "8.2.2",
- "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.2.2.tgz",
- "integrity": "sha512-NOn5eIcgWLOo6qW8AcuLZ7G8PycXu0xTxxkS6Q18VWFxgPUSOwV0pBj2a/4viNZVu25i7RIB7GttdkAIUUXOOg==",
+ "version": "8.5.10",
+ "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz",
+ "integrity": "sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==",
"dev": true,
"dependencies": {
"@types/node": "*"
@@ -3879,19 +3902,6 @@
"node": ">= 6.0.0"
}
},
- "node_modules/aggregate-error": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz",
- "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==",
- "dev": true,
- "dependencies": {
- "clean-stack": "^2.0.0",
- "indent-string": "^4.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
"node_modules/ajv": {
"version": "6.12.6",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
@@ -4055,12 +4065,6 @@
"integrity": "sha1-bI4obRHtdoMn+OYuzuhzU8o+eLg=",
"dev": true
},
- "node_modules/array-flatten": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz",
- "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==",
- "dev": true
- },
"node_modules/array-includes": {
"version": "3.1.6",
"resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.6.tgz",
@@ -4139,15 +4143,6 @@
"get-intrinsic": "^1.1.3"
}
},
- "node_modules/ast-types": {
- "version": "0.9.6",
- "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.9.6.tgz",
- "integrity": "sha1-ECyenpAF0+fjgpvwxPok7oYu6bk=",
- "dev": true,
- "engines": {
- "node": ">= 0.8"
- }
- },
"node_modules/ast-types-flow": {
"version": "0.0.7",
"resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz",
@@ -4164,15 +4159,6 @@
"node": ">=8"
}
},
- "node_modules/async": {
- "version": "2.6.4",
- "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz",
- "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==",
- "dev": true,
- "dependencies": {
- "lodash": "^4.17.14"
- }
- },
"node_modules/asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
@@ -4519,12 +4505,15 @@
}
},
"node_modules/binary-extensions": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
- "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
+ "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==",
"dev": true,
"engines": {
"node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/body-parser": {
@@ -4584,18 +4573,14 @@
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
"dev": true
},
- "node_modules/bonjour": {
- "version": "3.5.0",
- "resolved": "https://registry.npmjs.org/bonjour/-/bonjour-3.5.0.tgz",
- "integrity": "sha1-jokKGD2O6aI5OzhExpGkK897yfU=",
+ "node_modules/bonjour-service": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.2.1.tgz",
+ "integrity": "sha512-oSzCS2zV14bh2kji6vNe7vrpJYCHGvcZnlffFQ1MEoX/WOeQ/teD8SYWKR942OI3INjq8OMNJlbPK5LLLUxFDw==",
"dev": true,
"dependencies": {
- "array-flatten": "^2.1.0",
- "deep-equal": "^1.0.1",
- "dns-equal": "^1.0.0",
- "dns-txt": "^2.0.2",
- "multicast-dns": "^6.0.1",
- "multicast-dns-service-types": "^1.1.0"
+ "fast-deep-equal": "^3.1.3",
+ "multicast-dns": "^7.2.5"
}
},
"node_modules/boolbase": {
@@ -4615,12 +4600,12 @@
}
},
"node_modules/braces": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
- "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
+ "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
"dev": true,
"dependencies": {
- "fill-range": "^7.0.1"
+ "fill-range": "^7.1.1"
},
"engines": {
"node": ">=8"
@@ -4689,12 +4674,6 @@
"integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==",
"dev": true
},
- "node_modules/buffer-indexof": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.1.tgz",
- "integrity": "sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g==",
- "dev": true
- },
"node_modules/bytes": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz",
@@ -4726,15 +4705,21 @@
}
},
"node_modules/camel-case": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz",
- "integrity": "sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M=",
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz",
+ "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==",
"dev": true,
"dependencies": {
- "no-case": "^2.2.0",
- "upper-case": "^1.1.1"
+ "pascal-case": "^3.1.2",
+ "tslib": "^2.0.3"
}
},
+ "node_modules/camel-case/node_modules/tslib": {
+ "version": "2.6.2",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
+ "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==",
+ "dev": true
+ },
"node_modules/camelcase": {
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
@@ -4788,9 +4773,9 @@
}
},
"node_modules/chokidar": {
- "version": "3.5.2",
- "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz",
- "integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==",
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
+ "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
"dev": true,
"dependencies": {
"anymatch": "~3.1.2",
@@ -4804,6 +4789,9 @@
"engines": {
"node": ">= 8.10.0"
},
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ },
"optionalDependencies": {
"fsevents": "~2.3.2"
}
@@ -4850,15 +4838,6 @@
"node": ">=0.10.0"
}
},
- "node_modules/clean-stack": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
- "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==",
- "dev": true,
- "engines": {
- "node": ">=6"
- }
- },
"node_modules/cliui": {
"version": "7.0.4",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
@@ -4927,10 +4906,13 @@
}
},
"node_modules/commander": {
- "version": "2.17.1",
- "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz",
- "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==",
- "dev": true
+ "version": "10.0.1",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz",
+ "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==",
+ "dev": true,
+ "engines": {
+ "node": ">=14"
+ }
},
"node_modules/commondir": {
"version": "1.0.1",
@@ -4990,9 +4972,9 @@
"dev": true
},
"node_modules/connect-history-api-fallback": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz",
- "integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==",
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz",
+ "integrity": "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==",
"dev": true,
"engines": {
"node": ">=0.8"
@@ -5143,11 +5125,14 @@
}
},
"node_modules/core-js": {
- "version": "2.6.12",
- "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz",
- "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==",
- "deprecated": "core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.",
- "hasInstallScript": true
+ "version": "3.38.0",
+ "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.38.0.tgz",
+ "integrity": "sha512-XPpwqEodRljce9KswjZShh95qJ1URisBeKCjUdq27YdenkslVe7OO0ZJhlYXAChW7OhXaRLl8AAba7IBfoIHug==",
+ "hasInstallScript": true,
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/core-js"
+ }
},
"node_modules/core-js-compat": {
"version": "3.31.1",
@@ -5388,23 +5373,6 @@
"integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=",
"dev": true
},
- "node_modules/deep-equal": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz",
- "integrity": "sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==",
- "dev": true,
- "dependencies": {
- "is-arguments": "^1.0.4",
- "is-date-object": "^1.0.1",
- "is-regex": "^1.0.4",
- "object-is": "^1.0.1",
- "object-keys": "^1.1.1",
- "regexp.prototype.flags": "^1.2.0"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
"node_modules/deep-is": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
@@ -5456,28 +5424,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/del": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/del/-/del-6.0.0.tgz",
- "integrity": "sha512-1shh9DQ23L16oXSZKB2JxpL7iMy2E0S9d517ptA1P8iw0alkPtQcrKH7ru31rYtKwF499HkTu+DRzq3TCKDFRQ==",
- "dev": true,
- "dependencies": {
- "globby": "^11.0.1",
- "graceful-fs": "^4.2.4",
- "is-glob": "^4.0.1",
- "is-path-cwd": "^2.2.0",
- "is-path-inside": "^3.0.2",
- "p-map": "^4.0.0",
- "rimraf": "^3.0.2",
- "slash": "^3.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
@@ -5541,29 +5487,16 @@
"node": ">=8"
}
},
- "node_modules/dns-equal": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz",
- "integrity": "sha1-s55/HabrCnW6nBcySzR1PEfgZU0=",
- "dev": true
- },
"node_modules/dns-packet": {
- "version": "1.3.4",
- "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.4.tgz",
- "integrity": "sha512-BQ6F4vycLXBvdrJZ6S3gZewt6rcrks9KBgM9vrhW+knGRqc8uEdT7fuCwloc7nny5xNoMJ17HGH0R/6fpo8ECA==",
- "dev": true,
- "dependencies": {
- "ip": "^1.1.0",
- "safe-buffer": "^5.0.1"
- }
- },
- "node_modules/dns-txt": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/dns-txt/-/dns-txt-2.0.2.tgz",
- "integrity": "sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY=",
+ "version": "5.6.1",
+ "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz",
+ "integrity": "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==",
"dev": true,
"dependencies": {
- "buffer-indexof": "^1.0.0"
+ "@leichtgewicht/ip-codec": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=6"
}
},
"node_modules/doctrine": {
@@ -5906,16 +5839,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/es6-templates": {
- "version": "0.2.3",
- "resolved": "https://registry.npmjs.org/es6-templates/-/es6-templates-0.2.3.tgz",
- "integrity": "sha1-XLmsn7He1usSOTQrgdeSu7QHjuQ=",
- "dev": true,
- "dependencies": {
- "recast": "~0.11.12",
- "through": "~2.3.6"
- }
- },
"node_modules/escalade": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
@@ -6919,12 +6842,6 @@
"integrity": "sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow==",
"dev": true
},
- "node_modules/fastparse": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.2.tgz",
- "integrity": "sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ==",
- "dev": true
- },
"node_modules/fastq": {
"version": "1.11.0",
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.11.0.tgz",
@@ -6973,9 +6890,9 @@
"integrity": "sha512-spKHSBQIxxS81N/O21WmuXA2F6wppUCsutpzenOeZzOCCJ5gEfcbqJP983IrpLXzYmXnMUa6J03SubcNPdKrlg=="
},
"node_modules/fill-range": {
- "version": "7.0.1",
- "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
- "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
+ "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
"dev": true,
"dependencies": {
"to-regex-range": "^5.0.1"
@@ -7486,37 +7403,89 @@
"dev": true
},
"node_modules/html-loader": {
- "version": "0.5.5",
- "resolved": "https://registry.npmjs.org/html-loader/-/html-loader-0.5.5.tgz",
- "integrity": "sha512-7hIW7YinOYUpo//kSYcPB6dCKoceKLmOwjEMmhIobHuWGDVl0Nwe4l68mdG/Ru0wcUxQjVMEoZpkalZ/SE7zog==",
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/html-loader/-/html-loader-5.0.0.tgz",
+ "integrity": "sha512-puaGKdjdVVIFRtgIC2n5dt5bt0N5j6heXlAQZ4Do1MLjHmOT1gCE1Ogg7XZNeJlnOVHHsrZKGs5dfh+XwZ3XPw==",
+ "dev": true,
+ "dependencies": {
+ "html-minifier-terser": "^7.2.0",
+ "parse5": "^7.1.2"
+ },
+ "engines": {
+ "node": ">= 18.12.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ },
+ "peerDependencies": {
+ "webpack": "^5.0.0"
+ }
+ },
+ "node_modules/html-loader/node_modules/clean-css": {
+ "version": "5.3.3",
+ "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.3.tgz",
+ "integrity": "sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==",
"dev": true,
"dependencies": {
- "es6-templates": "^0.2.3",
- "fastparse": "^1.1.1",
- "html-minifier": "^3.5.8",
- "loader-utils": "^1.1.0",
- "object-assign": "^4.1.1"
+ "source-map": "~0.6.0"
+ },
+ "engines": {
+ "node": ">= 10.0"
+ }
+ },
+ "node_modules/html-loader/node_modules/entities": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
+ "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.12"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/entities?sponsor=1"
}
},
- "node_modules/html-minifier": {
- "version": "3.5.21",
- "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-3.5.21.tgz",
- "integrity": "sha512-LKUKwuJDhxNa3uf/LPR/KVjm/l3rBqtYeCOAekvG8F1vItxMUpueGd94i/asDDr8/1u7InxzFA5EeGjhhG5mMA==",
+ "node_modules/html-loader/node_modules/html-minifier-terser": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-7.2.0.tgz",
+ "integrity": "sha512-tXgn3QfqPIpGl9o+K5tpcj3/MN4SfLtsx2GWwBC3SSd0tXQGyF3gsSqad8loJgKZGM3ZxbYDd5yhiBIdWpmvLA==",
"dev": true,
"dependencies": {
- "camel-case": "3.0.x",
- "clean-css": "4.2.x",
- "commander": "2.17.x",
- "he": "1.2.x",
- "param-case": "2.1.x",
- "relateurl": "0.2.x",
- "uglify-js": "3.4.x"
+ "camel-case": "^4.1.2",
+ "clean-css": "~5.3.2",
+ "commander": "^10.0.0",
+ "entities": "^4.4.0",
+ "param-case": "^3.0.4",
+ "relateurl": "^0.2.7",
+ "terser": "^5.15.1"
},
"bin": {
- "html-minifier": "cli.js"
+ "html-minifier-terser": "cli.js"
},
"engines": {
- "node": ">=4"
+ "node": "^14.13.1 || >=16.0.0"
+ }
+ },
+ "node_modules/html-loader/node_modules/parse5": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz",
+ "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==",
+ "dev": true,
+ "dependencies": {
+ "entities": "^4.4.0"
+ },
+ "funding": {
+ "url": "https://github.com/inikulin/parse5?sponsor=1"
+ }
+ },
+ "node_modules/html-loader/node_modules/source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
}
},
"node_modules/html-minifier-terser": {
@@ -7540,16 +7509,6 @@
"node": ">=6"
}
},
- "node_modules/html-minifier-terser/node_modules/camel-case": {
- "version": "4.1.2",
- "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz",
- "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==",
- "dev": true,
- "dependencies": {
- "pascal-case": "^3.1.2",
- "tslib": "^2.0.3"
- }
- },
"node_modules/html-minifier-terser/node_modules/commander": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
@@ -7559,16 +7518,6 @@
"node": ">= 6"
}
},
- "node_modules/html-minifier-terser/node_modules/param-case": {
- "version": "3.0.4",
- "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz",
- "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==",
- "dev": true,
- "dependencies": {
- "dot-case": "^3.0.4",
- "tslib": "^2.0.3"
- }
- },
"node_modules/html-minifier-terser/node_modules/source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
@@ -7601,12 +7550,6 @@
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
"dev": true
},
- "node_modules/html-minifier-terser/node_modules/tslib": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz",
- "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==",
- "dev": true
- },
"node_modules/html-webpack-plugin": {
"version": "5.3.2",
"resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.3.2.tgz",
@@ -7733,12 +7676,12 @@
}
},
"node_modules/http-proxy-middleware": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.1.tgz",
- "integrity": "sha512-cfaXRVoZxSed/BmkA7SwBVNI9Kj7HFltaE5rqYOub5kWzWZ+gofV2koVN1j2rMW7pEfSSlCHGJ31xmuyFyfLOg==",
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz",
+ "integrity": "sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==",
"dev": true,
"dependencies": {
- "@types/http-proxy": "^1.17.5",
+ "@types/http-proxy": "^1.17.8",
"http-proxy": "^1.18.1",
"is-glob": "^4.0.1",
"is-plain-obj": "^3.0.0",
@@ -7746,6 +7689,14 @@
},
"engines": {
"node": ">=12.0.0"
+ },
+ "peerDependencies": {
+ "@types/express": "^4.17.13"
+ },
+ "peerDependenciesMeta": {
+ "@types/express": {
+ "optional": true
+ }
}
},
"node_modules/https-proxy-agent": {
@@ -7871,15 +7822,6 @@
"node": ">=0.8.19"
}
},
- "node_modules/indent-string": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz",
- "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
"node_modules/inflight": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
@@ -7917,12 +7859,6 @@
"node": ">= 0.10"
}
},
- "node_modules/ip": {
- "version": "1.1.9",
- "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.9.tgz",
- "integrity": "sha512-cyRxvOEpNHNtchU3Ln9KC/auJgup87llfQpQ+t5ghoC/UhL16SWzbueiCsdTnWmqAWl7LadfuwhlqmtOaqMHdQ==",
- "dev": true
- },
"node_modules/ipaddr.js": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.0.1.tgz",
@@ -8133,24 +8069,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/is-path-cwd": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz",
- "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==",
- "dev": true,
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/is-path-inside": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
- "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
"node_modules/is-plain-obj": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz",
@@ -10290,6 +10208,16 @@
"language-subtag-registry": "^0.3.20"
}
},
+ "node_modules/launch-editor": {
+ "version": "2.8.0",
+ "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.8.0.tgz",
+ "integrity": "sha512-vJranOAJrI/llyWGRQqiDM+adrw+k83fvmmx3+nV47g3+36xM15jE+zyZ6Ffel02+xSvuM0b2GDRosXZkbb6wA==",
+ "dev": true,
+ "dependencies": {
+ "picocolors": "^1.0.0",
+ "shell-quote": "^1.8.1"
+ }
+ },
"node_modules/less": {
"version": "3.13.1",
"resolved": "https://registry.npmjs.org/less/-/less-3.13.1.tgz",
@@ -10499,12 +10427,6 @@
"loose-envify": "cli.js"
}
},
- "node_modules/lower-case": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz",
- "integrity": "sha1-miyr0bno4K6ZOkv31YdcOcQujqw=",
- "dev": true
- },
"node_modules/lru-cache": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
@@ -10769,18 +10691,6 @@
"integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==",
"dev": true
},
- "node_modules/mkdirp": {
- "version": "0.5.5",
- "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz",
- "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==",
- "dev": true,
- "dependencies": {
- "minimist": "^1.2.5"
- },
- "bin": {
- "mkdirp": "bin/cmd.js"
- }
- },
"node_modules/mouse-wheel-zoom": {
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/mouse-wheel-zoom/-/mouse-wheel-zoom-1.1.5.tgz",
@@ -10793,24 +10703,18 @@
"dev": true
},
"node_modules/multicast-dns": {
- "version": "6.2.3",
- "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.2.3.tgz",
- "integrity": "sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g==",
+ "version": "7.2.5",
+ "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz",
+ "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==",
"dev": true,
"dependencies": {
- "dns-packet": "^1.3.1",
+ "dns-packet": "^5.2.2",
"thunky": "^1.0.2"
},
"bin": {
"multicast-dns": "cli.js"
}
},
- "node_modules/multicast-dns-service-types": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz",
- "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=",
- "dev": true
- },
"node_modules/nanoid": {
"version": "3.3.6",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz",
@@ -10864,15 +10768,6 @@
"integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
"dev": true
},
- "node_modules/no-case": {
- "version": "2.3.2",
- "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz",
- "integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==",
- "dev": true,
- "dependencies": {
- "lower-case": "^1.1.1"
- }
- },
"node_modules/node-forge": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz",
@@ -10947,6 +10842,7 @@
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
"dev": true,
+ "peer": true,
"engines": {
"node": ">=0.10.0"
}
@@ -10959,22 +10855,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/object-is": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz",
- "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.1.3"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
"node_modules/object-keys": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
@@ -11189,21 +11069,6 @@
"node": ">=8"
}
},
- "node_modules/p-map": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz",
- "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==",
- "dev": true,
- "dependencies": {
- "aggregate-error": "^3.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/p-retry": {
"version": "4.6.1",
"resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.1.tgz",
@@ -11227,14 +11092,21 @@
}
},
"node_modules/param-case": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz",
- "integrity": "sha1-35T9jPZTHs915r75oIWPvHK+Ikc=",
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz",
+ "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==",
"dev": true,
"dependencies": {
- "no-case": "^2.2.0"
+ "dot-case": "^3.0.4",
+ "tslib": "^2.0.3"
}
},
+ "node_modules/param-case/node_modules/tslib": {
+ "version": "2.6.2",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
+ "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==",
+ "dev": true
+ },
"node_modules/parent-module": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
@@ -11387,29 +11259,6 @@
"node": ">=8"
}
},
- "node_modules/portfinder": {
- "version": "1.0.28",
- "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.28.tgz",
- "integrity": "sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA==",
- "dev": true,
- "dependencies": {
- "async": "^2.6.2",
- "debug": "^3.1.1",
- "mkdirp": "^0.5.5"
- },
- "engines": {
- "node": ">= 0.12.0"
- }
- },
- "node_modules/portfinder/node_modules/debug": {
- "version": "3.2.7",
- "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
- "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
- "dev": true,
- "dependencies": {
- "ms": "^2.1.1"
- }
- },
"node_modules/postcss": {
"version": "8.4.31",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz",
@@ -11562,15 +11411,6 @@
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
- "node_modules/private": {
- "version": "0.1.8",
- "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz",
- "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==",
- "dev": true,
- "engines": {
- "node": ">= 0.6"
- }
- },
"node_modules/process-nextick-args": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
@@ -11792,34 +11632,6 @@
"node": ">=8.10.0"
}
},
- "node_modules/recast": {
- "version": "0.11.23",
- "resolved": "https://registry.npmjs.org/recast/-/recast-0.11.23.tgz",
- "integrity": "sha1-RR/TAEqx5N+bTktmN2sqIZEkYtM=",
- "dev": true,
- "dependencies": {
- "ast-types": "0.9.6",
- "esprima": "~3.1.0",
- "private": "~0.1.5",
- "source-map": "~0.5.0"
- },
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/recast/node_modules/esprima": {
- "version": "3.1.3",
- "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz",
- "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=",
- "dev": true,
- "bin": {
- "esparse": "bin/esparse.js",
- "esvalidate": "bin/esvalidate.js"
- },
- "engines": {
- "node": ">=4"
- }
- },
"node_modules/rechoir": {
"version": "0.7.1",
"resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.1.tgz",
@@ -12160,12 +11972,13 @@
"dev": true
},
"node_modules/selfsigned": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.0.0.tgz",
- "integrity": "sha512-cUdFiCbKoa1mZ6osuJs2uDHrs0k0oprsKveFiiaBKCNq3SYyb5gs2HxhQyDNLCmL51ZZThqi4YNDpCK6GOP1iQ==",
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz",
+ "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==",
"dev": true,
"dependencies": {
- "node-forge": "^1.2.0"
+ "@types/node-forge": "^1.3.0",
+ "node-forge": "^1"
},
"engines": {
"node": ">=10"
@@ -12366,6 +12179,15 @@
"node": ">=8"
}
},
+ "node_modules/shell-quote": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz",
+ "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/side-channel": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
@@ -12971,12 +12793,6 @@
"integrity": "sha512-8hmiGIJMDlwjg7dlJ4yKGLK8EsYqKgPWbG3b4wjJddKNwc7N7Dpn08Df4szr/sZdMVeOstrdYSsqzX6BYbcB+w==",
"dev": true
},
- "node_modules/through": {
- "version": "2.3.8",
- "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
- "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=",
- "dev": true
- },
"node_modules/thunky": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz",
@@ -13184,37 +13000,6 @@
"resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz",
"integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA=="
},
- "node_modules/uglify-js": {
- "version": "3.4.10",
- "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.10.tgz",
- "integrity": "sha512-Y2VsbPVs0FIshJztycsO2SfPk7/KAF/T72qzv9u5EpQ4kB2hQoHlhNQTsNyy6ul7lQtqJN/AoWeS23OzEiEFxw==",
- "dev": true,
- "dependencies": {
- "commander": "~2.19.0",
- "source-map": "~0.6.1"
- },
- "bin": {
- "uglifyjs": "bin/uglifyjs"
- },
- "engines": {
- "node": ">=0.8.0"
- }
- },
- "node_modules/uglify-js/node_modules/commander": {
- "version": "2.19.0",
- "resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz",
- "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==",
- "dev": true
- },
- "node_modules/uglify-js/node_modules/source-map": {
- "version": "0.6.1",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
- "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/unbox-primitive": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz",
@@ -13317,12 +13102,6 @@
"browserslist": ">= 4.21.0"
}
},
- "node_modules/upper-case": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz",
- "integrity": "sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg=",
- "dev": true
- },
"node_modules/uri-js": {
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
@@ -13729,40 +13508,41 @@
}
},
"node_modules/webpack-dev-server": {
- "version": "4.7.3",
- "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.7.3.tgz",
- "integrity": "sha512-mlxq2AsIw2ag016nixkzUkdyOE8ST2GTy34uKSABp1c4nhjZvH90D5ZRR+UOLSsG4Z3TFahAi72a3ymRtfRm+Q==",
+ "version": "4.15.2",
+ "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.15.2.tgz",
+ "integrity": "sha512-0XavAZbNJ5sDrCbkpWL8mia0o5WPOd2YGtxrEiZkBK9FjLppIUK2TgxK6qGD2P3hUXTJNNPVibrerKcx5WkR1g==",
"dev": true,
"dependencies": {
"@types/bonjour": "^3.5.9",
"@types/connect-history-api-fallback": "^1.3.5",
+ "@types/express": "^4.17.13",
"@types/serve-index": "^1.9.1",
+ "@types/serve-static": "^1.13.10",
"@types/sockjs": "^0.3.33",
- "@types/ws": "^8.2.2",
+ "@types/ws": "^8.5.5",
"ansi-html-community": "^0.0.8",
- "bonjour": "^3.5.0",
- "chokidar": "^3.5.2",
+ "bonjour-service": "^1.0.11",
+ "chokidar": "^3.5.3",
"colorette": "^2.0.10",
"compression": "^1.7.4",
- "connect-history-api-fallback": "^1.6.0",
+ "connect-history-api-fallback": "^2.0.0",
"default-gateway": "^6.0.3",
- "del": "^6.0.0",
- "express": "^4.17.1",
+ "express": "^4.17.3",
"graceful-fs": "^4.2.6",
"html-entities": "^2.3.2",
- "http-proxy-middleware": "^2.0.0",
+ "http-proxy-middleware": "^2.0.3",
"ipaddr.js": "^2.0.1",
+ "launch-editor": "^2.6.0",
"open": "^8.0.9",
"p-retry": "^4.5.0",
- "portfinder": "^1.0.28",
+ "rimraf": "^3.0.2",
"schema-utils": "^4.0.0",
- "selfsigned": "^2.0.0",
+ "selfsigned": "^2.1.1",
"serve-index": "^1.9.1",
- "sockjs": "^0.3.21",
+ "sockjs": "^0.3.24",
"spdy": "^4.0.2",
- "strip-ansi": "^7.0.0",
- "webpack-dev-middleware": "^5.3.0",
- "ws": "^8.1.0"
+ "webpack-dev-middleware": "^5.3.4",
+ "ws": "^8.13.0"
},
"bin": {
"webpack-dev-server": "bin/webpack-dev-server.js"
@@ -13770,10 +13550,17 @@
"engines": {
"node": ">= 12.13.0"
},
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ },
"peerDependencies": {
"webpack": "^4.37.0 || ^5.0.0"
},
"peerDependenciesMeta": {
+ "webpack": {
+ "optional": true
+ },
"webpack-cli": {
"optional": true
}
@@ -13807,18 +13594,6 @@
"ajv": "^8.8.2"
}
},
- "node_modules/webpack-dev-server/node_modules/ansi-regex": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
- "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
- "dev": true,
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/chalk/ansi-regex?sponsor=1"
- }
- },
"node_modules/webpack-dev-server/node_modules/colorette": {
"version": "2.0.16",
"resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.16.tgz",
@@ -13850,32 +13625,17 @@
"url": "https://opencollective.com/webpack"
}
},
- "node_modules/webpack-dev-server/node_modules/strip-ansi": {
- "version": "7.0.1",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz",
- "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==",
- "dev": true,
- "dependencies": {
- "ansi-regex": "^6.0.1"
- },
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/chalk/strip-ansi?sponsor=1"
- }
- },
"node_modules/webpack-dev-server/node_modules/ws": {
- "version": "8.4.0",
- "resolved": "https://registry.npmjs.org/ws/-/ws-8.4.0.tgz",
- "integrity": "sha512-IHVsKe2pjajSUIl4KYMQOdlyliovpEPquKkqbwswulszzI7r0SfQrxnXdWAEqOlDCLrVSJzo+O1hAwdog2sKSQ==",
+ "version": "8.17.1",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz",
+ "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==",
"dev": true,
"engines": {
"node": ">=10.0.0"
},
"peerDependencies": {
"bufferutil": "^4.0.1",
- "utf-8-validate": "^5.0.2"
+ "utf-8-validate": ">=5.0.2"
},
"peerDependenciesMeta": {
"bufferutil": {
@@ -14138,9 +13898,9 @@
}
},
"node_modules/ws": {
- "version": "7.5.5",
- "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.5.tgz",
- "integrity": "sha512-BAkMFcAzl8as1G/hArkxOxq3G7pjUqQ3gzYbLL0/5zNkph70e+lCoxBGnm6AW1+/aiNeV4fnKqZ8m4GZewmH2w==",
+ "version": "7.5.10",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz",
+ "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==",
"dev": true,
"engines": {
"node": ">=8.3.0"
@@ -15598,6 +15358,13 @@
"requires": {
"core-js": "^2.6.5",
"regenerator-runtime": "^0.13.4"
+ },
+ "dependencies": {
+ "core-js": {
+ "version": "2.6.12",
+ "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz",
+ "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ=="
+ }
}
},
"@babel/preset-env": {
@@ -16390,6 +16157,12 @@
"@jridgewell/sourcemap-codec": "1.4.14"
}
},
+ "@leichtgewicht/ip-codec": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz",
+ "integrity": "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==",
+ "dev": true
+ },
"@nodelib/fs.scandir": {
"version": "2.1.4",
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz",
@@ -16614,9 +16387,9 @@
"dev": true
},
"@types/http-proxy": {
- "version": "1.17.8",
- "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.8.tgz",
- "integrity": "sha512-5kPLG5BKpWYkw/LVOGWpiq3nEVqxiN32rTgI53Sk12/xHFQ2rG3ehI9IO+O3W2QoKeyB92dJkoka8SUm6BX1pA==",
+ "version": "1.17.14",
+ "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.14.tgz",
+ "integrity": "sha512-SSrD0c1OQzlFX7pGu1eXxSEjemej64aaNPRhhVYUGqXh0BtldAAx37MG8btcumvpgKyZp1F5Gn3JkktdxiFv6w==",
"dev": true,
"requires": {
"@types/node": "*"
@@ -16678,6 +16451,15 @@
"integrity": "sha512-dxcOx8801kMo3KlU+C+/ctWrzREAH7YvoF3aoVpRdqgs+Kf7flp+PJDN/EX5bME3suDUZHsxes9hpvBmzYlWbA==",
"dev": true
},
+ "@types/node-forge": {
+ "version": "1.3.11",
+ "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.11.tgz",
+ "integrity": "sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==",
+ "dev": true,
+ "requires": {
+ "@types/node": "*"
+ }
+ },
"@types/prettier": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.4.1.tgz",
@@ -16749,9 +16531,9 @@
"dev": true
},
"@types/ws": {
- "version": "8.2.2",
- "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.2.2.tgz",
- "integrity": "sha512-NOn5eIcgWLOo6qW8AcuLZ7G8PycXu0xTxxkS6Q18VWFxgPUSOwV0pBj2a/4viNZVu25i7RIB7GttdkAIUUXOOg==",
+ "version": "8.5.10",
+ "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz",
+ "integrity": "sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==",
"dev": true,
"requires": {
"@types/node": "*"
@@ -17183,16 +16965,6 @@
"debug": "4"
}
},
- "aggregate-error": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz",
- "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==",
- "dev": true,
- "requires": {
- "clean-stack": "^2.0.0",
- "indent-string": "^4.0.0"
- }
- },
"ajv": {
"version": "6.12.6",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
@@ -17313,12 +17085,6 @@
"integrity": "sha1-bI4obRHtdoMn+OYuzuhzU8o+eLg=",
"dev": true
},
- "array-flatten": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz",
- "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==",
- "dev": true
- },
"array-includes": {
"version": "3.1.6",
"resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.6.tgz",
@@ -17376,12 +17142,6 @@
"get-intrinsic": "^1.1.3"
}
},
- "ast-types": {
- "version": "0.9.6",
- "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.9.6.tgz",
- "integrity": "sha1-ECyenpAF0+fjgpvwxPok7oYu6bk=",
- "dev": true
- },
"ast-types-flow": {
"version": "0.0.7",
"resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz",
@@ -17395,15 +17155,6 @@
"integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==",
"dev": true
},
- "async": {
- "version": "2.6.4",
- "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz",
- "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==",
- "dev": true,
- "requires": {
- "lodash": "^4.17.14"
- }
- },
"asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
@@ -17664,9 +17415,9 @@
"dev": true
},
"binary-extensions": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
- "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
+ "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==",
"dev": true
},
"body-parser": {
@@ -17718,18 +17469,14 @@
}
}
},
- "bonjour": {
- "version": "3.5.0",
- "resolved": "https://registry.npmjs.org/bonjour/-/bonjour-3.5.0.tgz",
- "integrity": "sha1-jokKGD2O6aI5OzhExpGkK897yfU=",
+ "bonjour-service": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.2.1.tgz",
+ "integrity": "sha512-oSzCS2zV14bh2kji6vNe7vrpJYCHGvcZnlffFQ1MEoX/WOeQ/teD8SYWKR942OI3INjq8OMNJlbPK5LLLUxFDw==",
"dev": true,
"requires": {
- "array-flatten": "^2.1.0",
- "deep-equal": "^1.0.1",
- "dns-equal": "^1.0.0",
- "dns-txt": "^2.0.2",
- "multicast-dns": "^6.0.1",
- "multicast-dns-service-types": "^1.1.0"
+ "fast-deep-equal": "^3.1.3",
+ "multicast-dns": "^7.2.5"
}
},
"boolbase": {
@@ -17749,12 +17496,12 @@
}
},
"braces": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
- "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
+ "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
"dev": true,
"requires": {
- "fill-range": "^7.0.1"
+ "fill-range": "^7.1.1"
}
},
"browser-process-hrtime": {
@@ -17800,12 +17547,6 @@
"integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==",
"dev": true
},
- "buffer-indexof": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.1.tgz",
- "integrity": "sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g==",
- "dev": true
- },
"bytes": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz",
@@ -17828,13 +17569,21 @@
"dev": true
},
"camel-case": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz",
- "integrity": "sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M=",
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz",
+ "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==",
"dev": true,
"requires": {
- "no-case": "^2.2.0",
- "upper-case": "^1.1.1"
+ "pascal-case": "^3.1.2",
+ "tslib": "^2.0.3"
+ },
+ "dependencies": {
+ "tslib": {
+ "version": "2.6.2",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
+ "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==",
+ "dev": true
+ }
}
},
"camelcase": {
@@ -17867,9 +17616,9 @@
"dev": true
},
"chokidar": {
- "version": "3.5.2",
- "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz",
- "integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==",
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
+ "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
"dev": true,
"requires": {
"anymatch": "~3.1.2",
@@ -17917,12 +17666,6 @@
}
}
},
- "clean-stack": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
- "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==",
- "dev": true
- },
"cliui": {
"version": "7.0.4",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
@@ -17981,9 +17724,9 @@
}
},
"commander": {
- "version": "2.17.1",
- "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz",
- "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==",
+ "version": "10.0.1",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz",
+ "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==",
"dev": true
},
"commondir": {
@@ -18040,9 +17783,9 @@
"dev": true
},
"connect-history-api-fallback": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz",
- "integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==",
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz",
+ "integrity": "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==",
"dev": true
},
"content-disposition": {
@@ -18145,9 +17888,9 @@
}
},
"core-js": {
- "version": "2.6.12",
- "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz",
- "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ=="
+ "version": "3.38.0",
+ "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.38.0.tgz",
+ "integrity": "sha512-XPpwqEodRljce9KswjZShh95qJ1URisBeKCjUdq27YdenkslVe7OO0ZJhlYXAChW7OhXaRLl8AAba7IBfoIHug=="
},
"core-js-compat": {
"version": "3.31.1",
@@ -18325,20 +18068,6 @@
"integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=",
"dev": true
},
- "deep-equal": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz",
- "integrity": "sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==",
- "dev": true,
- "requires": {
- "is-arguments": "^1.0.4",
- "is-date-object": "^1.0.1",
- "is-regex": "^1.0.4",
- "object-is": "^1.0.1",
- "object-keys": "^1.1.1",
- "regexp.prototype.flags": "^1.2.0"
- }
- },
"deep-is": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
@@ -18375,22 +18104,6 @@
"object-keys": "^1.1.1"
}
},
- "del": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/del/-/del-6.0.0.tgz",
- "integrity": "sha512-1shh9DQ23L16oXSZKB2JxpL7iMy2E0S9d517ptA1P8iw0alkPtQcrKH7ru31rYtKwF499HkTu+DRzq3TCKDFRQ==",
- "dev": true,
- "requires": {
- "globby": "^11.0.1",
- "graceful-fs": "^4.2.4",
- "is-glob": "^4.0.1",
- "is-path-cwd": "^2.2.0",
- "is-path-inside": "^3.0.2",
- "p-map": "^4.0.0",
- "rimraf": "^3.0.2",
- "slash": "^3.0.0"
- }
- },
"delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
@@ -18435,29 +18148,13 @@
"path-type": "^4.0.0"
}
},
- "dns-equal": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz",
- "integrity": "sha1-s55/HabrCnW6nBcySzR1PEfgZU0=",
- "dev": true
- },
"dns-packet": {
- "version": "1.3.4",
- "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.4.tgz",
- "integrity": "sha512-BQ6F4vycLXBvdrJZ6S3gZewt6rcrks9KBgM9vrhW+knGRqc8uEdT7fuCwloc7nny5xNoMJ17HGH0R/6fpo8ECA==",
- "dev": true,
- "requires": {
- "ip": "^1.1.0",
- "safe-buffer": "^5.0.1"
- }
- },
- "dns-txt": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/dns-txt/-/dns-txt-2.0.2.tgz",
- "integrity": "sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY=",
+ "version": "5.6.1",
+ "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz",
+ "integrity": "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==",
"dev": true,
"requires": {
- "buffer-indexof": "^1.0.0"
+ "@leichtgewicht/ip-codec": "^2.0.1"
}
},
"doctrine": {
@@ -18729,16 +18426,6 @@
"is-symbol": "^1.0.2"
}
},
- "es6-templates": {
- "version": "0.2.3",
- "resolved": "https://registry.npmjs.org/es6-templates/-/es6-templates-0.2.3.tgz",
- "integrity": "sha1-XLmsn7He1usSOTQrgdeSu7QHjuQ=",
- "dev": true,
- "requires": {
- "recast": "~0.11.12",
- "through": "~2.3.6"
- }
- },
"escalade": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
@@ -19500,12 +19187,6 @@
"integrity": "sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow==",
"dev": true
},
- "fastparse": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.2.tgz",
- "integrity": "sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ==",
- "dev": true
- },
"fastq": {
"version": "1.11.0",
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.11.0.tgz",
@@ -19548,9 +19229,9 @@
"integrity": "sha512-spKHSBQIxxS81N/O21WmuXA2F6wppUCsutpzenOeZzOCCJ5gEfcbqJP983IrpLXzYmXnMUa6J03SubcNPdKrlg=="
},
"fill-range": {
- "version": "7.0.1",
- "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
- "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
+ "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
"dev": true,
"requires": {
"to-regex-range": "^5.0.1"
@@ -19930,31 +19611,60 @@
"dev": true
},
"html-loader": {
- "version": "0.5.5",
- "resolved": "https://registry.npmjs.org/html-loader/-/html-loader-0.5.5.tgz",
- "integrity": "sha512-7hIW7YinOYUpo//kSYcPB6dCKoceKLmOwjEMmhIobHuWGDVl0Nwe4l68mdG/Ru0wcUxQjVMEoZpkalZ/SE7zog==",
- "dev": true,
- "requires": {
- "es6-templates": "^0.2.3",
- "fastparse": "^1.1.1",
- "html-minifier": "^3.5.8",
- "loader-utils": "^1.1.0",
- "object-assign": "^4.1.1"
- }
- },
- "html-minifier": {
- "version": "3.5.21",
- "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-3.5.21.tgz",
- "integrity": "sha512-LKUKwuJDhxNa3uf/LPR/KVjm/l3rBqtYeCOAekvG8F1vItxMUpueGd94i/asDDr8/1u7InxzFA5EeGjhhG5mMA==",
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/html-loader/-/html-loader-5.0.0.tgz",
+ "integrity": "sha512-puaGKdjdVVIFRtgIC2n5dt5bt0N5j6heXlAQZ4Do1MLjHmOT1gCE1Ogg7XZNeJlnOVHHsrZKGs5dfh+XwZ3XPw==",
"dev": true,
"requires": {
- "camel-case": "3.0.x",
- "clean-css": "4.2.x",
- "commander": "2.17.x",
- "he": "1.2.x",
- "param-case": "2.1.x",
- "relateurl": "0.2.x",
- "uglify-js": "3.4.x"
+ "html-minifier-terser": "^7.2.0",
+ "parse5": "^7.1.2"
+ },
+ "dependencies": {
+ "clean-css": {
+ "version": "5.3.3",
+ "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.3.tgz",
+ "integrity": "sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==",
+ "dev": true,
+ "requires": {
+ "source-map": "~0.6.0"
+ }
+ },
+ "entities": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
+ "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
+ "dev": true
+ },
+ "html-minifier-terser": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-7.2.0.tgz",
+ "integrity": "sha512-tXgn3QfqPIpGl9o+K5tpcj3/MN4SfLtsx2GWwBC3SSd0tXQGyF3gsSqad8loJgKZGM3ZxbYDd5yhiBIdWpmvLA==",
+ "dev": true,
+ "requires": {
+ "camel-case": "^4.1.2",
+ "clean-css": "~5.3.2",
+ "commander": "^10.0.0",
+ "entities": "^4.4.0",
+ "param-case": "^3.0.4",
+ "relateurl": "^0.2.7",
+ "terser": "^5.15.1"
+ }
+ },
+ "parse5": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz",
+ "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==",
+ "dev": true,
+ "requires": {
+ "entities": "^4.4.0"
+ }
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ }
}
},
"html-minifier-terser": {
@@ -19972,32 +19682,12 @@
"terser": "^4.6.3"
},
"dependencies": {
- "camel-case": {
- "version": "4.1.2",
- "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz",
- "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==",
- "dev": true,
- "requires": {
- "pascal-case": "^3.1.2",
- "tslib": "^2.0.3"
- }
- },
"commander": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
"integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==",
"dev": true
},
- "param-case": {
- "version": "3.0.4",
- "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz",
- "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==",
- "dev": true,
- "requires": {
- "dot-case": "^3.0.4",
- "tslib": "^2.0.3"
- }
- },
"source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
@@ -20022,12 +19712,6 @@
"dev": true
}
}
- },
- "tslib": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz",
- "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==",
- "dev": true
}
}
},
@@ -20126,12 +19810,12 @@
}
},
"http-proxy-middleware": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.1.tgz",
- "integrity": "sha512-cfaXRVoZxSed/BmkA7SwBVNI9Kj7HFltaE5rqYOub5kWzWZ+gofV2koVN1j2rMW7pEfSSlCHGJ31xmuyFyfLOg==",
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz",
+ "integrity": "sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==",
"dev": true,
"requires": {
- "@types/http-proxy": "^1.17.5",
+ "@types/http-proxy": "^1.17.8",
"http-proxy": "^1.18.1",
"is-glob": "^4.0.1",
"is-plain-obj": "^3.0.0",
@@ -20222,12 +19906,6 @@
"integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=",
"dev": true
},
- "indent-string": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz",
- "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==",
- "dev": true
- },
"inflight": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
@@ -20259,12 +19937,6 @@
"integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==",
"dev": true
},
- "ip": {
- "version": "1.1.9",
- "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.9.tgz",
- "integrity": "sha512-cyRxvOEpNHNtchU3Ln9KC/auJgup87llfQpQ+t5ghoC/UhL16SWzbueiCsdTnWmqAWl7LadfuwhlqmtOaqMHdQ==",
- "dev": true
- },
"ipaddr.js": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.0.1.tgz",
@@ -20394,18 +20066,6 @@
"has-tostringtag": "^1.0.0"
}
},
- "is-path-cwd": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz",
- "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==",
- "dev": true
- },
- "is-path-inside": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
- "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
- "dev": true
- },
"is-plain-obj": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz",
@@ -22000,6 +21660,16 @@
"language-subtag-registry": "^0.3.20"
}
},
+ "launch-editor": {
+ "version": "2.8.0",
+ "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.8.0.tgz",
+ "integrity": "sha512-vJranOAJrI/llyWGRQqiDM+adrw+k83fvmmx3+nV47g3+36xM15jE+zyZ6Ffel02+xSvuM0b2GDRosXZkbb6wA==",
+ "dev": true,
+ "requires": {
+ "picocolors": "^1.0.0",
+ "shell-quote": "^1.8.1"
+ }
+ },
"less": {
"version": "3.13.1",
"resolved": "https://registry.npmjs.org/less/-/less-3.13.1.tgz",
@@ -22161,12 +21831,6 @@
"js-tokens": "^3.0.0 || ^4.0.0"
}
},
- "lower-case": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz",
- "integrity": "sha1-miyr0bno4K6ZOkv31YdcOcQujqw=",
- "dev": true
- },
"lru-cache": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
@@ -22362,15 +22026,6 @@
"integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==",
"dev": true
},
- "mkdirp": {
- "version": "0.5.5",
- "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz",
- "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==",
- "dev": true,
- "requires": {
- "minimist": "^1.2.5"
- }
- },
"mouse-wheel-zoom": {
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/mouse-wheel-zoom/-/mouse-wheel-zoom-1.1.5.tgz",
@@ -22383,21 +22038,15 @@
"dev": true
},
"multicast-dns": {
- "version": "6.2.3",
- "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.2.3.tgz",
- "integrity": "sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g==",
+ "version": "7.2.5",
+ "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz",
+ "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==",
"dev": true,
"requires": {
- "dns-packet": "^1.3.1",
+ "dns-packet": "^5.2.2",
"thunky": "^1.0.2"
}
},
- "multicast-dns-service-types": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz",
- "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=",
- "dev": true
- },
"nanoid": {
"version": "3.3.6",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz",
@@ -22436,15 +22085,6 @@
"integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
"dev": true
},
- "no-case": {
- "version": "2.3.2",
- "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz",
- "integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==",
- "dev": true,
- "requires": {
- "lower-case": "^1.1.1"
- }
- },
"node-forge": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz",
@@ -22503,23 +22143,14 @@
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
- "dev": true
+ "dev": true,
+ "peer": true
},
"object-inspect": {
"version": "1.12.2",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz",
"integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ=="
},
- "object-is": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz",
- "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==",
- "dev": true,
- "requires": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.1.3"
- }
- },
"object-keys": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
@@ -22674,15 +22305,6 @@
"p-limit": "^2.2.0"
}
},
- "p-map": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz",
- "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==",
- "dev": true,
- "requires": {
- "aggregate-error": "^3.0.0"
- }
- },
"p-retry": {
"version": "4.6.1",
"resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.1.tgz",
@@ -22700,12 +22322,21 @@
"dev": true
},
"param-case": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz",
- "integrity": "sha1-35T9jPZTHs915r75oIWPvHK+Ikc=",
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz",
+ "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==",
"dev": true,
"requires": {
- "no-case": "^2.2.0"
+ "dot-case": "^3.0.4",
+ "tslib": "^2.0.3"
+ },
+ "dependencies": {
+ "tslib": {
+ "version": "2.6.2",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
+ "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==",
+ "dev": true
+ }
}
},
"parent-module": {
@@ -22832,28 +22463,6 @@
"find-up": "^4.0.0"
}
},
- "portfinder": {
- "version": "1.0.28",
- "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.28.tgz",
- "integrity": "sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA==",
- "dev": true,
- "requires": {
- "async": "^2.6.2",
- "debug": "^3.1.1",
- "mkdirp": "^0.5.5"
- },
- "dependencies": {
- "debug": {
- "version": "3.2.7",
- "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
- "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
- "dev": true,
- "requires": {
- "ms": "^2.1.1"
- }
- }
- }
- },
"postcss": {
"version": "8.4.31",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz",
@@ -22953,12 +22562,6 @@
}
}
},
- "private": {
- "version": "0.1.8",
- "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz",
- "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==",
- "dev": true
- },
"process-nextick-args": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
@@ -23135,26 +22738,6 @@
"picomatch": "^2.2.1"
}
},
- "recast": {
- "version": "0.11.23",
- "resolved": "https://registry.npmjs.org/recast/-/recast-0.11.23.tgz",
- "integrity": "sha1-RR/TAEqx5N+bTktmN2sqIZEkYtM=",
- "dev": true,
- "requires": {
- "ast-types": "0.9.6",
- "esprima": "~3.1.0",
- "private": "~0.1.5",
- "source-map": "~0.5.0"
- },
- "dependencies": {
- "esprima": {
- "version": "3.1.3",
- "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz",
- "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=",
- "dev": true
- }
- }
- },
"rechoir": {
"version": "0.7.1",
"resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.1.tgz",
@@ -23408,12 +22991,13 @@
"dev": true
},
"selfsigned": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.0.0.tgz",
- "integrity": "sha512-cUdFiCbKoa1mZ6osuJs2uDHrs0k0oprsKveFiiaBKCNq3SYyb5gs2HxhQyDNLCmL51ZZThqi4YNDpCK6GOP1iQ==",
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz",
+ "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==",
"dev": true,
"requires": {
- "node-forge": "^1.2.0"
+ "@types/node-forge": "^1.3.0",
+ "node-forge": "^1"
}
},
"semver": {
@@ -23587,6 +23171,12 @@
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
"dev": true
},
+ "shell-quote": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz",
+ "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==",
+ "dev": true
+ },
"side-channel": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
@@ -24052,12 +23642,6 @@
"integrity": "sha512-8hmiGIJMDlwjg7dlJ4yKGLK8EsYqKgPWbG3b4wjJddKNwc7N7Dpn08Df4szr/sZdMVeOstrdYSsqzX6BYbcB+w==",
"dev": true
},
- "through": {
- "version": "2.3.8",
- "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
- "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=",
- "dev": true
- },
"thunky": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz",
@@ -24219,30 +23803,6 @@
"resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz",
"integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA=="
},
- "uglify-js": {
- "version": "3.4.10",
- "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.10.tgz",
- "integrity": "sha512-Y2VsbPVs0FIshJztycsO2SfPk7/KAF/T72qzv9u5EpQ4kB2hQoHlhNQTsNyy6ul7lQtqJN/AoWeS23OzEiEFxw==",
- "dev": true,
- "requires": {
- "commander": "~2.19.0",
- "source-map": "~0.6.1"
- },
- "dependencies": {
- "commander": {
- "version": "2.19.0",
- "resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz",
- "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==",
- "dev": true
- },
- "source-map": {
- "version": "0.6.1",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
- "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
- "dev": true
- }
- }
- },
"unbox-primitive": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz",
@@ -24304,12 +23864,6 @@
"picocolors": "^1.0.0"
}
},
- "upper-case": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz",
- "integrity": "sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg=",
- "dev": true
- },
"uri-js": {
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
@@ -24663,40 +24217,41 @@
}
},
"webpack-dev-server": {
- "version": "4.7.3",
- "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.7.3.tgz",
- "integrity": "sha512-mlxq2AsIw2ag016nixkzUkdyOE8ST2GTy34uKSABp1c4nhjZvH90D5ZRR+UOLSsG4Z3TFahAi72a3ymRtfRm+Q==",
+ "version": "4.15.2",
+ "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.15.2.tgz",
+ "integrity": "sha512-0XavAZbNJ5sDrCbkpWL8mia0o5WPOd2YGtxrEiZkBK9FjLppIUK2TgxK6qGD2P3hUXTJNNPVibrerKcx5WkR1g==",
"dev": true,
"requires": {
"@types/bonjour": "^3.5.9",
"@types/connect-history-api-fallback": "^1.3.5",
+ "@types/express": "^4.17.13",
"@types/serve-index": "^1.9.1",
+ "@types/serve-static": "^1.13.10",
"@types/sockjs": "^0.3.33",
- "@types/ws": "^8.2.2",
+ "@types/ws": "^8.5.5",
"ansi-html-community": "^0.0.8",
- "bonjour": "^3.5.0",
- "chokidar": "^3.5.2",
+ "bonjour-service": "^1.0.11",
+ "chokidar": "^3.5.3",
"colorette": "^2.0.10",
"compression": "^1.7.4",
- "connect-history-api-fallback": "^1.6.0",
+ "connect-history-api-fallback": "^2.0.0",
"default-gateway": "^6.0.3",
- "del": "^6.0.0",
- "express": "^4.17.1",
+ "express": "^4.17.3",
"graceful-fs": "^4.2.6",
"html-entities": "^2.3.2",
- "http-proxy-middleware": "^2.0.0",
+ "http-proxy-middleware": "^2.0.3",
"ipaddr.js": "^2.0.1",
+ "launch-editor": "^2.6.0",
"open": "^8.0.9",
"p-retry": "^4.5.0",
- "portfinder": "^1.0.28",
+ "rimraf": "^3.0.2",
"schema-utils": "^4.0.0",
- "selfsigned": "^2.0.0",
+ "selfsigned": "^2.1.1",
"serve-index": "^1.9.1",
- "sockjs": "^0.3.21",
+ "sockjs": "^0.3.24",
"spdy": "^4.0.2",
- "strip-ansi": "^7.0.0",
- "webpack-dev-middleware": "^5.3.0",
- "ws": "^8.1.0"
+ "webpack-dev-middleware": "^5.3.4",
+ "ws": "^8.13.0"
},
"dependencies": {
"ajv": {
@@ -24720,12 +24275,6 @@
"fast-deep-equal": "^3.1.3"
}
},
- "ansi-regex": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
- "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
- "dev": true
- },
"colorette": {
"version": "2.0.16",
"resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.16.tgz",
@@ -24750,19 +24299,10 @@
"ajv-keywords": "^5.0.0"
}
},
- "strip-ansi": {
- "version": "7.0.1",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz",
- "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==",
- "dev": true,
- "requires": {
- "ansi-regex": "^6.0.1"
- }
- },
"ws": {
- "version": "8.4.0",
- "resolved": "https://registry.npmjs.org/ws/-/ws-8.4.0.tgz",
- "integrity": "sha512-IHVsKe2pjajSUIl4KYMQOdlyliovpEPquKkqbwswulszzI7r0SfQrxnXdWAEqOlDCLrVSJzo+O1hAwdog2sKSQ==",
+ "version": "8.17.1",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz",
+ "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==",
"dev": true,
"requires": {}
}
@@ -24928,9 +24468,9 @@
}
},
"ws": {
- "version": "7.5.5",
- "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.5.tgz",
- "integrity": "sha512-BAkMFcAzl8as1G/hArkxOxq3G7pjUqQ3gzYbLL0/5zNkph70e+lCoxBGnm6AW1+/aiNeV4fnKqZ8m4GZewmH2w==",
+ "version": "7.5.10",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz",
+ "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==",
"dev": true,
"requires": {}
},
diff --git a/package.json b/package.json
index 7c27dbd..16b4742 100644
--- a/package.json
+++ b/package.json
@@ -29,7 +29,7 @@
"eslint-import-resolver-alias": "^1.1.2",
"eslint-import-resolver-webpack": "^0.13.1",
"eslint-plugin-import": "^2.25.1",
- "html-loader": "^0.5.1",
+ "html-loader": "^5.0.0",
"html-webpack-plugin": "^5.3.2",
"jest": "^27.2.5",
"less": "^3.13.1",
@@ -45,6 +45,7 @@
"@isic/client": "^0.6.2",
"aws-sdk": "^2.910.0",
"axios": "^1.6.1",
+ "core-js": "^3.38.0",
"data-collection": "^1.1.6",
"file-saver": "^1.3.8",
"hint.css": "^2.6.0",
diff --git a/sources/constants.js b/sources/constants.js
index 507d4ee..bc6b830 100644
--- a/sources/constants.js
+++ b/sources/constants.js
@@ -184,11 +184,30 @@ export default {
NULL_OPTION_VALUE: "unknown",
MISSING_KEY_VALUE: "missing key",
+ DEFAULT_RIBBON_IMAGE_ICON_WIDTH: 14,
+ DEFAULT_RIBBON_IMAGE_ICON_HEIGHT: 14,
+ DEFAULT_RIBBON_ICON_CONTAINER_WIDTH: 18,
+ DEFAULT_RIBBON_ICON_CONTAINER_HEIGHT: 18,
DEFAULT_GALLERY_IMAGE_ICON_WIDTH: 18,
DEFAULT_GALLERY_IMAGE_ICON_HEIGHT: 18,
DEFAULT_GALLERY_IMAGE_ICON_CONTAINER_WIDTH: 22,
DEFAULT_GALLERY_IMAGE_ICON_CONTAINER_HEIGHT: 22,
DEFAULT_GALLERY_IMAGE_NAME_FONT_SIZE: 14,
DEFAULT_GALLERY_IMAGE_WIDTH: 180,
- DEFAULT_GALLERY_IMAGE_HEIGHT: 123
+ DEFAULT_GALLERY_IMAGE_HEIGHT: 123,
+
+ // MultiLesion
+ MULTI_LESION_GROUP_BY: {
+ TIME: "Time Point",
+ TYPE: "Modality",
+ COMBINATION: "Time Point and Modality",
+ NO_GROUP: "No group"
+ },
+ MULTI_LESION_SIDE: {
+ LEFT: "left",
+ RIGHT: "right",
+ },
+ MULTI_LESION_TYPE_PRIORITY: {
+ FIRST: "dermoscopic"
+ },
};
diff --git a/sources/models/lesionWindowImagesUrls.js b/sources/models/lesionWindowImagesUrls.js
new file mode 100644
index 0000000..cdad7ba
--- /dev/null
+++ b/sources/models/lesionWindowImagesUrls.js
@@ -0,0 +1,47 @@
+let prevImagesUrl = "";
+let nextImagesUrl = "";
+let currImagesUrl = "";
+let offset = 0;
+
+function setCurrImagesUrl(url) {
+ currImagesUrl = url;
+}
+
+function getCurrImagesUrl() {
+ return currImagesUrl;
+}
+
+function setNextImagesUrl(url) {
+ nextImagesUrl = url;
+}
+
+function getNextImagesUrl() {
+ return nextImagesUrl;
+}
+
+function setPrevImagesUrl(url) {
+ prevImagesUrl = url;
+}
+
+function getPrevImagesUrl() {
+ return prevImagesUrl;
+}
+
+function getOffset() {
+ return offset;
+}
+
+function setOffset(newOffset) {
+ offset = newOffset;
+}
+
+export default {
+ getCurrImagesUrl,
+ setCurrImagesUrl,
+ getNextImagesUrl,
+ setNextImagesUrl,
+ getPrevImagesUrl,
+ setPrevImagesUrl,
+ getOffset,
+ setOffset,
+};
diff --git a/sources/models/lesionsModel.js b/sources/models/lesionsModel.js
new file mode 100644
index 0000000..aeee28b
--- /dev/null
+++ b/sources/models/lesionsModel.js
@@ -0,0 +1,388 @@
+import groupBy from "core-js/actual/object/group-by";
+
+const lesionsMap = new Map();
+let currentItem;
+let leftMode;
+let rightMode;
+let leftImage;
+let rightImage;
+/** @type {webix.DataCollection} */
+const currentLeftImagesCollection = new webix.DataCollection();
+/** @type {webix.DataCollection} */
+const currentRightImagesCollection = new webix.DataCollection();
+
+function getLesionByID(lesionID) {
+ if (lesionID) {
+ const lesion = lesionsMap.get(lesionID);
+ return lesion ?? null;
+ }
+ return null;
+}
+
+function setLesionByID(lesionID, lesion) {
+ if (lesion) {
+ lesionsMap.set(lesionID, lesion);
+ }
+ return lesion;
+}
+
+function setLesions(lesions) {
+ if (Array.isArray(lesions)) {
+ lesions.push(...lesions);
+ }
+ lesions.forEach((l) => {
+ lesionsMap.set(l.id, l);
+ });
+}
+
+function getLesionImagesCount(lesionID) {
+ const lesion = getLesionByID(lesionID);
+ return lesion?.images_count ?? 0;
+}
+
+function getLesionAnchorImageID(lesionID) {
+ const lesion = getLesionByID(lesionID);
+ return lesion?.index_image_id;
+}
+
+function checkIsImageAnchor(image) {
+ const lesionID = getItemLesionID(image);
+ if (lesionID) {
+ const lesionAnchorImageID = getAnchorImageID(lesionID);
+ return lesionAnchorImageID === getItemID(image);
+ }
+ return false;
+}
+
+function getLesionModalitiesCount(lesionID) {
+ const lesion = getLesionByID(lesionID);
+ if (lesion) {
+ const images = lesion.images;
+ const lesionModalitiesCount = images.reduce((modalities, img) => {
+ const imgModality = getImageModality(img);
+ if (modalities.includes(imgModality)) {
+ return modalities;
+ }
+ modalities.push(imgModality);
+ return modalities;
+ }, [])?.length;
+ return lesionModalitiesCount;
+ }
+ return 0;
+}
+
+function getImagesWithModalityCount(item) {
+ const lesionID = getItemLesionID(item);
+ const lesion = getLesionByID(lesionID);
+ if (lesion) {
+ const modality = getItemModality(item);
+ const images = lesion.images;
+ const lesionModalityImagesCount = images.filter(i => getImageModality(i) === modality).length;
+ return lesionModalityImagesCount;
+ }
+ return 0;
+}
+
+function getLesionTimePoints(lesionID) {
+ const lesion = getLesionByID(lesionID);
+ const images = lesion?.images;
+ const lesionTimePoints = images?.reduce((timePoints, img) => {
+ const imgTimePoint = getImageTimePoint(img);
+ if (timePoints.includes(imgTimePoint)) {
+ return timePoints;
+ }
+ timePoints.push(imgTimePoint);
+ return timePoints;
+ }, []);
+ return lesionTimePoints ?? [];
+}
+
+function getLesionTimePointsCount(lesionID) {
+ const lesionTimePoints = getLesionTimePoints(lesionID);
+ return lesionTimePoints?.length ?? 0;
+}
+
+function getImagesWithTimePointsCount(item) {
+ const lesionID = getItemLesionID(item);
+ const lesion = getLesionByID(lesionID);
+ if (lesion) {
+ const timePoint = getItemTimePoint(item);
+ const images = lesion?.images;
+ const lesionTimePointsImagesCount = images
+ .filter(i => getImageTimePoint(i) === timePoint).length;
+ return lesionTimePointsImagesCount;
+ }
+ return 0;
+}
+
+function getLesionImages(lesionID) {
+ const lesion = getLesionByID(lesionID);
+ return lesion?.images ?? [];
+}
+
+function getModalityImages(lesionID, modality) {
+ const lesionImages = getLesionImages(lesionID);
+ return lesionImages?.filter(i => getImageModality(i) === modality);
+}
+
+function getTimePointImages(lesionID, timePoint) {
+ const lesionImages = getLesionImages(lesionID);
+ return lesionImages?.filter(i => getImageTimePoint(i) === timePoint);
+}
+
+// combine is time point and modality
+function getCombineImages(lesionID, timePoint, modality) {
+ const lesionImages = getLesionImages(lesionID);
+ return lesionImages?.filter((i) => {
+ const result = getImageTimePoint(i) === timePoint && getImageModality(i) === modality;
+ return result;
+ });
+}
+
+function getAnchorImageID(lesionID) {
+ const lesion = getLesionByID(lesionID);
+ return lesion?.index_image_id ?? null;
+}
+
+function getFirstNonAnchorImage(lesionID, anchorImageID) {
+ const timePoints = getLesionTimePoints(lesionID);
+ const lesionImages = getLesionImages(lesionID);
+ const anchorImage = lesionImages.find(i => getItemID(i) === anchorImageID);
+ const anchorTimePoint = getImageTimePoint(anchorImage);
+ const sortedTimePoints = timePoints.sort((a, b) => a - b);
+ const firstTimePoint = sortedTimePoints[0];
+ let nonAnchorImage;
+ if (timePoints.length === 1) {
+ nonAnchorImage = lesionImages.find(i => anchorImageID !== getItemID(i))
+ ?? lesionImages[0];
+ }
+ else if (anchorTimePoint === firstTimePoint) {
+ const secondTimePoint = sortedTimePoints[1];
+ nonAnchorImage = lesionImages.find(i => getImageTimePoint(i) === secondTimePoint);
+ }
+ else {
+ nonAnchorImage = lesionImages.find(i => getImageTimePoint(i) === firstTimePoint);
+ }
+ return nonAnchorImage;
+}
+
+function getImageTimePoint(image) {
+ return image?.metadata?.clinical?.acquisition_day;
+}
+
+function getImageModality(image) {
+ return image?.metadata?.acquisition?.image_type;
+}
+
+function getItemLesionID(item) {
+ return item?.metadata?.clinical?.lesion_id;
+}
+
+function checkMultipleModality(lesionID) {
+ const lesionModalitiesCount = getLesionModalitiesCount(lesionID);
+ return lesionModalitiesCount > 1;
+}
+
+function getCurrentItem() {
+ return currentItem;
+}
+
+function setCurrentItem(item) {
+ currentItem = item;
+}
+
+function getItemID(item) {
+ return item?.isic_id;
+}
+
+function getItemTimePoint(item) {
+ return item?.metadata?.clinical?.acquisition_day;
+}
+
+function getItemModality(item) {
+ return item?.metadata?.acquisition?.image_type;
+}
+
+function getUploadDay(item) {
+ return item?.contribution_day;
+}
+
+function getLeftMode() {
+ return leftMode;
+}
+
+function setLeftMode(mode) {
+ leftMode = mode;
+}
+
+function getRightMode() {
+ return rightMode;
+}
+
+function setRightMode(mode) {
+ rightMode = mode;
+}
+
+function getLeftImage() {
+ return leftImage;
+}
+
+function setLeftImage(image) {
+ leftImage = image;
+}
+
+function getRightImage() {
+ return rightImage;
+}
+
+function setRightImage(image) {
+ rightImage = image;
+}
+
+function groupByTimePoint(images) {
+ const imagesGroups = !Object.groupBy
+ ? Object.groupBy(images, i => getImageTimePoint(i))
+ : groupBy(images, i => getImageTimePoint(i));
+ return imagesGroups;
+}
+
+function groupByModality(images) {
+ const imagesGroups = !Object.groupBy
+ ? Object.groupBy(images, i => getImageModality(i))
+ : groupBy(images, i => getImageTimePoint(i));
+ return imagesGroups;
+}
+
+function groupByTimePointAndModality(images) {
+ const timePointGroups = !Object.groupBy
+ ? Object.groupBy(images, i => getImageTimePoint(i))
+ : groupBy(images, i => getImageTimePoint(i));
+ const timePointKeys = Object.keys(timePointGroups);
+ const imagesGroups = {};
+ timePointKeys.forEach((tpk) => {
+ const modalityGroups = !Object.groupBy
+ ? Object.groupBy(timePointGroups[tpk], i => getImageModality(i))
+ : groupBy(timePointGroups[tpk], i => getImageModality(i));
+ const modalityKeys = Object.keys(modalityGroups);
+ modalityKeys.forEach((mk) => {
+ imagesGroups[`${tpk} and ${mk}`] = modalityGroups[mk];
+ });
+ });
+ return imagesGroups;
+}
+
+function groupByID(images) {
+ const imagesGroups = !Object.groupBy
+ ? Object.groupBy(images, i => getItemID(i))
+ : groupBy(images, i => getItemID(i));
+ return imagesGroups;
+}
+
+function setCurrentLeftImages(images) {
+ currentLeftImagesCollection.clearAll();
+ currentLeftImagesCollection.parse(images);
+}
+
+function getCurrentLeftImages() {
+ return currentLeftImagesCollection.serialize();
+}
+
+function setCurrentRightImages(images) {
+ currentRightImagesCollection.clearAll();
+ currentRightImagesCollection.parse(images);
+}
+
+function getCurrentRightImages() {
+ return currentRightImagesCollection.serialize();
+}
+
+function getNextLeftImage(image) {
+ const currentImage = currentLeftImagesCollection.find(
+ i => getItemID(i) === getItemID(image),
+ true
+ );
+ const nextImageId = currentLeftImagesCollection.getNextId(currentImage.id)
+ ?? currentLeftImagesCollection.getFirstId();
+ const nextImage = currentLeftImagesCollection.getItem(nextImageId);
+ return nextImage;
+}
+
+function getNextRightImage(image) {
+ const currentImage = currentRightImagesCollection.find(
+ i => getItemID(i) === getItemID(image),
+ true
+ );
+ const nextImageId = currentRightImagesCollection.getNextId(currentImage.id)
+ ?? currentRightImagesCollection.getFirstId();
+ const nextImage = currentRightImagesCollection.getItem(nextImageId);
+ return nextImage;
+}
+
+function getPrevLeftImage(image) {
+ const currentImage = currentLeftImagesCollection.find(
+ i => getItemID(i) === getItemID(image),
+ true
+ );
+ const prevImageId = currentLeftImagesCollection.getPrevId(currentImage.id)
+ ?? currentLeftImagesCollection.getLastId();
+ const prevImage = currentLeftImagesCollection.getItem(prevImageId);
+ return prevImage;
+}
+
+function getPrevRightImage(image) {
+ const currentImage = currentRightImagesCollection.find(
+ i => getItemID(i) === getItemID(image),
+ true
+ );
+ const prevImageId = currentRightImagesCollection.getPrevId(currentImage.id)
+ ?? currentRightImagesCollection.getLastId();
+ const prevImage = currentRightImagesCollection.getItem(prevImageId);
+ return prevImage;
+}
+
+export default {
+ setLesions,
+ getLesionByID,
+ setLesionByID,
+ getLesionImagesCount,
+ getLesionModalitiesCount,
+ getModalityImages,
+ getImagesWithModalityCount,
+ getLesionTimePointsCount,
+ getLesionAnchorImageID,
+ getLesionImages,
+ getTimePointImages,
+ getCombineImages,
+ getImagesWithTimePointsCount,
+ getAnchorImageID,
+ getItemLesionID,
+ checkMultipleModality,
+ getCurrentItem,
+ setCurrentItem,
+ getItemID,
+ getItemTimePoint,
+ getItemModality,
+ getUploadDay,
+ getLeftMode,
+ setLeftMode,
+ getRightMode,
+ setRightMode,
+ getLeftImage,
+ setLeftImage,
+ getRightImage,
+ setRightImage,
+ checkIsImageAnchor,
+ getFirstNonAnchorImage,
+ groupByModality,
+ groupByTimePoint,
+ groupByTimePointAndModality,
+ groupByID,
+ setCurrentLeftImages,
+ getCurrentLeftImages,
+ setCurrentRightImages,
+ getCurrentRightImages,
+ getPrevLeftImage,
+ getNextLeftImage,
+ getPrevRightImage,
+ getNextRightImage,
+};
diff --git a/sources/models/state.js b/sources/models/state.js
index 7bd851e..2e100f0 100644
--- a/sources/models/state.js
+++ b/sources/models/state.js
@@ -29,7 +29,11 @@ const state = {
toolbarValues: {}
};
},
- imagesOffset: 0
+ imagesOffset: 0,
+ filteredImages: {
+ isImagesFiltered: false,
+ filteredImagesCount: 0
+ }
};
export default state;
diff --git a/sources/services/ajaxActions.js b/sources/services/ajaxActions.js
index ecb2220..93e2a80 100644
--- a/sources/services/ajaxActions.js
+++ b/sources/services/ajaxActions.js
@@ -66,6 +66,7 @@ class AjaxActions {
async _ajaxGet(url, params) {
const headers = await getAuthHeaders();
+ headers["Content-Type"] = "application/json";
if (!params) {
params = {};
}
@@ -248,6 +249,28 @@ class AjaxActions {
}
return null;
}
+
+ async getLesions(/* sourceParams */) {
+ try {
+ const result = await this._ajaxGet(`${API_URL}lesions/`);
+ return this._parseData(result);
+ }
+ catch (error) {
+ parseError(error);
+ return [];
+ }
+ }
+
+ async getLesionByID(lesionID) {
+ try {
+ const result = await this._ajaxGet(`${API_URL}lesions/${lesionID}`);
+ return this._parseData(result);
+ }
+ catch (error) {
+ parseError(error);
+ return null;
+ }
+ }
}
const instance = new AjaxActions();
diff --git a/sources/services/gallery/gallery.js b/sources/services/gallery/gallery.js
index 78b4d6e..7a61a9b 100644
--- a/sources/services/gallery/gallery.js
+++ b/sources/services/gallery/gallery.js
@@ -5,6 +5,7 @@ import constants from "../../constants";
import appliedFilterModel from "../../models/appliedFilters";
import galleryImagesUrls from "../../models/galleryImagesUrls";
import filtersData from "../../models/imagesFilters";
+import lesionsModel from "../../models/lesionsModel";
import selectedImages from "../../models/selectedGalleryImages";
import state from "../../models/state";
import util from "../../utils/util";
@@ -35,6 +36,7 @@ class GalleryService {
imageWindowMetadata,
metadataWindow,
metadataWindowMetadata,
+ multiImageLesionWindow,
filtersForm,
appliedFiltersList,
unselectLink,
@@ -66,6 +68,7 @@ class GalleryService {
this._imageWindowMetadata = imageWindowMetadata;
this._metadataWindow = metadataWindow;
this._metadataWindowMetadata = metadataWindowMetadata;
+ this._multiImageLesionWindow = multiImageLesionWindow;
this._filtersForm = filtersForm;
this._appliedFiltersList = appliedFiltersList;
this._imagesSelectionTemplate = unselectLink;
@@ -440,7 +443,9 @@ class GalleryService {
const filtered = state.imagesTotalCounts.passedFilters.filtered;
this._updateContentHeaderTemplate({
rangeStart: offset + 1,
- rangeFinish: currentCount && offset + limit >= currentCount ? currentCount : offset + limit,
+ rangeFinish: currentCount && offset + limit >= currentCount
+ ? currentCount
+ : offset + limit,
totalCount: count,
currentCount,
filtered
@@ -636,6 +641,16 @@ class GalleryService {
}
};
+ this._imagesDataview.on_click["layer-group"] = (e, id) => {
+ if (this._multiImageLesionWindow) {
+ const currentItem = this._imagesDataview.getItem(id);
+ this._view.$scope.setMultiLesionMode(
+ currentItem,
+ );
+ this._multiImageLesionWindow.show();
+ }
+ };
+
// -->add onClick property for template
this._imagesSelectionTemplate?.define("onClick", {
"unselect-images-link": () => {
@@ -1139,6 +1154,12 @@ class GalleryService {
}
_updateContentHeaderTemplate(ranges) {
+ if (ranges.filtered) {
+ state.filteredImages.isImagesFiltered = true;
+ if (ranges.currentCount) {
+ state.filteredImages.filteredImagesCount = ranges.currentCount;
+ }
+ }
const values = webix.copy(ranges);
this._contentHeaderTemplate?.setValues(values, true); // true -> unchange existing values
this._contentHeaderTemplate?.refresh();
@@ -1279,9 +1300,17 @@ class GalleryService {
galleryImagesUrls.setNextImagesUrl(images.next);
galleryImagesUrls.setPrevImagesUrl(images.previous);
if (images && images.results.length > 0) {
- images.results.forEach((item) => {
+ for await (const item of images.results) {
item.markCheckbox = selectedImages.isSelected(item.isic_id);
- });
+ const lesionID = lesionsModel.getItemLesionID(item);
+ const lesion = lesionID ? await lesionsModel.getLesionByID(lesionID) : null;
+ if (lesionID && !lesion) {
+ const newLesion = await ajax.getLesionByID(lesionID);
+ if (newLesion) {
+ await lesionsModel.setLesionByID(lesionID, newLesion);
+ }
+ }
+ }
parseDataToDataview(images);
}
else {
@@ -1462,7 +1491,7 @@ class GalleryService {
_searchEventsMethods(eventMethod) {
this._searchInput.detachEvent("onEnter");
- this._searchInput.on_click["fa-search"] = eventMethod;
+ this._searchInput.on_click["gallery-search-filter"] = eventMethod;
this._searchInput.attachEvent("onEnter", eventMethod);
}
diff --git a/sources/services/gallery/multiimageLesionWindow.js b/sources/services/gallery/multiimageLesionWindow.js
new file mode 100644
index 0000000..00e586e
--- /dev/null
+++ b/sources/services/gallery/multiimageLesionWindow.js
@@ -0,0 +1,667 @@
+import constants from "../../constants";
+import galleryImagesUrls from "../../models/galleryImagesUrls";
+import lesionWindowImagesUrls from "../../models/lesionWindowImagesUrls";
+import lesionsModel from "../../models/lesionsModel";
+import util from "../../utils/util";
+import metadataPart from "../../views/subviews/gallery/parts/metadata";
+import multiImageLesionWindow from "../../views/subviews/gallery/windows/multiImageLesionWindow";
+import ajax from "../ajaxActions";
+import authService from "../auth";
+import searchButtonModel from "./searchButtonModel";
+
+const MOVE = {
+ next: "next",
+ prev: "prev",
+};
+
+export default class MultiLesionWindowService {
+ constructor(
+ galleryService,
+ ) {
+ /** @type {import("./gallery").default} */
+ this._galleryService = galleryService;
+ this._window = $$(multiImageLesionWindow.getWindowID());
+ /** @type {webix.ui.list} */
+ this._topSlider = $$(multiImageLesionWindow.getTopSliderID());
+ /** @type {webix.ui.list} */
+ this._leftSlider = $$(multiImageLesionWindow.getLeftSliderID());
+ /** @type {webix.ui.list} */
+ this._rightSlider = $$(multiImageLesionWindow.getRightSliderID());
+ this._leftFooter = $$(multiImageLesionWindow.getLeftFooterID());
+ this._rightFooter = $$(multiImageLesionWindow.getRightFooterID());
+ this._leftGroup = $$(multiImageLesionWindow.getLeftDropDownFilterID());
+ this._rightGroup = $$(multiImageLesionWindow.getRightDropDownFilterID());
+ this._leftImageLabel = $$(multiImageLesionWindow.getLeftImageNameLabelID());
+ this._rightImageLabel = $$(multiImageLesionWindow.getRightImageNameLabelID());
+ this._rightContainer = $$(multiImageLesionWindow.getRightContainerID());
+ /** @type {webix.ui.template} */
+ this._leftImage = $$(multiImageLesionWindow.getLeftImageID());
+ /** @type {webix.ui.template} */
+ this._rightImage = $$(multiImageLesionWindow.getRightImageID());
+ this._fullScreenButton = $$(multiImageLesionWindow.getFullScreenButtonID());
+ this._windowedButton = $$(multiImageLesionWindow.getWindowedButtonID());
+ /** @type {webix.ui.search} */
+ this._searchInput = $$(multiImageLesionWindow.getSearchID());
+ this._prevPageButton = $$(multiImageLesionWindow.getPrevPageButtonID());
+ this._nextPageButton = $$(multiImageLesionWindow.getNextPageButtonID());
+ /** @type {webix.ui.layout} */
+ this._leftAnchorIcon = $$(multiImageLesionWindow.getLeftAnchorIconID());
+ this._rightAnchorIcon = $$(multiImageLesionWindow.getRightAnchorIconID());
+ this._topPanel = $$(multiImageLesionWindow.getTopPanelID());
+ this._expandButton = $$(multiImageLesionWindow.getExpandButtonID());
+ this._collapseButton = $$(multiImageLesionWindow.getCollapseButtonID());
+ this._fullscreen = false;
+ this.init();
+ }
+
+ async init() {
+ this._leftImage.attachEvent("onBeforeRender", this.updateImage);
+ this._leftImage.attachEvent("onAfterLoad", this.updateImage);
+
+ this._rightImage.attachEvent("onBeforeRender", this.updateImage);
+ this._rightImage.attachEvent("onAfterLoad", this.updateImage);
+
+ this._fullScreenButton.attachEvent("onItemClick", () => { this.changeWindowMode(); });
+ this._windowedButton.attachEvent("onItemClick", () => { this.changeWindowMode(); });
+
+ this._searchInput.on_click["lesionWindow__filter-search"] = this.searchImagesByQueryHandler.bind(this);
+ this._searchInput.on_click["lesionWindow__fa-times"] = () => {
+ if (this._searchInput.getValue() !== "") {
+ this._searchInput.setValue("");
+ this._searchInput.callEvent("onEnter");
+ }
+ };
+ this._searchInput.attachEvent("onEnter", this.searchImagesByQueryHandler.bind(this));
+ this._searchInput.attachEvent("onViewShow", this.searchImagesByQueryHandler.bind(this));
+ this._searchInput.attachEvent("onAfterRender", () => {
+ const inputNode = this._searchInput.$view.getElementsByClassName("webix_el_box")[0];
+ const tooltipText = "Clear search value";
+ searchButtonModel.createTimesSearchButton(
+ this._searchInput,
+ null,
+ inputNode,
+ tooltipText,
+ true
+ );
+ });
+
+ const navButtonClickHandler = util.debounce(async (navigate) => {
+ let url = navigate === MOVE.prev
+ ? lesionWindowImagesUrls.getPrevImagesUrl()
+ : lesionWindowImagesUrls.getNextImagesUrl();
+ if (url) {
+ this._topSlider.showProgress();
+ lesionWindowImagesUrls.setCurrImagesUrl(url);
+ const result = await ajax.getImagesByUrl(url);
+ lesionWindowImagesUrls.setPrevImagesUrl(result.previous);
+ lesionWindowImagesUrls.setNextImagesUrl(result.next);
+ this._topSlider.clearAll();
+ this._topSlider.parse(result.results);
+ this._topSlider.hideProgress();
+ }
+ }, 100);
+ this._prevPageButton.attachEvent("onItemClick", navButtonClickHandler.bind(this, MOVE.prev));
+ this._nextPageButton.attachEvent("onItemClick", navButtonClickHandler.bind(this, MOVE.next));
+
+ const clearWindow = () => {
+ this._leftSlider.clearAll();
+ this._rightSlider.clearAll();
+ this._topSlider.clearAll();
+ this._searchInput.setValue("");
+ if (this._window.config.fullscreen) {
+ this.changeWindowMode();
+ }
+ };
+ this._window.attachEvent("onHide", clearWindow);
+ this._window.attachEvent("onShow", this.searchImagesByQueryHandler.bind(this));
+ this._window.attachEvent("onShow", () => {
+ this._leftGroup.setValue(constants.MULTI_LESION_GROUP_BY.TIME);
+ this._rightGroup.setValue(constants.MULTI_LESION_GROUP_BY.TIME);
+ const leftImage = lesionsModel.getLeftImage();
+ const leftLesionId = lesionsModel.getItemLesionID(leftImage);
+ const LeftLesionImages = lesionsModel.getLesionImages(leftLesionId);
+ const leftType = this._leftGroup.getValue();
+ const leftImagesGroups = this.groupImages(LeftLesionImages, leftType);
+ if (leftImagesGroups.length === 1) {
+ this._leftGroup.setValue(constants.MULTI_LESION_GROUP_BY.TYPE);
+ this._leftGroup.refresh();
+ }
+
+ const rightImage = lesionsModel.getRightImage();
+ const rightLesionId = lesionsModel.getItemLesionID(rightImage);
+ const rightLesionImages = lesionsModel.getLesionImages(rightLesionId);
+ const rightType = this._rightGroup.getValue();
+ const rightImagesGroups = this.groupImages(rightLesionImages, rightType);
+ if (rightImagesGroups.length === 1) {
+ this._rightGroup.setValue(constants.MULTI_LESION_GROUP_BY.TYPE);
+ this._rightGroup.refresh();
+ }
+
+ if (this._topPanel.isVisible()) {
+ this._collapseButton.hide();
+ this._topPanel.hide();
+ this._expandButton.show();
+ }
+ });
+
+ const leftGroupByHandler = () => {
+ const leftImage = lesionsModel.getLeftImage();
+ this.fillLeftPanel(leftImage);
+ };
+
+ this._leftGroup.attachEvent("onChange", leftGroupByHandler.bind(this));
+
+ const rightGroupByHandler = () => {
+ const rightImage = lesionsModel.getRightImage();
+ this.fillRightPanel(rightImage);
+ };
+
+ this._rightGroup.attachEvent("onChange", rightGroupByHandler.bind(this));
+
+ this._rightSlider.attachEvent("onBeforeDrop", () => false);
+ this._topSlider.attachEvent("onBeforeDrop", () => false);
+ this._leftSlider.attachEvent("onBeforeDrop", () => false);
+ const leftImageView = this._leftImage.$view;
+ const rightImageView = this._rightImage.getNode();
+ webix.DragControl.addDrop(leftImageView, {$drop: (/* source, target, event */) => {
+ const dnd = webix.DragControl.getContext();
+ const item = dnd.from.getItem(dnd.start);
+ const image = item.firstImage ?? item;
+ const lesionID = lesionsModel.getItemLesionID(image);
+ if (lesionID) {
+ lesionsModel.setLeftImage(image);
+ this.fillLeftPanel(image);
+ }
+ else {
+ webix.message("There are no lesions attached to this image");
+ }
+ }});
+ webix.DragControl.addDrop(rightImageView, {$drop: (/* source, target, event */) => {
+ const dnd = webix.DragControl.getContext();
+ const item = dnd.from.getItem(dnd.start);
+ const image = item.firstImage ?? item;
+ const lesionID = lesionsModel.getItemLesionID(image);
+ if (lesionID) {
+ lesionsModel.setRightImage(image);
+ this.fillRightPanel(image);
+ }
+ else {
+ webix.message("There are no lesions attached to this image");
+ }
+ }});
+
+ const changeImage = (side, move) => {
+ if (side === constants.MULTI_LESION_SIDE.LEFT) {
+ const currentImage = lesionsModel.getLeftImage();
+ const newImage = move === MOVE.prev
+ ? lesionsModel.getPrevLeftImage(currentImage)
+ : lesionsModel.getNextLeftImage(currentImage);
+ if (newImage) {
+ this.fillLeftPanel(newImage);
+ }
+ }
+ if (side === constants.MULTI_LESION_SIDE.RIGHT) {
+ const currentImage = lesionsModel.getRightImage();
+ const newImage = move === MOVE.prev
+ ? lesionsModel.getPrevRightImage(currentImage)
+ : lesionsModel.getNextRightImage(currentImage);
+ if (newImage) {
+ this.fillRightPanel(newImage);
+ }
+ }
+ };
+
+ this._leftImage.define("onClick", {
+ prev: () => {
+ changeImage(constants.MULTI_LESION_SIDE.LEFT, MOVE.prev);
+ },
+ next: () => {
+ changeImage(constants.MULTI_LESION_SIDE.LEFT, MOVE.next);
+ }
+ });
+
+ this._rightImage.define("onClick", {
+ prev: () => {
+ changeImage(constants.MULTI_LESION_SIDE.RIGHT, MOVE.prev);
+ },
+ next: () => {
+ changeImage(constants.MULTI_LESION_SIDE.RIGHT, MOVE.next);
+ }
+ });
+
+ this._topSlider.on_click["resize-icon"] = (e, id) => {
+ const currentItem = this._topSlider.getItem(id);
+ this._galleryService._imageWindowTemplateWithoutControls?.hide();
+ this._galleryService._imageWindowTemplate?.show();
+ this._galleryService._setImageWindowValues(currentItem);
+ if (this._galleryService._imageWindow) {
+ this._galleryService._eventForHideMessages(this._galleryService._imageWindow);
+ this._galleryService._imageWindow.show();
+ }
+ };
+
+ this._topSlider.on_click["info-icon"] = async (e, id) => {
+ try {
+ const currentItem = this._topSlider.getItem(id);
+ const image = await ajax.getImageItem(currentItem.isic_id);
+ if (this._galleryService._metadataWindowMetadata) {
+ webix.ui([metadataPart.getConfig("metadata-window-metadata", image, currentItem)], this._galleryService._metadataWindowMetadata); // [] - because we rebuild only rows of this._imageWindowMetadata
+ }
+ else {
+ webix.ui([metadataPart.getConfig("metadata-window-metadata", image, currentItem)]); // [] - because we rebuild only rows of this._imageWindowMetadata
+ }
+ if (this._galleryService._metadataWindow) {
+ this._galleryService._eventForHideMessages(this._galleryService._metadataWindow);
+ this._galleryService._metadataWindow.show();
+ }
+ }
+ catch (error) {
+ if (!this._galleryService._view.$destructed) {
+ webix.message("ShowMetadata: Something went wrong");
+ }
+ }
+ };
+
+ this._topSlider.on_click["diagnosis-icon"] = (e, id) => {
+ const currentItem = this._topSlider.getItem(id);
+ const url = `${constants.URL_MULTIRATER}?id=${currentItem.isic_id}&sid=${currentItem.studyId}&uid=${authService.getToken()}`;
+ util.openInNewTab(url);
+ };
+
+ this._topSlider.on_click["batch-icon"] = async (e, id) => {
+ const currentItem = this._topSlider.getItem(id);
+ const currentItemId = currentItem.isic_id;
+ const url = await ajax.getDownloadUrl(
+ constants.DOWNLOAD_ZIP_SINGLE_IMAGE,
+ `isic_id:${currentItemId}`,
+ currentItemId
+ );
+ if (url) {
+ util.downloadByLink(url, `${currentItemId}.zip`);
+ }
+ };
+
+ this._topSlider.on_click["layer-group"] = (e, id) => {
+ if (this._window) {
+ const currentItem = this._topSlider.getItem(id);
+ this.setMultiLesionState(
+ currentItem,
+ );
+ }
+ };
+
+ this._collapseButton.attachEvent("onViewShow", () => {
+ this._searchInput.show();
+ });
+
+ this._expandButton.attachEvent("onViewShow", () => {
+ this._searchInput.hide();
+ });
+
+ webix.extend(this._topSlider, webix.ProgressBar);
+ }
+
+ async ready() {
+ const data = await ajax.getLesions();
+ if (data) {
+ lesionsModel.setLesions(data.results);
+ }
+ }
+
+ async updateImage(obj) {
+ if (typeof galleryImagesUrls.getNormalImageUrl(obj?.isic_id) === "undefined") {
+ if (obj?.isic_id) {
+ const item = await ajax.getImageItem(obj.isic_id);
+ galleryImagesUrls.setNormalImageUrl(obj.isic_id, item.files.full.url);
+ this.refresh();
+ }
+ }
+ return true;
+ }
+
+ setMultiLesionState(item) {
+ lesionsModel.setCurrentItem(item);
+ const lesionID = lesionsModel.getItemLesionID(item);
+ const lesionImages = webix.copy(lesionsModel.getLesionImages(lesionID));
+ const itemID = lesionsModel.getItemID(item);
+ const anchorImageID = lesionsModel.getAnchorImageID(lesionID);
+ this._rightContainer.show();
+ let rightGroupType = this._rightGroup.getValue();
+ let imageForRightPanel;
+ if (itemID === anchorImageID) {
+ imageForRightPanel = lesionsModel.getFirstNonAnchorImage(lesionID, anchorImageID);
+ }
+ else {
+ imageForRightPanel = item;
+ }
+ lesionsModel.setRightImage(imageForRightPanel);
+ if (rightGroupType === "") {
+ this._rightGroup.setValue(constants.MULTI_LESION_GROUP_BY.TIME);
+ rightGroupType = this._rightGroup.getValue();
+ }
+ this.fillRightPanel(imageForRightPanel);
+
+ let leftGroupType = this._leftGroup.getValue();
+ if (leftGroupType === "") {
+ this._leftGroup.setValue(constants.MULTI_LESION_GROUP_BY.TYPE);
+ leftGroupType = this._leftGroup.getValue();
+ }
+ const anchorImg = lesionImages.find(i => lesionsModel.getItemID(i) === anchorImageID);
+ this.fillLeftPanel(anchorImg);
+ }
+
+ parseImages(item, lesionID, isRightSide) {
+ const lesionImages = lesionsModel.getLesionImages(lesionID);
+ if (isRightSide === true) {
+ let rightGroupType = this._rightGroup.getValue();
+ const rightImagesGroups = this.groupImages(lesionImages, rightGroupType);
+ const sortedImages = this.sortImages(rightImagesGroups, rightGroupType, item);
+ lesionsModel.setCurrentRightImages(sortedImages);
+ this._rightSlider.clearAll();
+ this._rightSlider.parse(rightImagesGroups);
+ this._rightSlider.unselectAll();
+ const groupToSelect = this.findItemToSelect(rightImagesGroups, item);
+ this._rightSlider.select(groupToSelect.id);
+ }
+ else {
+ let leftGroupType = this._leftGroup.getValue();
+ const leftImagesGroups = this.groupImages(lesionImages, leftGroupType);
+ const sortedImages = this.sortImages(leftImagesGroups, leftGroupType, item);
+ lesionsModel.setCurrentLeftImages(sortedImages);
+ this._leftSlider.clearAll();
+ this._leftSlider.parse(leftImagesGroups);
+ this._leftSlider.unselectAll();
+ const groupToSelect = this.findItemToSelect(leftImagesGroups, item);
+ this._leftSlider.select(groupToSelect.id);
+ }
+ }
+
+ changeWindowMode() {
+ if (this._fullscreen) {
+ this._fullscreen = false;
+ this._window.define("width", 1240);
+ this._window.define("height", 750);
+ this._window.define("position", "center");
+ this._fullScreenButton.show();
+ this._windowedButton.hide();
+ }
+ else {
+ this._fullscreen = true;
+ this._window.define("width", window.innerWidth);
+ this._window.define("height", window.innerHeight);
+ this._window.define("position", "center");
+ this._fullScreenButton.hide();
+ this._windowedButton.show();
+ }
+ this.searchImagesByQueryHandler();
+ }
+
+ async searchImagesByQueryHandler() {
+ let searchValue = this._searchInput.getValue().trim();
+ this._searchInput.setValue(searchValue);
+ let filteredImages = [];
+ const filter = searchValue !== ""
+ ? this.buildCondition(searchValue)
+ : null;
+ const limit = Math.ceil(this._topSlider.$width / 174) - 1;
+ this._topSlider.define("type", {width: this._topSlider.$width / limit, height: 104});
+ const sourceParams = {
+ limit,
+ filter
+ };
+ this._topSlider.showProgress();
+ let foundImages = {};
+ try {
+ foundImages = await ajax.getImages(sourceParams);
+ }
+ catch (e) {
+ this._topSlider.hideProgress();
+ return;
+ }
+ lesionWindowImagesUrls.setPrevImagesUrl(foundImages?.previous);
+ lesionWindowImagesUrls.setNextImagesUrl(foundImages?.next);
+ try {
+ const allImagesArray = webix.copy(foundImages?.results ?? []);
+ const foundImagesCount = foundImages.count ?? 0;
+ allImagesArray.forEach((imageObj) => {
+ filteredImages.push(imageObj);
+ });
+ if (foundImagesCount > 0) {
+ this._topSlider.clearAll();
+ this._topSlider.parse(filteredImages);
+ }
+ else {
+ webix.alert(`Image with name "${searchValue}" was not found`);
+ }
+ this._topSlider.hideProgress();
+ }
+ catch (error) {
+ if (!this._view.$destructed) {
+ webix.alert(`Image with name "${searchValue}" was not found`);
+ webix.message("Search Images: Something went wrong");
+ this._topSlider.hideProgress();
+ }
+ }
+ }
+
+ async getImagesByUrl(url) {
+ const result = ajax.getImagesByUrl(url);
+ lesionWindowImagesUrls.setCurrImagesUrl(url);
+ lesionWindowImagesUrls.setNextImagesUrl(url);
+ lesionWindowImagesUrls.setPrevImagesUrl(url);
+ return result.results;
+ }
+
+ fillRightPanel(image) {
+ lesionsModel.setRightImage(image);
+ this._rightFooter.parse(image);
+ this.setAnchorIcon(image, constants.MULTI_LESION_SIDE.RIGHT);
+ const imageID = lesionsModel.getItemID(image);
+ this._rightImageLabel.define("label", imageID.toUpperCase());
+ this._rightImageLabel.refresh();
+ const lesionID = lesionsModel.getItemLesionID(image);
+ this.parseImages(image, lesionID, true);
+ this._rightImage.parse(image);
+ }
+
+ fillLeftPanel(image) {
+ lesionsModel.setLeftImage(image);
+ this._leftFooter.parse(image);
+ this.setAnchorIcon(image, constants.MULTI_LESION_SIDE.LEFT);
+ const imageID = lesionsModel.getItemID(image);
+ this._leftImageLabel.define("label", imageID.toUpperCase());
+ this._leftImageLabel.refresh();
+ const lesionID = lesionsModel.getItemLesionID(image);
+ this.parseImages(image, lesionID, false);
+ this._leftImage.parse(image);
+ }
+
+ buildCondition(filter) {
+ const searchValues = filter.split(" OR ");
+ const conditions = searchValues.map((str) => {
+ const values = str.split(" AND ");
+ return values.map((v) => {
+ if (v.includes(":")) {
+ return v;
+ }
+ return `isic_id:${v}`;
+ }).join(" AND ");
+ });
+ return conditions.join(" OR ");
+ }
+
+ groupImages(images, type) {
+ let imagesGroupsObj;
+ switch (type) {
+ case constants.MULTI_LESION_GROUP_BY.TIME:
+ imagesGroupsObj = lesionsModel.groupByTimePoint(images);
+ break;
+ case constants.MULTI_LESION_GROUP_BY.TYPE:
+ imagesGroupsObj = lesionsModel.groupByModality(images);
+ break;
+ case constants.MULTI_LESION_GROUP_BY.COMBINATION:
+ imagesGroupsObj = lesionsModel.groupByTimePointAndModality(images);
+ break;
+ default:
+ imagesGroupsObj = lesionsModel.groupByID(images);
+ }
+ const imagesGroupsObjectKeys = Object.keys(imagesGroupsObj);
+ const result = imagesGroupsObjectKeys.map((k) => {
+ const imgsGroup = {
+ firstImage: imagesGroupsObj[k][0],
+ groupBy: type,
+ groupValue: k,
+ images: imagesGroupsObj[k],
+ };
+ return imgsGroup;
+ });
+ return result;
+ }
+
+ sortImages(imagesGroups, groupType, item) {
+ let images;
+ if (groupType === constants.MULTI_LESION_GROUP_BY.NO_GROUP) {
+ images = imagesGroups.map(g => g.images[0]);
+ imagesGroups.sort((a, b) => {
+ const aValue = lesionsModel.getItemID(a.images[0]);
+ const bValue = lesionsModel.getItemID(b.images[0]);
+ const result = aValue.localeCompare(bValue);
+ return result;
+ });
+ }
+ else {
+ switch (groupType) {
+ case constants.MULTI_LESION_GROUP_BY.TIME:
+ imagesGroups.sort((a, b) => {
+ const aValue = a.groupValue;
+ const bValue = b.groupValue;
+ return Number(aValue) - Number(bValue);
+ });
+ break;
+ case constants.MULTI_LESION_GROUP_BY.TYPE:
+ imagesGroups.sort((a, b) => {
+ const aValue = a.groupValue;
+ if (aValue === constants.MULTI_LESION_TYPE_PRIORITY.FIRST) {
+ return -1;
+ }
+ const bValue = b.groupValue;
+ if (bValue === constants.MULTI_LESION_TYPE_PRIORITY.FIRST) {
+ return 1;
+ }
+ return aValue.localeCompare(bValue);
+ });
+ break;
+ case constants.MULTI_LESION_GROUP_BY.COMBINATION:
+ imagesGroups.sort((a, b) => {
+ const aValue = a.groupValue;
+ const bValue = b.groupValue;
+ return aValue.localeCompare(bValue);
+ });
+ break;
+ default:
+ imagesGroups.sort((a, b) => {
+ const aValue = a.value;
+ const bValue = b.value;
+ return aValue.localeCompare(bValue);
+ });
+ }
+ const currentImagesGroup = imagesGroups.find((g) => {
+ const found = g.images
+ .find(i => lesionsModel.getItemID(item) === lesionsModel.getItemID(i));
+ return found;
+ });
+ images = [...currentImagesGroup.images];
+ }
+ if (images.length === 1) {
+ return images;
+ }
+ const sortedImages = images.sort((a, b) => {
+ let result;
+ let aValue;
+ let bValue;
+ switch (groupType) {
+ case constants.MULTI_LESION_GROUP_BY.TIME:
+ aValue = lesionsModel.getItemModality(a);
+ if (aValue === constants.MULTI_LESION_TYPE_PRIORITY.FIRST) {
+ result = -1;
+ }
+ else {
+ bValue = lesionsModel.getItemModality(b);
+ if (bValue === constants.MULTI_LESION_TYPE_PRIORITY.FIRST) {
+ result = 1;
+ }
+ else {
+ result = aValue.localeCompare(bValue);
+ }
+ if (result === 0) {
+ aValue = lesionsModel.getItemID(a);
+ bValue = lesionsModel.getItemID(b);
+ result = aValue.localeCompare(bValue);
+ }
+ }
+ break;
+ case constants.MULTI_LESION_GROUP_BY.TYPE:
+ aValue = lesionsModel.getItemTimePoint(a);
+ bValue = lesionsModel.getItemTimePoint(b);
+ result = Number(aValue) - Number(bValue);
+ if (result === 0) {
+ aValue = lesionsModel.getItemID(a);
+ bValue = lesionsModel.getItemID(b);
+ result = aValue.localeCompare(bValue);
+ }
+ break;
+ case constants.MULTI_LESION_GROUP_BY.COMBINATION:
+ aValue = lesionsModel.getItemID(a);
+ bValue = lesionsModel.getItemID(b);
+ result = aValue.localeCompare(bValue);
+ break;
+ default:
+ aValue = lesionsModel.getItemID(a);
+ bValue = lesionsModel.getItemID(b);
+ result = aValue.localeCompare(bValue);
+ }
+ return result;
+ });
+ return sortedImages;
+ }
+
+ setAnchorIcon(image, side) {
+ if (lesionsModel.checkIsImageAnchor(image)) {
+ switch (side) {
+ case constants.MULTI_LESION_SIDE.LEFT:
+ this._leftAnchorIcon.show();
+ break;
+ case constants.MULTI_LESION_SIDE.RIGHT:
+ this._rightAnchorIcon.show();
+ break;
+ default:
+ break;
+ }
+ }
+ else {
+ switch (side) {
+ case constants.MULTI_LESION_SIDE.LEFT:
+ this._leftAnchorIcon.hide();
+ break;
+ case constants.MULTI_LESION_SIDE.RIGHT:
+ this._rightAnchorIcon.hide();
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ findItemToSelect(groups, image) {
+ const groupToSelect = groups.find((obj) => {
+ if (obj.images) {
+ if (obj.images.find(i => lesionsModel.getItemID(i) === lesionsModel.getItemID(image))) {
+ return true;
+ }
+ return false;
+ }
+ return lesionsModel.getItemID(obj) === lesionsModel.getItemID(image);
+ });
+ return groupToSelect;
+ }
+}
diff --git a/sources/services/gallery/searchButtonModel.js b/sources/services/gallery/searchButtonModel.js
index 09d6fe7..75d699b 100644
--- a/sources/services/gallery/searchButtonModel.js
+++ b/sources/services/gallery/searchButtonModel.js
@@ -24,7 +24,7 @@ function createHintForSearchTimesButton(elementNodeForTooltip, tooltipClassName,
const linkProps = this.getBoundingClientRect();
const tooltipProps = tooltipWrap.getBoundingClientRect();
const topPos = linkProps.top - (tooltipProps.height + padding);
- tooltipWrap.setAttribute("style", `top:${topPos}px;left:${linkProps.left}px;`);
+ tooltipWrap.setAttribute("style", `top:${topPos}px;left:${linkProps.left}px;z-index: 1010`); // z-index: 1010 to show tooltip in modal window background
}
elementNodeForTooltip.addEventListener("mouseover", mouseOverHandler);
elementNodeForTooltip.addEventListener("mouseout", () => {
@@ -39,11 +39,12 @@ function createTimesSearchButton(
tooltipText,
nameFilter
) {
+ const className = `clear-input-${webix.uid()}`;
inputNode.lastChild.style.paddingRight = "26px";
const timesSpan = document.createElement("span");
inputNode.appendChild(timesSpan);
const timesButtonNode = inputNode.lastChild;
- timesButtonNode.setAttribute("class", "search-times-button webix_input_icon fas fa-times");
+ timesButtonNode.setAttribute("class", `search-times-button webix_input_icon fas fa-times ${className}`);
timesButtonNode.setAttribute("style", "height:26px; padding-top:6px;");
const tootipTextForTimesButton = `${tooltipText}`;
const tooltipClassNameForTimesButton = "tooltip";
@@ -52,10 +53,12 @@ function createTimesSearchButton(
tooltipClassNameForTimesButton,
tootipTextForTimesButton
);
- searchInput.on_click["fa-times"] = () => {
+ searchInput.on_click[className] = () => {
if (searchInput.getValue() !== "") {
searchInput.setValue("");
- appliedFilterModel.setFilterValue("");
+ if (appliedFilterModel) {
+ appliedFilterModel?.setFilterValue("");
+ }
if (nameFilter) {
searchInput.callEvent("onEnter");
}
diff --git a/sources/styles/common.less b/sources/styles/common.less
index 525e157..56134d3 100644
--- a/sources/styles/common.less
+++ b/sources/styles/common.less
@@ -250,6 +250,58 @@ a, .link {
}
}
+.collapser-vertical {
+ .box-shadow2(0 1px 4px 0 rgba(0,0,0,0.12), 0 2px 4px 0 rgba(0,0,0,0.04));
+
+ .collapser-btn {
+ border: none;
+ cursor: pointer;
+ .webix_template {
+ position: relative;
+ }
+ .webix_icon {
+ font-weight: 600;
+ text-align: center;
+ position: absolute;
+ left: 50%;
+ }
+ }
+}
+
+/* gallery-images-badge */
+.gallery-images-badge {
+ background-color: #3C87CB;
+ font-size: 8px;
+ line-height: 10px;
+ text-align: center;
+ color: #FFFFFF;
+ border: 1px;
+ border-radius: 10px;
+ height: 13px;
+ width: 13px;
+ padding: 2px;
+ text-align: center;
+ position: absolute;
+ right: -5px;
+ top: -5px;
+ -moz-box-sizing: border-box;
+ -webkit-box-sizing: border-box;
+ box-sizing: border-box;
+}
+
+.gallery-images-badge_1 {
+ top: -5px;
+ right: -5px;
+}
+
+.gallery-images-badge_2 {
+ top: -5px;
+ right: 13px;
+}
+
+.disabled-badge {
+ background-color: #cccccc;
+}
/* tooltip */
.tooltip-container {
diff --git a/sources/styles/pages.less b/sources/styles/pages.less
index 8e40465..2530974 100644
--- a/sources/styles/pages.less
+++ b/sources/styles/pages.less
@@ -1215,6 +1215,34 @@
border-radius: 5px;
}
+.gallery-image.framed-image, .gallery-image.framed-image2, .gallery-image.framed-image3 {
+ position: absolute
+}
+
+.gallery-image.framed-image {
+ top: -13px;
+ left: -10px;
+ background: transparent;
+ z-index: 2;
+ border: 1px solid black;
+ box-shadow: 2px 2px rgb(100, 100, 100);
+}
+
+.gallery-image.framed-image2 {
+ top: -8px;
+ left: -5px;
+ z-index: 1;
+ border: 1px solid black;
+ box-shadow: 2px 2px rgb(100, 100, 100);
+}
+
+.gallery-image.framed-image3 {
+ top: 0px;
+ left: 0px;
+ z-index: 0;
+ filter: blur(2px)
+}
+
/* gallery-images-dataview-mobile */
.gallery-images-dataview-mobile {
.webix_dataview_item {
@@ -1335,13 +1363,21 @@
width: 100%;
}
-.gallery-images-button-elem {
+.gallery-images-button-elem, .gallery-images-button-elem-disabled {
display: inline-block;
vertical-align: top;
width: 22px;
height: 22px;
margin: 0 4px;
}
+.gallery-images-button-elem-disabled {
+ background-color: #cccccc;
+ pointer-events: none;
+}
+.gallery-images-button-elem-disabled:active {
+ background-color: #cccccc;
+ pointer-events: none;
+}
.gallery-images-button {
display: block;
line-height: 0;
diff --git a/sources/styles/popups.less b/sources/styles/popups.less
index 00cbab1..8f2129a 100644
--- a/sources/styles/popups.less
+++ b/sources/styles/popups.less
@@ -12,6 +12,17 @@
.box-sizing(border-box);
padding-left: 14px;
}
+
+ .window-header-toolbar2 {
+ .window-header-toolbar2__title {
+ .webix_template {
+ display: flex;
+ .window-header-toolbar-text_title {
+ align-self: center;
+ }
+ }
+ }
+ }
}
.window-close-button {
@@ -188,6 +199,17 @@
display: flex;
align-items: center;
justify-content: center;
+ user-select: none;
+ height: 100%;
+ .zoomable-image {
+ max-height:100%;
+ max-width:100%;
+ object-fit: contain;
+ }
+}
+
+.prev, .next {
+ user-select: none;
}
/*========== Metadata popup =============*/
@@ -222,3 +244,230 @@
.webix_modal_box {
font-family: @main-font;
}
+
+/*========= Multi image lesion window =========*/
+.multi-image-lesion-search-block {
+ display: flex;
+ align-content: center;
+}
+.multi-image-lesion-window-body {
+ .lesion-controls {
+ background-color: #E1E7F0;
+ }
+ .left-image-panel-container, .right-image-panel-container {
+ position: relative;
+ .absolute-centered-image-template {
+ position: absolute;
+ top: 0;
+ left: 0;
+ .next, .prev {
+ border-radius: 50%;
+ background: rgba(255, 255, 255, 0.3);
+ padding: 0;
+ width: 40px;
+ height: 40px;
+ padding: 0px;
+ text-align: center;
+ line-height: 40px;
+ }
+ }
+ .vertical-slider-left, .vertical-slider-right {
+ position: absolute;
+ border: none;
+ z-index: 10;
+ top: 0px;
+ }
+ // scroll start
+ --sb-track-color: #ffffff;
+ --sb-thumb-color: #bbc0cb;
+ --sb-size: 8px;
+ .vertical-slider-left::-webkit-scrollbar, .vertical-slider-right::-webkit-scrollbar {
+ width: var(--sb-size);
+ }
+ .vertical-slider-left::-webkit-scrollbar-track, .vertical-slider-right::-webkit-scrollbar-track {
+ background: var(--sb-track-color);
+ border-radius: 3px;
+ }
+ .vertical-slider-left::-webkit-scrollbar-thumb, .vertical-slider-right::-webkit-scrollbar-thumb {
+ background: var(--sb-thumb-color);
+ border-radius: 3px;
+ border: 1px solid #ffffff;
+ }
+ @supports not selector(::-webkit-scrollbar) {
+ .vertical-slider-left, .vertical-slider-right {
+ scrollbar-color: var(--sb-thumb-color)
+ var(--sb-track-color);
+ opacity: 0.1;
+ }
+ }
+ // scroll end
+ .vertical-slider-left {
+ right: 10;
+ }
+
+ .vertical-slider-right {
+ left: 10
+ }
+ }
+
+ .left-image-panel-container {
+ .absolute-centered-image-template {
+ .next {
+ right: 90px;
+ }
+ .prev {
+ left: 10px;
+ }
+ }
+ }
+
+ .right-image-panel-container {
+ .absolute-centered-image-template {
+ .prev {
+ left: 90px;
+ }
+ .next {
+ right: 10px;
+ }
+ }
+ }
+
+ .container {
+ position: relative;
+ .vertical-slider-left, .vertical-slider-right {
+ position: absolute;
+ border: none;
+ z-index: 10;
+ top: 0px;
+ width: 80px !important;
+ background: transparent;
+ .webix_list_item.webix_selected {
+ border-color: #46C03C;
+ }
+ .webix_list_item{
+ background-color: white;
+ margin-top: 5px;
+ margin-bottom: 5px;
+ padding-left: 0px;
+ padding-right: 0px;
+ padding-top: 0px;
+ border: solid 2px white;
+ .ribbon-image-elem {
+ position: absolute;
+ width: 15px;
+ height: 15px;
+ bottom: 0px;
+ right: 5px;
+ border-radius: 7.5px;
+ background: rgba(0, 0, 0, 0.3);
+ .gallery-images-button {
+ position: absolute;
+ top: 7.5px;
+ left: 2px;
+ width: 10px;
+ height: 10px;
+ background: transparent;
+ border: none;
+ font-size: 10px;
+ padding: 0px;
+ color: white;
+ }
+ }
+ }
+ }
+ // scroll start
+ --sb-track-color: transparent;
+ --sb-thumb-color: transparent;
+ --sb-size: 8px;
+ .vertical-slider-left::-webkit-scrollbar, .vertical-slider-right::-webkit-scrollbar {
+ width: var(--sb-size);
+ }
+ .vertical-slider-left::-webkit-scrollbar-track, .vertical-slider-right::-webkit-scrollbar-track {
+ background: var(--sb-track-color);
+ border-radius: 0px;
+ }
+ .vertical-slider-left::-webkit-scrollbar-thumb, .vertical-slider-right::-webkit-scrollbar-thumb {
+ background: var(--sb-thumb-color);
+ border-radius: 3px;
+ border: 1px solid transparent;
+ }
+ @supports not selector(::-webkit-scrollbar) {
+ .vertical-slider-left, .vertical-slider-right {
+ scrollbar-color: var(--sb-thumb-color)
+ var(--sb-track-color);
+ }
+ }
+ // scroll end
+ .vertical-slider-left {
+ right: 10px;
+ }
+
+ .vertical-slider-right {
+ left: 10px;
+ }
+
+ .multi-image-lesion-window__image-label {
+ font: Roboto;
+ font-weight: 500;
+ font-size: 14px;
+ line-height: 16px;
+ }
+
+ .footer-template {
+ border: 0px;
+ .webix_template {
+ display: flex;
+ align-items: center;
+ .footer-container-wide {
+ width: 100%;
+ display: grid;
+ grid-template-columns: auto auto auto auto;
+ .footer-item {
+ min-width: 240px;
+ .footer-item__name {
+ color: #6F747F;
+ }
+ .footer-item__value {
+ color: black;
+ }
+ }
+ }
+ .footer-container-narrow{
+ min-width: 435px;
+ width: calc(100%);
+ display: grid;
+ grid-template-columns: auto auto;
+ grid-template-rows: auto auto;
+ overflow: hidden;
+ .footer-item {
+ overflow: hidden;
+ min-width: 200px;
+ padding-bottom: 5px;
+ .footer-item__name {
+ color: #6F747F;
+ min-width: 210px;
+ }
+ .footer-item__value {
+ color: black;
+ }
+ }
+ }
+ }
+ }
+
+ }
+ .multilesion-filter-dropdown {
+ .webix_inp_static {
+ border: none;
+ padding-left: 0px;
+ }
+ .webix_input_icon.wxi-menu-down, .webix_input_icon.wxi-menu-down:focus {
+ outline: none;
+ color: @main-color-light;
+ background-color: transparent;
+ }
+ }
+ .multilesion-top-list {
+ border: none;
+ }
+}
diff --git a/sources/views/components/collapser.js b/sources/views/components/collapser.js
index 37cce08..d30b0ea 100644
--- a/sources/views/components/collapser.js
+++ b/sources/views/components/collapser.js
@@ -19,21 +19,103 @@ function changeDataviewItemDimensions(collapsedView) {
function getConfig(collapsedViewId, config) {
const BTN_CLOSED_STATE_ID = `collapser-btn-closed-${webix.uid()}`;
const BTN_OPENED_STATE_ID = `collapser-btn-opened-${webix.uid()}`;
+ let openedSpan;
+ let closedSpan;
+ switch (config.type) {
+ case "left":
+ openedSpan = "";
+ closedSpan = "";
+ break;
+ case "right":
+ openedSpan = "";
+ closedSpan = "";
+ break;
+ case "top":
+ openedSpan = "";
+ closedSpan = "";
+ break;
+ case "bottom":
+ openedSpan = "";
+ closedSpan = "";
+ break;
+ default:
+ openedSpan = "";
+ closedSpan = "";
+ }
+ if (config.type === "top" || config.type === "bottom") {
+ return {
+ css: "collapser-vertical",
+ height: 23,
+ cols: [
+ {
+ view: "template",
+ template: openedSpan,
+ css: "collapser-btn",
+ id: BTN_OPENED_STATE_ID,
+ state: "wasOpened",
+ hidden: config && config.closed,
+ onClick: {
+ // eslint-disable-next-line func-names
+ "collapser-btn": function (thisButton) {
+ const thisCollapsedButton = this?.config ? this : thisButton;
+ const collapsedView = $$(collapsedViewId);
+ collapsedView.hide();
+ thisCollapsedButton.hide();
+ $$(BTN_CLOSED_STATE_ID).show();
+ webix.ui.resize();
+ if (collapsedViewId === constants.ID_GALLERY_RIGHT_PANEL) {
+ util.setHiddenGalleryCartList(true);
+ }
+ else if (collapsedViewId === constants.ID_GALLERY_LEFT_PANEL) {
+ util.setHiddenGalleryLeftPanel(true);
+ }
+ changeDataviewItemDimensions(collapsedView);
+ }
+ }
+ },
+ {
+ view: "template",
+ template: closedSpan,
+ css: "collapser-btn",
+ id: BTN_CLOSED_STATE_ID,
+ state: "wasClosed",
+ hidden: !(config && config.closed),
+ onClick: {
+ // eslint-disable-next-line func-names
+ "collapser-btn": function (thisButton) {
+ const thisCollapsedButton = this?.config ? this : thisButton;
+ const collapsedView = $$(collapsedViewId);
+ collapsedView.show();
+ thisCollapsedButton.hide();
+ $$(BTN_OPENED_STATE_ID).show();
+ webix.ui.resize();
+ if (collapsedViewId === constants.ID_GALLERY_RIGHT_PANEL) {
+ util.setHiddenGalleryCartList(false);
+ }
+ else if (collapsedViewId === constants.ID_GALLERY_LEFT_PANEL) {
+ util.setHiddenGalleryLeftPanel(false);
+ }
+ changeDataviewItemDimensions(collapsedView);
+ }
+ }
+ }
+ ]
+ };
+ }
return {
css: "collapser",
width: 23,
rows: [
{
view: "template",
- template: config && config.type === "left" ?
- "" :
- "",
+ template: openedSpan,
css: "collapser-btn",
id: BTN_OPENED_STATE_ID,
state: "wasOpened",
hidden: config && config.closed,
onClick: {
+ // eslint-disable-next-line func-names
"collapser-btn": function (thisButton) {
const thisCollapsedButton = this?.config ? this : thisButton;
const collapsedView = $$(collapsedViewId);
@@ -53,14 +135,13 @@ function getConfig(collapsedViewId, config) {
},
{
view: "template",
- template: config && config.type === "left" ?
- "" :
- "",
+ template: closedSpan,
css: "collapser-btn",
id: BTN_CLOSED_STATE_ID,
state: "wasClosed",
hidden: !(config && config.closed),
onClick: {
+ // eslint-disable-next-line func-names
"collapser-btn": function (thisButton) {
const thisCollapsedButton = this?.config ? this : thisButton;
const collapsedView = $$(collapsedViewId);
diff --git a/sources/views/components/svgIcon.js b/sources/views/components/svgIcon.js
new file mode 100644
index 0000000..7b6396a
--- /dev/null
+++ b/sources/views/components/svgIcon.js
@@ -0,0 +1,27 @@
+webix.protoUI({
+ name: "svgIcon",
+ $cssName: "icon",
+ defaults: {
+ template(obj, view) {
+ const min = Math.min(obj.awidth, obj.aheight);
+ const top = Math.round((view.$height - obj.aheight) / 2);
+ const inner = ``;
+
+ const lineHeight = obj.aheight !== min ? obj.aheight : 0;
+ return `${inner}
+ ${obj.tooltip}
+ ${obj.badge || obj.badge === 0 ? `${obj.badge}` : ""}
+
`;
+ }
+ }
+}, webix.ui.icon);
+
+function wrapIconWithSpan(elementClass, icon, active) {
+ return `
+
+ `;
+}
diff --git a/sources/views/subviews/gallery/gallery.js b/sources/views/subviews/gallery/gallery.js
index 6d770c8..41bac56 100644
--- a/sources/views/subviews/gallery/gallery.js
+++ b/sources/views/subviews/gallery/gallery.js
@@ -4,9 +4,11 @@ import constants from "../../../constants";
import "../../components/activeList";
import galleryImagesUrls from "../../../models/galleryImagesUrls";
import selectedImages from "../../../models/selectedGalleryImages";
+import state from "../../../models/state";
import ajax from "../../../services/ajaxActions";
import authService from "../../../services/auth";
import GalleryService from "../../../services/gallery/gallery";
+import MultiLesionWindowService from "../../../services/gallery/multiimageLesionWindow";
import searchButtonModel from "../../../services/gallery/searchButtonModel";
import util from "../../../utils/util";
import collapser from "../../components/collapser";
@@ -17,6 +19,7 @@ import dataview from "./parts/galleryDataview";
import pager from "./parts/galleryPager";
import imageWindow from "./windows/imageWindow";
import metadataWindow from "./windows/metadataWindow";
+import multiImageLesionWindow from "./windows/multiImageLesionWindow";
const ID_PAGER = "gallery-pager-id";
const ID_DATAVIEW = "gallery-dataview-id";
@@ -143,11 +146,11 @@ export default class GalleryView extends JetView {
template(obj) {
const rangeHtml = `Shown images: ${obj.rangeStart || ""}-${obj.rangeFinish || ""}.`;
const totalAmountHtml = `Total amount of images: ${obj.totalCount || ""}.`;
- const filteredAmountHtml = `Filtered images: ${obj.currentCount || 0}`;
+ const filteredAmountHtml = `Filtered images: ${state.filteredImages.filteredImagesCount || 0}`;
let result = "";
if (obj.filtered) {
result = ` ${filteredAmountHtml} ${totalAmountHtml}`;
- if (obj.rangeFinish - obj.rangeStart < obj.currentCount) {
+ if (obj.rangeFinish - obj.rangeStart < state.filteredImages.filteredImagesCount) {
result = `${rangeHtml} ${result}`;
}
}
@@ -326,6 +329,10 @@ export default class GalleryView extends JetView {
null,
this.removeParam.bind(this)
));
+ this.multiImageLesionWindow = this.ui(multiImageLesionWindow.getConfig(
+ "MULTI-IMAGE LESION CASE STUDY",
+ () => {}
+ ));
this.metadataWindow = this.ui(metadataWindow.getConfig(ID_METADATA_WINDOW));
const contextMenuConfig = contextMenu.getConfig(ID_GALLERY_CONTEXT_MENU);
this.galleryContextMenu = this.ui(contextMenuConfig);
@@ -354,6 +361,7 @@ export default class GalleryView extends JetView {
$$(imageWindow.getMetadataLayoutId()),
this.metadataWindow,
$$(metadataWindow.getMetadataLayoutId()),
+ this.multiImageLesionWindow,
filtersForm,
this.getAppliedFiltersList(),
this.imagesSelectionTemplate,
@@ -376,6 +384,12 @@ export default class GalleryView extends JetView {
null, // portraitClearAllFiltersTemplate
null // landscapeClearAllFiltersTemplate
);
+
+ // multi lesion
+ this._multiImageLesionService = new MultiLesionWindowService(
+ this._galleryService
+ );
+ this._multiImageLesionService.ready();
}
async ready() {
@@ -666,4 +680,8 @@ export default class GalleryView extends JetView {
this.setParam("image", "", true);
}
}
+
+ setMultiLesionMode(item) {
+ this._multiImageLesionService.setMultiLesionState(item);
+ }
}
diff --git a/sources/views/subviews/gallery/parts/filterPanel.js b/sources/views/subviews/gallery/parts/filterPanel.js
index 3d8aa01..4384a2e 100644
--- a/sources/views/subviews/gallery/parts/filterPanel.js
+++ b/sources/views/subviews/gallery/parts/filterPanel.js
@@ -36,7 +36,7 @@ function getConfig(config) {
const searchField = {
view: "search",
- icon: "fas fa-search",
+ icon: "fas fa-search gallery-search-filter",
id: ID_SEARCH_FIELD,
name: NAME_SEARCH_FIELD,
value: `${appliedFiltersModel.getFilterValue()}`,
diff --git a/sources/views/subviews/gallery/parts/galleryDataview.js b/sources/views/subviews/gallery/parts/galleryDataview.js
index 05af097..9c719c7 100644
--- a/sources/views/subviews/gallery/parts/galleryDataview.js
+++ b/sources/views/subviews/gallery/parts/galleryDataview.js
@@ -1,6 +1,7 @@
import "../../../components/activeDataview";
import constants from "../../../../constants";
import galleryImageUrl from "../../../../models/galleryImagesUrls";
+import lesionsModel from "../../../../models/lesionsModel";
import selectedImages from "../../../../models/selectedGalleryImages";
import state from "../../../../models/state";
import util from "../../../../utils/util";
@@ -89,12 +90,21 @@ const dataview = {
datathrottle: 500,
onContext: {},
template(obj, common) {
+ const lesionID = lesionsModel.getItemLesionID(obj);
+ const lesion = lesionsModel.getLesionByID(lesionID);
+ const lesionModalitiesCount = lesionID
+ ? lesionsModel.getLesionModalitiesCount(lesionID)
+ : null;
+ const lesionTimePointsCount = lesionID
+ ? lesionsModel.getLesionTimePointsCount(lesionID)
+ : null;
const imageIconDimensions = util.getImageIconDimensions();
let flagForStudies = selectedImages.getStudyFlag();
// TODO check this when if study works
if (flagForStudies) {
// eslint-disable-next-line no-use-before-define
let dataviewConfig = $$(getIdFromConfig());
+ // TODO: find out why we use find
// eslint-disable-next-line array-callback-return
dataviewConfig.find((config) => {
if (selectedImages.isSelectedInStudies(config.isic_id)) {
@@ -112,6 +122,24 @@ const dataview = {
Multirater
` : "";
+ const lesionIconElementClass = lesion
+ ? "gallery-images-button-elem"
+ : "gallery-images-button-elem-disabled";
+ const disabledBadge = lesion
+ ? ""
+ : " disabled-badge";
+ const lesionIcon = `
+
+
+
+ Lesion
+ ${lesionModalitiesCount ?? 0}
+ Lesion modalities count
+ ${lesionTimePointsCount ?? 0}
+ Lesion time points count
+
`;
const starHtml = obj.hasAnnotations ? "" : "";
if (typeof galleryImageUrl.getPreviewImageUrl(obj.isic_id) === "undefined") {
galleryImageUrl.setPreviewImageUrl(
@@ -151,6 +179,7 @@ const dataview = {
Download ZIP
+ ${lesionIcon}
${diagnosisIcon}
diff --git a/sources/views/subviews/gallery/parts/mobileFilterPanel.js b/sources/views/subviews/gallery/parts/mobileFilterPanel.js
index 7391d44..a7c5bb0 100644
--- a/sources/views/subviews/gallery/parts/mobileFilterPanel.js
+++ b/sources/views/subviews/gallery/parts/mobileFilterPanel.js
@@ -65,7 +65,7 @@ function getConfig(config) {
const searchField = {
view: "search",
- icon: "fas fa-search",
+ icon: "fas fa-search gallery-search-filter",
id: ID_SEARCH_FIELD,
name: NAME_SEARCH_FIELD,
value: `${appliedFiltersModel.getFilterValue()}`,
diff --git a/sources/views/subviews/gallery/windows/multiImageLesionWindow.js b/sources/views/subviews/gallery/windows/multiImageLesionWindow.js
new file mode 100644
index 0000000..5693dc5
--- /dev/null
+++ b/sources/views/subviews/gallery/windows/multiImageLesionWindow.js
@@ -0,0 +1,742 @@
+import constants from "../../../../constants";
+import appliedFiltersModel from "../../../../models/appliedFilters";
+import galleryImageUrl from "../../../../models/galleryImagesUrls";
+import lesionsModel from "../../../../models/lesionsModel";
+import util from "../../../../utils/util";
+import collapser from "../../../components/collapser";
+import "../../../components/svgIcon";
+
+const ID_MULTI_IMAGE_LESION_WINDOW = `multi-image-lesion-window-id-${webix.uid()}`;
+const ID_LEFT_IMAGE_NAME_LABEL = `image-name-id-${webix.uid()}`;
+const ID_RIGHT_IMAGE_NAME_LABEL = `image-name-id-${webix.uid()}`;
+const ID_TOP_PANEL = `top-panel-id-${webix.uid()}`;
+const ID_TOP_SLIDER = `top-slider-id-${webix.uid()}`;
+const ID_PREV_PAGE_BUTTON = `prev-page-button-id-${webix.uid()}`;
+const ID_NEXT_PAGE_BUTTON = `next-page-button-id-${webix.uid()}`;
+const ID_RIGHT_CONTAINER = `container-id-${webix.uid()}`;
+const ID_LEFT_DROP_DOWN_FILTER = `left-drop-down-filter-${webix.uid()}`;
+const ID_RIGHT_DROP_DOWN_FILTER = `right-drop-down-filter-${webix.uid()}`;
+const ID_LEFT_FOOTER = `footer-id-${webix.uid()}`;
+const ID_RIGHT_FOOTER = `footer-id-${webix.uid()}`;
+const ID_LEFT_SLIDER = `slider-id-${webix.uid()}`;
+const ID_RIGHT_SLIDER = `slider-id-${webix.uid()}`;
+const ID_LEFT_IMAGE = `image-id-${webix.uid()}`;
+const ID_RIGHT_IMAGE = `image-id-${webix.uid()}`;
+const ID_BUTTON_FULL_SCREEN = `button-full-screen-id-${webix.uid()}`;
+const ID_BUTTON_WINDOWED = `button-windowed-id-${webix.uid()}`;
+const ID_SEARCH = `search-id-${webix.uid()}`;
+const ID_LEFT_ANCHOR_ICON = `left-anchor-icon-id-${webix.uid()}`;
+const ID_RIGHT_ANCHOR_ICON = `right-anchor-icon-id-${webix.uid()}`;
+
+let expandButtonID;
+let collapseButtonID;
+
+function getConfig(windowTitle, closeCallback) {
+ const topSlider = getTopSlider(
+ ID_TOP_PANEL,
+ ID_TOP_SLIDER,
+ ID_PREV_PAGE_BUTTON,
+ ID_NEXT_PAGE_BUTTON
+ );
+ const topSliderCollapser = collapser.getConfig(ID_TOP_PANEL, {type: "top", closed: true});
+ // TODO: find alternatives
+ collapseButtonID = topSliderCollapser.cols[0].id;
+ expandButtonID = topSliderCollapser.cols[1].id;
+ const leftSlider = getVerticalSlider(ID_LEFT_SLIDER, constants.MULTI_LESION_SIDE.LEFT);
+ const rightSlider = getVerticalSlider(ID_RIGHT_SLIDER, constants.MULTI_LESION_SIDE.RIGHT);
+
+ /** @type {webix.ui.labelConfig} */
+ const leftImageLabel = getImageLabel(ID_LEFT_IMAGE_NAME_LABEL);
+ const rightImageLabel = getImageLabel(ID_RIGHT_IMAGE_NAME_LABEL);
+
+ const leftAnchorIcon = {
+ view: "icon",
+ id: ID_LEFT_ANCHOR_ICON,
+ width: 20,
+ height: 20,
+ icon: "fas fa-anchor"
+ };
+
+ const rightAnchorIcon = {
+ view: "icon",
+ id: ID_RIGHT_ANCHOR_ICON,
+ width: 20,
+ height: 20,
+ icon: "fas fa-anchor"
+ };
+
+ /** @type {webix.ui.richselectConfig} */
+ const leftGroupDropdown = {
+ view: "richselect",
+ id: ID_LEFT_DROP_DOWN_FILTER,
+ css: "multilesion-filter-dropdown",
+ label: "Group by:",
+ labelAlign: "left",
+ width: 270,
+ height: 24,
+ labelWidth: 75,
+ value: constants.MULTI_LESION_GROUP_BY.TIME,
+ // TODO: check options
+ options: [
+ constants.MULTI_LESION_GROUP_BY.TIME,
+ constants.MULTI_LESION_GROUP_BY.TYPE,
+ constants.MULTI_LESION_GROUP_BY.COMBINATION,
+ constants.MULTI_LESION_GROUP_BY.NO_GROUP,
+ ]
+ };
+
+ const rightGroupDropdown = {
+ view: "richselect",
+ id: ID_RIGHT_DROP_DOWN_FILTER,
+ css: "multilesion-filter-dropdown",
+ label: "Group by:",
+ labelAlign: "left",
+ width: 270,
+ height: 30,
+ labelWidth: 75,
+ value: constants.MULTI_LESION_GROUP_BY.TIME,
+ // TODO: check options
+ options: [
+ constants.MULTI_LESION_GROUP_BY.TIME,
+ constants.MULTI_LESION_GROUP_BY.TYPE,
+ constants.MULTI_LESION_GROUP_BY.COMBINATION,
+ constants.MULTI_LESION_GROUP_BY.NO_GROUP,
+ ]
+ };
+
+ const leftTemplateViewer = getTemplateViewer(
+ ID_LEFT_IMAGE,
+ true,
+ constants.MULTI_LESION_SIDE.LEFT
+ );
+
+ const rightTemplateViewer = getTemplateViewer(
+ ID_RIGHT_IMAGE,
+ true,
+ constants.MULTI_LESION_SIDE.RIGHT
+ );
+
+ /** @type {webix.ui.toolbarConfig} */
+ const leftToolbar = {
+ height: 60,
+ cols: [
+ {width: 20},
+ leftImageLabel,
+ {width: 5},
+ leftAnchorIcon,
+ {
+ gravity: 1,
+ minWidth: 10
+ },
+ {
+ rows: [
+ {gravity: 1},
+ leftGroupDropdown,
+ {gravity: 1},
+ ]
+ },
+ {width: 100}
+ ]
+ };
+
+ /** @type {webix.ui.toolbarConfig} */
+ const rightToolbar = {
+ height: 60,
+ cols: [
+ {width: 100},
+ {
+ rows: [
+ {gravity: 1},
+ rightGroupDropdown,
+ {gravity: 1},
+ ]
+ },
+ {gravity: 1},
+ rightImageLabel,
+ {width: 5},
+ rightAnchorIcon,
+ {gravity: 1},
+ ],
+ };
+
+ const leftFooter = getFooter(ID_LEFT_FOOTER, constants.MULTI_LESION_SIDE.LEFT);
+ const rightFooter = getFooter(ID_RIGHT_FOOTER, constants.MULTI_LESION_SIDE.RIGHT);
+
+ const leftImageContainer = {
+ css: "container",
+ cols: [
+ {
+ rows: [
+ leftToolbar,
+ {
+ css: "left-image-panel-container",
+ cols: [
+ leftTemplateViewer,
+ ]
+ },
+ {
+ cols: [
+ {width: 10},
+ leftFooter
+ ]
+ }
+ ]
+ },
+ {
+ width: 1,
+ cols: [
+ leftSlider
+ ]
+ }
+ ]
+ };
+
+ const rightImageContainer = {
+ id: ID_RIGHT_CONTAINER,
+ css: "container",
+ cols: [
+ {
+ width: 1,
+ cols: [
+ rightSlider
+ ]
+ },
+ {
+ rows: [
+ rightToolbar,
+ {
+ css: "right-image-panel-container",
+ cols: [
+ rightTemplateViewer,
+ ]
+ },
+ rightFooter
+ ]
+ }
+ ]
+ };
+
+ return {
+ view: "window",
+ id: ID_MULTI_IMAGE_LESION_WINDOW,
+ width: 1240,
+ height: 750,
+ css: "window-with-header",
+ modal: true,
+ fullscreen: false,
+ position: "center",
+ headHeight: 48,
+ move: false,
+ head: {
+ view: "toolbar",
+ css: "window-header-toolbar2",
+ borderless: true,
+ type: "clean",
+ height: 48,
+ cols: [
+ {
+ template: `` || "",
+ css: "window-header-toolbar-text main-subtitle4 window-header-toolbar2__title",
+ borderless: true,
+ autoheight: true,
+ },
+ {gravity: 0.001},
+ {
+ view: "search",
+ icon: "fas fa-search lesionWindow__filter-search",
+ id: ID_SEARCH,
+ name: "multilesionSearchName",
+ value: `${appliedFiltersModel.getFilterValue()}`,
+ css: "multi-image-lesion-search-block",
+ placeholder: "Search images",
+ hidden: true,
+ inputHeight: 38,
+ width: 634,
+ },
+ {width: 20},
+ {
+ view: "button",
+ id: ID_BUTTON_FULL_SCREEN,
+ label: "Full Screen",
+ css: "window-header-toolbar2__fullscreen-button",
+ type: "icon",
+ icon: "fas fa-expand",
+ width: 120,
+ height: 32,
+ },
+ {
+ view: "button",
+ id: ID_BUTTON_WINDOWED,
+ hidden: true,
+ label: "Windowed",
+ css: "window-header-toolbar2__fullscreen-button",
+ type: "icon",
+ icon: "fas fa-compress",
+ width: 120,
+ height: 32,
+ },
+ {width: 20},
+ {
+ view: "button",
+ css: "window-close-button",
+ label: '',
+ type: "htmlbutton",
+ width: 30,
+ align: "right",
+ on: {
+ onItemClick() {
+ this.getTopParentView().hide();
+ if (typeof closeCallback === "function") {
+ closeCallback();
+ }
+ }
+ }
+ },
+ {width: 5}
+ ]
+ },
+ body: {
+ css: "multi-image-lesion-window-body",
+ rows: [
+ topSlider,
+ topSliderCollapser,
+ {height: 10},
+ {
+ cols: [
+ leftImageContainer,
+ rightImageContainer
+ ]
+ }
+ ]
+ }
+ };
+}
+
+/**
+ * Description placeholder
+ *
+ * @returns {webix.ui.listConfig}
+ */
+function getTopSlider(topPanelID, sliderID, prevButtonID, nextButtonID) {
+ return {
+ id: topPanelID,
+ hidden: true,
+ cols: [
+ {width: 20},
+ {
+ view: "icon",
+ id: prevButtonID,
+ width: 24,
+ icon: "fas fa-chevron-left",
+ css: "navigation-button"
+ },
+ {
+ view: "list",
+ id: sliderID,
+ layout: "x",
+ css: "multilesion-top-list",
+ scroll: false,
+ select: false,
+ drag: true,
+ height: 134,
+ type: {
+ height: 104
+ },
+ template(obj, /* common */) {
+ const lesionID = lesionsModel.getItemLesionID(obj);
+ const lesion = lesionsModel.getLesionByID(lesionID);
+ const lesionModalitiesCount = lesionID
+ ? lesionsModel.getLesionModalitiesCount(lesionID)
+ : null;
+ const lesionTimePointsCount = lesionID
+ ? lesionsModel.getLesionTimePointsCount(lesionID)
+ : null;
+ const imageIconDimensions = {
+ iconContainerDimensions: {
+ width: constants.DEFAULT_RIBBON_ICON_CONTAINER_WIDTH,
+ height: constants.DEFAULT_RIBBON_ICON_CONTAINER_HEIGHT
+ },
+ iconDimensions: {
+ width: constants.DEFAULT_RIBBON_IMAGE_ICON_WIDTH,
+ height: constants.DEFAULT_RIBBON_IMAGE_ICON_HEIGHT
+ }
+ };
+ const lesionIconElementClass = lesion
+ ? "gallery-images-button-elem"
+ : "gallery-images-button-elem-disabled";
+ const disabledBadge = lesion
+ ? ""
+ : " disabled-badge";
+ const diagnosisIcon = obj.hasAnnotations ?
+ `
+
+
+
+ Multirater
+
` : "";
+ const lesionIcon = `
+
+
+
+ Lesion
+ ${lesionModalitiesCount ?? 0}
+ Modalities count
+ ${lesionTimePointsCount ?? 0}
+ Time points count
+
`;
+ const starHtml = obj.hasAnnotations ? "" : "";
+ if (typeof galleryImageUrl.getPreviewImageUrl(lesionsModel.getItemID(obj)) === "undefined") {
+ galleryImageUrl.setPreviewImageUrl(
+ lesionsModel.getItemID(obj),
+ obj.files.thumbnail_256.url
+ ); // to prevent sending query more than 1 time
+ }
+ return `
+
+ ${starHtml}
+
+
`;
+ },
+ },
+ {
+ view: "icon",
+ id: nextButtonID,
+ width: 24,
+ icon: "fas fa-chevron-right",
+ css: "navigation-button"
+ },
+ {width: 20}
+ ]
+ };
+}
+
+function getVerticalSlider(id, side) {
+ return {
+ view: "list",
+ id,
+ layout: "y",
+ drag: true,
+ select: false,
+ type: {
+ width: 62,
+ height: 42,
+ },
+ css: `vertical-slider-${side}`,
+ width: 1,
+ /**
+ *
+ * @param {Object} obj
+ * @param {obj} obj.firstImage
+ * @param {string} obj.groupBy
+ * @param {string | number} obj.groupValue
+ * @param {Array} obj.images
+ * @returns
+ */
+ template(obj, /* common */) {
+ let images;
+ let multipleFlag = false;
+ if (obj.images) {
+ images = obj.images;
+ multipleFlag = obj.images.length > 1;
+ }
+ const lesionID = lesionsModel.getItemLesionID(images[0]);
+ const anchorImageID = lesionsModel.getAnchorImageID(lesionID);
+ const anchorIcon = lesionsModel.getItemID(images) === anchorImageID
+ ? `
+
+
`
+ : "";
+ images.forEach((i) => {
+ if (typeof galleryImageUrl.getPreviewImageUrl(lesionsModel.getItemID(i)) === "undefined") {
+ galleryImageUrl.setPreviewImageUrl(
+ lesionsModel.getItemID(i),
+ i.files.thumbnail_256.url
+ ); // to prevent sending query more than 1 time
+ }
+ });
+ return ``;
+ }
+ };
+}
+
+
+/**
+ * Description placeholder
+ *
+ * @param {boolean} showButtons
+ * @returns {webix.ui.templateConfig}
+ */
+function getTemplateViewer(id, showButtons, side) {
+ return {
+ view: "template",
+ id,
+ css: "absolute-centered-image-template",
+ template(obj) {
+ const imageUrl = galleryImageUrl.getNormalImageUrl(lesionsModel.getItemID(obj)) || "";
+ const lesionsImages = side === constants.MULTI_LESION_SIDE.LEFT
+ ? lesionsModel.getCurrentLeftImages()
+ : lesionsModel.getCurrentRightImages();
+ return `
+
+
+ ${showButtons && lesionsImages.length > 1 ? '❮❯' : ""}
+ `;
+ },
+ borderless: true
+ };
+}
+
+function getImageLabel(imageNameId) {
+ return {
+ view: "label",
+ css: "multi-image-lesion-window__image-label",
+ width: 100,
+ id: imageNameId,
+ label: ""
+ };
+}
+
+function footerTemplateFunction(obj, /* common */) {
+ const lesionID = lesionsModel.getItemLesionID(obj);
+ const lesionImagesCount = lesionID
+ ? lesionsModel.getLesionImagesCount(lesionID)
+ : "";
+ const lesionTimePointsCount = lesionID
+ ? lesionsModel.getLesionTimePointsCount(lesionID)
+ : "";
+ let multipleModalities;
+ let timePoint;
+ let modality;
+ if (lesionID) {
+ multipleModalities = lesionsModel.checkMultipleModality(lesionID) ? "Yes" : "No";
+ timePoint = lesionsModel.getItemTimePoint(obj);
+ modality = lesionsModel.getItemModality(obj);
+ }
+ else {
+ multipleModalities = "";
+ }
+ const container = $$(ID_RIGHT_CONTAINER).isVisible()
+ ? "