diff --git a/package-lock.json b/package-lock.json index c0166d6be5ded8ffc9eacc4cb0b08c66510d103f..439068220cecfd01195c9b686d54bbecabdb6a8b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,11 +10,9 @@ "license": "MIT", "dependencies": { "grunt-contrib-concat": "^2.1.0", - "grunt-contrib-uglify": "^5.2.2" - }, - "devDependencies": { "grunt-contrib-cssmin": "^5.0.0", "grunt-contrib-htmlmin": "^3.1.0", + "grunt-contrib-uglify": "^5.2.2", "grunt-minify-html": "^3.0.0" } }, @@ -29,7 +27,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -54,7 +51,6 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/argh/-/argh-0.1.4.tgz", "integrity": "sha512-sQN85FUGbEUBLyQiSJp4v8yAHTST2ao1WVXb/L8jkVqQTsypZuJQD0gMVeOLoSZBz21p22izF6HsBQP16QKQtg==", - "dev": true, "license": "MIT" }, "node_modules/argparse": { @@ -129,7 +125,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz", "integrity": "sha512-+MbKztAYHXPr1jNTSKQF52VpcFjwY5RkR7fxksV8Doo4KAYc5Fl4UJRgthBbTmEx8C54DqahhbLJkDwjI3PI/w==", - "dev": true, "license": "MIT", "dependencies": { "no-case": "^2.2.0", @@ -156,7 +151,6 @@ "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, "license": "MIT", "dependencies": { "source-map": "~0.6.0" @@ -169,7 +163,6 @@ "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" @@ -179,7 +172,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-1.4.0.tgz", "integrity": "sha512-xu6RvQqqrWEo6MPR1eixqGPywhYBHRs653F9jfXB2Hx4jdM/3WxiNE1vppRmxtMIfl16SFYTpYlrnqH/HsK/2w==", - "dev": true, "license": "ISC", "dependencies": { "ansi-regex": "^2.1.1", @@ -194,7 +186,6 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz", "integrity": "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==", - "dev": true, "license": "MIT", "dependencies": { "color-convert": "^1.9.3", @@ -223,7 +214,6 @@ "version": "1.9.1", "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", - "dev": true, "license": "MIT", "dependencies": { "color-name": "^1.0.0", @@ -234,7 +224,6 @@ "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, "license": "MIT", "dependencies": { "color-name": "1.1.3" @@ -244,14 +233,12 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true, "license": "MIT" }, "node_modules/colornames": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/colornames/-/colornames-1.1.1.tgz", "integrity": "sha512-/pyV40IrsdulWv+wFPmERh9k/mjsPZ64yUMDmWrtj/k1nmgrzzIENWKdaVKyBbvFdQWqkcaRxr+polCo3VMe7A==", - "dev": true, "license": "MIT" }, "node_modules/colors": { @@ -268,7 +255,6 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.4.tgz", "integrity": "sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==", - "dev": true, "license": "MIT", "dependencies": { "color": "^3.1.3", @@ -279,7 +265,6 @@ "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true, "license": "MIT" }, "node_modules/concat-map": { @@ -293,7 +278,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/d/-/d-1.0.2.tgz", "integrity": "sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw==", - "dev": true, "license": "ISC", "dependencies": { "es5-ext": "^0.10.64", @@ -327,7 +311,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/diagnostics/-/diagnostics-1.1.1.tgz", "integrity": "sha512-8wn1PmdunLJ9Tqbx+Fx/ZEuHfJf4NKSN2ZBj7SJC/OWRWha843+WsTjqMe1B5E3p28jqBlp+mJ2fPVxPyNgYKQ==", - "dev": true, "license": "MIT", "dependencies": { "colorspace": "1.1.x", @@ -339,7 +322,6 @@ "version": "0.2.2", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", - "dev": true, "license": "MIT", "dependencies": { "domelementtype": "^2.0.1", @@ -350,7 +332,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", - "dev": true, "funding": [ { "type": "github", @@ -363,7 +344,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", - "dev": true, "license": "BSD-2-Clause", "funding": { "url": "https://github.com/fb55/entities?sponsor=1" @@ -373,14 +353,12 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==", - "dev": true, "license": "BSD-2-Clause" }, "node_modules/domhandler": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz", "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==", - "dev": true, "license": "BSD-2-Clause", "dependencies": { "domelementtype": "1" @@ -390,7 +368,6 @@ "version": "1.7.0", "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==", - "dev": true, "license": "BSD-2-Clause", "dependencies": { "dom-serializer": "0", @@ -407,7 +384,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/each-async/-/each-async-1.1.1.tgz", "integrity": "sha512-0hJGub96skwr+sUojv7zQ0kc9i4jn3SwLiLk8Jr7KDz7aaaMzkN5UX3a/9ZhzC0OfZVyXHhlHcjC0KVOiKZ+HQ==", - "dev": true, "license": "MIT", "dependencies": { "onetime": "^1.0.0", @@ -421,14 +397,12 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/emits/-/emits-3.0.0.tgz", "integrity": "sha512-WJSCMaN/qjIkzWy5Ayu0MDENFltcu4zTPPnWqdFPOVBtsENVTN+A3d76G61yuiVALsMK+76MejdPrwmccv/wag==", - "dev": true, "license": "MIT" }, "node_modules/enabled": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/enabled/-/enabled-1.0.2.tgz", "integrity": "sha512-nnzgVSpB35qKrUN8358SjO1bYAmxoThECTWw9s3J0x5G8A9hokKHVDFzBjVpCoSryo6MhN8woVyascN5jheaNA==", - "dev": true, "license": "MIT", "dependencies": { "env-variable": "0.0.x" @@ -438,21 +412,18 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==", - "dev": true, "license": "BSD-2-Clause" }, "node_modules/env-variable": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/env-variable/-/env-variable-0.0.6.tgz", "integrity": "sha512-bHz59NlBbtS0NhftmR8+ExBEekE7br0e01jw+kk0NDro7TtZzBYZ5ScGPs3OmwnpyfHTHOtr1Y6uedCdrIldtg==", - "dev": true, "license": "MIT" }, "node_modules/es5-ext": { "version": "0.10.64", "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.64.tgz", "integrity": "sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==", - "dev": true, "hasInstallScript": true, "license": "ISC", "dependencies": { @@ -469,7 +440,6 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==", - "dev": true, "license": "MIT", "dependencies": { "d": "1", @@ -481,7 +451,6 @@ "version": "3.1.4", "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.4.tgz", "integrity": "sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg==", - "dev": true, "license": "ISC", "dependencies": { "d": "^1.0.2", @@ -495,7 +464,6 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", - "dev": true, "license": "ISC", "dependencies": { "d": "1", @@ -517,7 +485,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/esniff/-/esniff-2.0.1.tgz", "integrity": "sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==", - "dev": true, "license": "ISC", "dependencies": { "d": "^1.0.1", @@ -547,7 +514,6 @@ "version": "0.3.5", "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", "integrity": "sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==", - "dev": true, "license": "MIT", "dependencies": { "d": "1", @@ -587,7 +553,6 @@ "version": "1.7.0", "resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz", "integrity": "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==", - "dev": true, "license": "ISC", "dependencies": { "type": "^2.7.2" @@ -869,7 +834,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/grunt-contrib-cssmin/-/grunt-contrib-cssmin-5.0.0.tgz", "integrity": "sha512-SNp4H4+85mm2xaHYi83FBHuOXylpi5vcwgtNoYCZBbkgeXQXoeTAKa59VODRb0woTDBvxouP91Ff5PzCkikg6g==", - "dev": true, "license": "MIT", "dependencies": { "chalk": "^4.1.2", @@ -884,7 +848,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/grunt-contrib-htmlmin/-/grunt-contrib-htmlmin-3.1.0.tgz", "integrity": "sha512-Khaa+0MUuqqNroDIe9tsjZkioZnW2Y+iTGbonBkLWaG7+SkSFExfb4jLt7M6rxKV3RSqlS7NtVvu4SVIPkmKXg==", - "dev": true, "license": "MIT", "dependencies": { "chalk": "^2.4.2", @@ -899,7 +862,6 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, "license": "MIT", "dependencies": { "color-convert": "^1.9.0" @@ -912,7 +874,6 @@ "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^3.2.1", @@ -927,7 +888,6 @@ "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, "license": "MIT", "dependencies": { "color-name": "1.1.3" @@ -937,14 +897,12 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true, "license": "MIT" }, "node_modules/grunt-contrib-htmlmin/node_modules/has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, "license": "MIT", "engines": { "node": ">=4" @@ -954,7 +912,6 @@ "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, "license": "MIT", "dependencies": { "has-flag": "^3.0.0" @@ -1041,7 +998,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/grunt-minify-html/-/grunt-minify-html-3.0.0.tgz", "integrity": "sha512-//Paw/bXj9H+aZltKAC6fGXRbhtr5QKla/ZPOQjMiqZnI1sIrI82+3Q6fIEHhjeW4rJxmZ/Bwc1yJF1L+PySog==", - "dev": true, "license": "MIT", "dependencies": { "each-async": "^1.0.0", @@ -1094,7 +1050,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true, "license": "MIT", "bin": { "he": "bin/he" @@ -1126,7 +1081,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-4.0.0.tgz", "integrity": "sha512-aoGxanpFPLg7MkIl/DDFYtb0iWz7jMFGqFhvEDZga6/4QTjneiD8I/NXL1x5aaoCp7FSIT6h/OhykDdPsbtMig==", - "dev": true, "license": "MIT", "dependencies": { "camel-case": "^3.0.0", @@ -1148,7 +1102,6 @@ "version": "4.2.4", "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.4.tgz", "integrity": "sha512-EJUDT7nDVFDvaQgAo2G/PJvxmp1o/c6iXLbswsBbUFXi1Nr+AjA2cKmfbKDMjMvzEe75g3P6JkaDDAKk96A85A==", - "dev": true, "license": "MIT", "dependencies": { "source-map": "~0.6.0" @@ -1161,7 +1114,6 @@ "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" @@ -1171,7 +1123,6 @@ "version": "3.10.1", "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz", "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==", - "dev": true, "license": "MIT", "dependencies": { "domelementtype": "^1.3.1", @@ -1245,7 +1196,6 @@ "version": "0.3.2", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", - "dev": true, "license": "MIT" }, "node_modules/is-core-module": { @@ -1314,7 +1264,6 @@ "version": "2.2.2", "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==", - "dev": true, "license": "MIT" }, "node_modules/is-relative": { @@ -1398,7 +1347,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/kuler/-/kuler-1.0.1.tgz", "integrity": "sha512-J9nVUucG1p/skKul6DU3PUZrhs0LPulNaeUOox0IyXDi8S4CztTHs1gQphhuZmzXG7VOQSf6NJfKuzteQLv9gQ==", - "dev": true, "license": "MIT", "dependencies": { "colornames": "^1.1.1" @@ -1450,14 +1398,12 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz", "integrity": "sha512-2Fgx1Ycm599x+WGpIYwJOvsjmXFzTSc34IwDWALRA/8AopUKAVPwfJ+h5+f85BCp0PWmmJcWzEpxOpoXycMpdA==", - "dev": true, "license": "MIT" }, "node_modules/lru-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", "integrity": "sha512-BpdYkt9EvGl8OfWHDQPISVpcl5xZthb+XPsbELj5AQXxIC8IriDZIQYjBJPEm5rS420sjZ0TLEzRcq5KdBhYrQ==", - "dev": true, "license": "MIT", "dependencies": { "es5-ext": "~0.10.2" @@ -1467,7 +1413,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", - "dev": true, "license": "MIT", "dependencies": { "pify": "^3.0.0" @@ -1480,7 +1425,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", - "dev": true, "license": "MIT", "engines": { "node": ">=4" @@ -1531,7 +1475,6 @@ "version": "0.4.17", "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.17.tgz", "integrity": "sha512-DGqD7Hjpi/1or4F/aYAspXKNm5Yili0QDAFAY4QYvpqpgiY6+1jOfqpmByzjxbWd/T9mChbCArXAbDAsTm5oXA==", - "dev": true, "license": "ISC", "dependencies": { "d": "^1.0.2", @@ -1578,7 +1521,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/minimize/-/minimize-2.2.0.tgz", "integrity": "sha512-IxR2XMbw9pXCxApkdD9BTcH2U4XlXhbeySUrv71rmMS9XDA8BVXEsIuFu24LtwCfBgfbL7Fuh8/ZzkO5DaTLlQ==", - "dev": true, "license": "MIT", "dependencies": { "argh": "^0.1.4", @@ -1597,7 +1539,6 @@ "version": "2.6.4", "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", - "dev": true, "license": "MIT", "dependencies": { "lodash": "^4.17.14" @@ -1607,14 +1548,12 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==", - "dev": true, "license": "ISC" }, "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, "license": "MIT", "dependencies": { "lower-case": "^1.1.1" @@ -1690,7 +1629,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", "integrity": "sha512-GZ+g4jayMqzCRMgB2sol7GiCLjKfS1PINkjmx8spcKce1LiVqcbQreXwqs2YAFXC6R03VIG28ZS31t8M866v6A==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -1732,7 +1670,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz", "integrity": "sha512-eQE845L6ot89sk2N8liD8HAuH4ca6Vvr7VWAWwt7+kvvG5aBcPmmphQ68JsEG2qa9n1TykS2DLeMt363AAH8/w==", - "dev": true, "license": "MIT", "dependencies": { "no-case": "^2.2.0" @@ -1841,7 +1778,6 @@ "version": "3.6.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, "license": "MIT", "dependencies": { "inherits": "^2.0.3", @@ -1869,7 +1805,6 @@ "version": "0.2.7", "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", "integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.10" @@ -1911,7 +1846,6 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, "funding": [ { "type": "github", @@ -1939,7 +1873,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", "integrity": "sha512-Li5AOqrZWCVA2n5kryzEmqai6bKSIvpz5oUJHPVj6+dsbD3X1ixtsY5tEnsaNpH3pFAHmG8eIHUrtEtohrg+UQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -1949,7 +1882,6 @@ "version": "0.2.2", "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", - "dev": true, "license": "MIT", "dependencies": { "is-arrayish": "^0.3.1" @@ -1975,7 +1907,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, "license": "MIT", "dependencies": { "safe-buffer": "~5.2.0" @@ -2010,14 +1941,12 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==", - "dev": true, "license": "MIT" }, "node_modules/timers-ext": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.8.tgz", "integrity": "sha512-wFH7+SEAcKfJpfLPkrgMPvvwnEtj8W4IurvEyrKsDleXnKLCDw71w8jltvfLa8Rm4qQxxT4jmDBYbJG/z7qoww==", - "dev": true, "license": "ISC", "dependencies": { "es5-ext": "^0.10.64", @@ -2044,7 +1973,6 @@ "version": "2.7.3", "resolved": "https://registry.npmjs.org/type/-/type-2.7.3.tgz", "integrity": "sha512-8j+1QmAbPvLZow5Qpi6NCaN8FB60p/6x8/vfNqOk/hC+HuvFZhL4+WfekuhQLiqFZXOgQdrs3B+XxEmCc6b3FQ==", - "dev": true, "license": "ISC" }, "node_modules/uglify-js": { @@ -2094,7 +2022,6 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz", "integrity": "sha512-WRbjgmYzgXkCV7zNVpy5YgrHgbBv126rMALQQMrmzOVC4GM2waQ9x7xtm8VU+1yF2kWyPzI9zbZ48n4vSxwfSA==", - "dev": true, "license": "MIT" }, "node_modules/uri-path": { @@ -2117,7 +2044,6 @@ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", - "dev": true, "license": "MIT", "bin": { "uuid": "bin/uuid" diff --git a/src/app.html b/src/app.html index e5db8fcd2d28b60a5204634f573b7bf6ec63be66..9b8073d7dab74ddef85fcfbb19fcfa2b0076bb6c 100644 --- a/src/app.html +++ b/src/app.html @@ -322,7 +322,7 @@ <div id="panelsStayOpen-collapseTwo" class="accordion-collapse collapse" aria-labelledby="panelsStayOpen-headingTwo"> <div class="accordion-body"> - <div id="annotation_editor_container" aria-hidden="true" class="card mb-3 overflow-auto" + <div id="annotation_editor_container" class="card mb-3 overflow-auto" style="height: 250px"> <div class="card-body" id="annotation_editor_panel"> <h5 class="card-title placeholder-glow"> @@ -1173,6 +1173,25 @@ </div> <!-- end of message panel --> + <!-- disclamier modal --> + <div class="modal fade" id="disclaimerModal" tabindex="-1" aria-labelledby="disclaimerModalLabel" aria-hidden="true"> + <div class="modal-dialog"> + <div class="modal-content"> + <div class="modal-header"> + <h5 class="modal-title" id="disclaimerModalLabel">Disclaimer</h5> + <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> + </div> + <div class="modal-body"> + <p>This application is still in development; therefore, errors or unexpected behavior may be experienced. We would be glad to improve any issues reported at infarctsize@pharmahungary.com</p> + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-primary" data-bs-dismiss="modal">I understand</button> + </div> + </div> + </div> + </div> + <!-- end of disclamier modal --> + <!-- end of main panel --> <div id="loading" class="d-flex justify-content-center align-items-center" style=" @@ -1197,6 +1216,16 @@ $(window).on("load", function () { $("#loading").fadeOut(500).addClass("d-none"); }); + $(document).ready(function() { + // Check if disclaimer has been shown before + if (!localStorage.getItem('disclaimerShown')) { + // Show the modal + $('#disclaimerModal').modal('show'); + + // Set flag in localStorage + localStorage.setItem('disclaimerShown', 'true'); + } + }); </script> <script src="https://cdn.jsdelivr.net/npm/@panzoom/panzoom@4.5.1/dist/panzoom.min.js" diff --git a/src/js/buffer.js b/src/js/buffer.js index 3d1658fc0e874da2ef18713e3d39daedfc8fe91a..6041b8786a1bd82378648bda2b0f888b7c9df0ba 100644 --- a/src/js/buffer.js +++ b/src/js/buffer.js @@ -123,8 +123,6 @@ class ImageBuffer { } postImageLoad(idx) { - _via_img_metadata[_via_image_id].clearGroupedRegions(); - let arr_idx = this.bufferIdList.indexOf(idx); this.bufferTimestamp[arr_idx] = Date.now(); @@ -193,7 +191,7 @@ class ImageBuffer { zoom.fixCanvasBlur() image.show().then(_ => this.loading.addClass("d-none")); - if (_via_img_metadata[_via_image_id].autoAnnotated === undefined) { + if (_via_img_metadata[_via_image_id].autoAnnotated !== undefined) { if (_via_img_metadata[_via_image_id].autoAnnotated) { plugin.updateSliceRegion() } diff --git a/src/js/file_metadata.js b/src/js/file_metadata.js index 97bba2376d791d09b3e8d30c2503e4ec4b5ec3d1..f57a453e09e4e3a7dce3d5df1838f498335f9f17 100644 --- a/src/js/file_metadata.js +++ b/src/js/file_metadata.js @@ -20,7 +20,8 @@ class FileMetadata { this.groupedRegions = { groupBy: new Array(), groups: new Map(), - groupIDs: new Map() + groupIDs: new Map(), + hash: '', }; this.autoAnnotated = false; } @@ -49,6 +50,26 @@ class FileMetadata { this.lockedRegions.clear(); } + computeHash() { + let str = JSON.stringify(this.regions); + let hash = 0; + if (str.length == 0) return hash; + for (let i = 0; i < str.length; i++) { + let char = str.charCodeAt(i); + hash = ((hash << 5) - hash) + char; + hash = hash & hash; + } + return hash + } + + getHash() { + return this.groupedRegions.hash; + } + + updateHash(hash) { + this.groupedRegions.hash = hash; + } + clearRegionLock(region) { this.lockedRegions.delete(region); } @@ -87,6 +108,10 @@ class FileMetadata { this.groupedRegions.groups.set(region, group); } + isGroupEmpty() { + return this.groupedRegions.groups.size === 0; + } + getGroupedRegion(region) { return this.groupedRegions.groups.get(region); } diff --git a/src/js/science_plugins.js b/src/js/science_plugins.js index 02fb4dd6142494a82128e5e854f96c105e46055f..53697fd81f933f20665cbae5c7c09c9afdf4bfaf 100644 --- a/src/js/science_plugins.js +++ b/src/js/science_plugins.js @@ -6,6 +6,7 @@ function infarctSizeAiWorker() { let slice_regions_id = JSON.parse(e.data.slice_regions_id); let regions = JSON.parse(e.data.regions); let update = e.data.update; + let image_id = e.data.image_id; let grouped_regions = {}; // Pre-calculate centroids for all regions @@ -59,6 +60,7 @@ function infarctSizeAiWorker() { grouped_regions[element] = tmp; } postMessage({ + image_id: image_id, slice_regions_id: JSON.stringify(slice_regions_id), grouped_regions: JSON.stringify(grouped_regions), update: update, @@ -159,11 +161,13 @@ function Science_plugins() { }) ) ); + this.workerSignal = new Set(); this.GroupingWorker.onmessage = this.groupingWorkerOnMessage.bind(this); } -Science_plugins.prototype.updateSliceRegion = function (img_id = _via_image_id, update = true) { +Science_plugins.prototype.updateSliceRegion = async function (img_id = _via_image_id, update = true) { let groupBy = []; + this.workerSignal.add(img_id); for (let i = 0; i < _via_img_metadata[img_id].regions.length; ++i) { if ( _via_img_metadata[img_id].regions[i].region_attributes.Type === @@ -173,32 +177,69 @@ Science_plugins.prototype.updateSliceRegion = function (img_id = _via_image_id, } } if (groupBy.length === 0) { - console.log("No slice regions found"); + this.workerSignal.delete(img_id); + console.warn("No slice regions found"); return false; } - if (groupBy === _via_img_metadata[img_id].groupedRegions.groupBy) { - console.log("No change in slice regions") + let hash = _via_img_metadata[img_id].computeHash(); + if (hash === _via_img_metadata[img_id].getHash() && !_via_img_metadata[img_id].isGroupEmpty()) { + this.workerSignal.delete(img_id); + console.debug("No change in regions or groups not empty"); return false; } - _via_img_metadata[img_id].clearGroups(); + _via_img_metadata[_via_image_id].updateHash(hash); this.GroupingWorker.postMessage({ + image_id: img_id, slice_regions_id: JSON.stringify(groupBy), regions: JSON.stringify(_via_img_metadata[img_id].regions), - grouped_regions: JSON.stringify(_via_img_metadata[_via_image_id].groupedRegions.groups, Project.replacer), + grouped_regions: JSON.stringify(_via_img_metadata[img_id].groupedRegions.groups, Project.replacer), update: update, }); }; // Grouping regions on other thread -Science_plugins.prototype.groupingWorkerOnMessage = function (e) { +Science_plugins.prototype.groupingWorkerOnMessage = async function (e) { let groups = JSON.parse(e.data.grouped_regions); + let img_id = e.data.image_id; + if (Object.keys(groups).length === 0) { + console.debug("No groups found"); + return; + } + _via_img_metadata[img_id].clearGroups(); for (const element in groups) { - _via_img_metadata[_via_image_id].addGroupedRegion(parseInt(element), groups[element]) + _via_img_metadata[img_id].addGroupedRegion(parseInt(element), groups[element]) } - _via_img_metadata[_via_image_id].groupedRegions.groupBy = JSON.parse(e.data.slice_regions_id); + _via_img_metadata[img_id].groupedRegions.groupBy = JSON.parse(e.data.slice_regions_id); if (e.data.update) { sidebar.annotation_editor_update_content(); } + this.workerSignal.delete(img_id); +}; + +Science_plugins.prototype.getGroupingProgress = function (imageId, timeout = 5000) { + return new Promise((resolve) => { + const startTime = Date.now(); + + const checkProgress = () => { + // If no longer processing, resolve success + if (!this.workerSignal.has(imageId)) { + resolve(true); + return; + } + + // If timeout reached, resolve false + if (Date.now() - startTime > timeout) { + resolve(false); + return; + } + + // Check again after small delay + setTimeout(checkProgress, 100); + }; + + // Start checking + checkProgress(); + }); }; // Grouping modify name to group @@ -294,7 +335,7 @@ Science_plugins.prototype.calcPolygonArea = function (xCoordinates, yCoordinates // Export the region sizes to a csv file Science_plugins.prototype.ExportArea = async function () { - let rows = [ + const rows = [ ["Filename", "File_ID", "Treatment_ID", "Slice_ID", "Slice_area", "Infract_area", "Risk_area", "Slice_score", "Infract_score", "Risk_score"] ]; let done = 0; @@ -303,130 +344,119 @@ Science_plugins.prototype.ExportArea = async function () { if (_via_img_metadata[img_id].regions.length === 0) { continue; } - if (!_via_img_metadata[img_id].groupedRegions.groups.size > 0) { - if (!this.updateSliceRegion(img_id, false)) { - console.log("Slice regions updated but not grouped yet. Skipping image: " + img_id); - continue; - } + this.updateSliceRegion(_via_image_id, false); + await this.getGroupingProgress(_via_image_id); + + let slices = []; + if (_via_img_metadata[img_id].groupedRegions.groups === 0) { + message.showError("No groups found! Ensure that there are slice regions in the image: " + _via_image_filename_list[img_index]); + return; } - await new Promise((resolve) => { - let interval = setInterval(() => { - if (_via_img_metadata[img_id].groupedRegions.groups.size > 0) { - clearInterval(interval); - resolve(); - } - }, 100); - }).then(() => { - let slices = []; - if (_via_img_metadata[img_id].groupedRegions.groups === 0) { - return; + for (let i = 0; i < _via_img_metadata[img_id].groupedRegions.groupBy.length; i++) { + let element = _via_img_metadata[img_id].groupedRegions.groupBy[i]; + let slice = { + ID: i + 1, + Area: 0, + InfarctArea: 0, + RiskArea: 0, + SliceScore: "n/a", + InfarctScore: "n/a", + RiskScore: "n/a", + }; + let scores = { + score_exists: false, + Slice: 0, + Slice_no: 0, + Infarct: 0, + Infarct_no: 0, + Risk: 0, + Risk_no: 0, + }; + if (_via_img_metadata[img_id].groupedRegions.groupIDs.has(element)) { + slice.ID = _via_img_metadata[img_id].groupedRegions.groupIDs.get(element); } - for (let i = 0; i < _via_img_metadata[img_id].groupedRegions.groupBy.length; i++) { - let element = _via_img_metadata[img_id].groupedRegions.groupBy[i]; - let slice = { - ID: i + 1, - Area: 0, - InfarctArea: 0, - RiskArea: 0, - SliceScore: "n/a", - InfarctScore: "n/a", - RiskScore: "n/a", - }; - let scores = { - score_exists: false, - Slice: 0, - Slice_no: 0, - Infarct: 0, - Infarct_no: 0, - Risk: 0, - Risk_no: 0, - }; - if (_via_img_metadata[img_id].groupedRegions.groupIDs.has(element)) { - slice.ID = _via_img_metadata[img_id].groupedRegions.groupIDs.get(element); - } - slice.Area = this.calcPolygonArea(_via_img_metadata[img_id].regions[element].shape_attributes.all_points_x, _via_img_metadata[img_id].regions[element].shape_attributes.all_points_y); - if (_via_img_metadata[img_id].regions[element].hasOwnProperty("score")) { + slice.Area = this.calcPolygonArea(_via_img_metadata[img_id].regions[element].shape_attributes.all_points_x, _via_img_metadata[img_id].regions[element].shape_attributes.all_points_y); + if (_via_img_metadata[img_id].regions[element].hasOwnProperty("score")) { + scores.score_exists = true; + scores.Slice += _via_img_metadata[img_id].regions[element].score; + scores.Slice_no++; + } + for (let i = 0; i < _via_img_metadata[img_id].getGroupedRegion(element).length; i++) { + let region = _via_img_metadata[img_id].regions[_via_img_metadata[img_id].getGroupedRegion(element)[i]]; + let Area = this.calcPolygonArea(region.shape_attributes.all_points_x, region.shape_attributes.all_points_y); + if (region.hasOwnProperty("score")) { scores.score_exists = true; - scores.Slice += _via_img_metadata[img_id].regions[element].score; - scores.Slice_no++; - } - for (let i = 0; i < _via_img_metadata[img_id].getGroupedRegion(element).length; i++) { - let region = _via_img_metadata[img_id].regions[_via_img_metadata[img_id].getGroupedRegion(element)[i]]; - let Area = this.calcPolygonArea(region.shape_attributes.all_points_x, region.shape_attributes.all_points_y); - if (region.hasOwnProperty("score")) { - scores.score_exists = true; - switch (region.region_attributes.Type) { - case "Slice": - if (region.score === "n/a") { - break; - } - scores.Slice += region.score; - scores.Slice_no++; - break; - case "Risk": - if (region.score === "n/a") { - break; - } - scores.Risk += region.score; - scores.Risk_no++; - break; - case "Infarct": - if (region.score === "n/a") { - break; - } - scores.Infarct += region.score; - scores.Infarct_no++; - break; - } - } switch (region.region_attributes.Type) { case "Slice": - slice.Area -= Area; + if (region.score === "n/a") { + break; + } + scores.Slice += region.score; + scores.Slice_no++; break; case "Risk": - slice.RiskArea += Area; + if (region.score === "n/a") { + break; + } + scores.Risk += region.score; + scores.Risk_no++; break; case "Infarct": - slice.InfarctArea += Area; + if (region.score === "n/a") { + break; + } + scores.Infarct += region.score; + scores.Infarct_no++; break; } } - if (scores.score_exists) { - if (scores.Slice_no > 0 && scores.Slice > 0) { - slice.SliceScore = scores.Slice / scores.Slice_no; - } else { - slice.SliceScore = "n/a"; - } - if (scores.Infarct_no > 0 && scores.Infarct > 0) { - slice.InfarctScore = scores.Infarct / scores.Infarct_no; - } else { - slice.InfarctScore = "n/a"; - } - if (scores.Risk_no > 0 && scores.Risk > 0) { - slice.RiskScore = scores.Risk / scores.Risk_no; - } else { - slice.RiskScore = "n/a"; - } + switch (region.region_attributes.Type) { + case "Slice": + slice.Area -= Area; + break; + case "Risk": + slice.RiskArea += Area; + break; + case "Infarct": + slice.InfarctArea += Area; + break; } - slices.push(slice); } - let img_file = _via_image_filename_list[img_index]; - let file_id = _via_img_metadata[img_id].file_attributes.ID || ""; - slices.forEach((slice, i) => { - rows.push([ - img_file, - file_id, - slice.ID, - slice.Area, - slice.InfarctArea, - slice.RiskArea, - slice.SliceScore, - slice.InfarctScore, - slice.RiskScore - ]); - }); - done++; + if (scores.score_exists) { + if (scores.Slice_no > 0 && scores.Slice > 0) { + slice.SliceScore = scores.Slice / scores.Slice_no; + } else { + slice.SliceScore = "n/a"; + } + if (scores.Infarct_no > 0 && scores.Infarct > 0) { + slice.InfarctScore = scores.Infarct / scores.Infarct_no; + } else { + slice.InfarctScore = "n/a"; + } + if (scores.Risk_no > 0 && scores.Risk > 0) { + slice.RiskScore = scores.Risk / scores.Risk_no; + } else { + slice.RiskScore = "n/a"; + } + } + slices.push(slice); + } + let img_file = _via_image_filename_list[img_index]; + let file_id = _via_img_metadata[img_id].file_attributes.ID || ""; + slices.forEach((slice, i) => { + rows.push([ + img_file, + file_id, + slice.ID, + slice.Area, + slice.InfarctArea, + slice.RiskArea, + slice.SliceScore, + slice.InfarctScore, + slice.RiskScore + ]); }); + done++; } let csvContent = "data:text/csv;charset=utf-8," + rows.map(e => e.join(",")).join("\n"); diff --git a/src/js/sidebar.js b/src/js/sidebar.js index 1a68933d61f074ad29087edaaa966ae793ecadf9..7ee6d0db7f83eee2a21be4cf0810d15986de8078 100644 --- a/src/js/sidebar.js +++ b/src/js/sidebar.js @@ -692,9 +692,11 @@ class Sidebar { annotation_editor_update_content() { try { if (this.ae !== undefined) { + this.ae.addClass("d-none"); this.ae.empty(); this.annotation_editor_update_header_html(); this.annotation_editor_update_metadata_html(); + this.ae.removeClass("d-none"); drawing.updateCheckedLockHtml(); } } catch (err) { @@ -880,115 +882,145 @@ class Sidebar { } } - annotation_editor_update_metadata_html() { - if (!_via_img_count) { - return; + ensureTableBodyExists() { + if (!this.ae.find("tbody").length) { + const tbody = $('<tbody id="annotation_editor_content"></tbody>'); + this.ae.append(tbody); + this.aec = tbody; } + } - if (!this.ae.has("tbody").length) { - this.ae.append('<tbody id="annotation_editor_content"></tbody>'); - this.aec = $("#annotation_editor_content"); - } + createGroupRow(groupIndex, groupId) { + const rowId = `ae_row_${groupId}`; + const row = $("<tr>", { + id: rowId, + onclick: "plugin.selectAllRegionsInGroup(this)", + style: "height: 40px;", + class: "align-bottom", + }); + + const header = $("<th>", { + scope: "row", + id: `ae_${groupId}_rid`, + html: "O", + }); + + const placeholder = _via_img_metadata[_via_image_id].groupedRegions.groupIDs.has(groupId) + ? _via_img_metadata[_via_image_id].groupedRegions.groupIDs.get(groupId) + : `Group: ${groupIndex + 1}`; + + const cell = $("<td>", { + id: `ae_row_${groupId}_group`, + colspan: 4, + }); + + const input = $("<input>", { + class: 'form-control form-control-sm', + onchange: 'plugin.changeGroupIdentifier(this)', + type: 'text', + placeholder: placeholder, + 'aria-label': 'group identifier', + id: `group_${groupId}` + }); + + cell.append(input); + row.append(header, cell); + + return row; + } + - switch (_via_metadata_being_updated) { - case "region": - let rindex; - if (_via_display_area_content_name === VIA_DISPLAY_AREA_CONTENT_NAME.IMAGE_GRID) { - this.aec.append(this.annotation_editor_get_metadata_row_html(0)); + async updateRegionMetadata(){ + let rindex; + if (_via_display_area_content_name === VIA_DISPLAY_AREA_CONTENT_NAME.IMAGE_GRID) { + this.aec.append(this.annotation_editor_get_metadata_row_html(0)); + } else { + if (_via_display_area_content_name === VIA_DISPLAY_AREA_CONTENT_NAME.IMAGE) { + if (_via_annotation_editor_mode === VIA_ANNOTATION_EDITOR_MODE.SINGLE_REGION) { + this.aec.append( + this.annotation_editor_get_metadata_row_html( + drawing.userSelRegionId() + ) + ); } else { - if (_via_display_area_content_name === VIA_DISPLAY_AREA_CONTENT_NAME.IMAGE) { - if (_via_annotation_editor_mode === VIA_ANNOTATION_EDITOR_MODE.SINGLE_REGION) { - this.aec.append( - this.annotation_editor_get_metadata_row_html( - drawing.userSelRegionId() - ) + if (_via_img_metadata[_via_image_id].isGroupable()) { + plugin.updateSliceRegion(_via_image_id, false); + await plugin.getGroupingProgress(_via_image_id); + let tmp = []; + let colspan = 4; + let done_ids = []; + const fragment = document.createDocumentFragment(); + for (rindex = 0; rindex < _via_img_metadata[_via_image_id].groupedRegions.groupBy.length; ++rindex) { + if (!_via_img_metadata[_via_image_id].isGroupedKey(_via_img_metadata[_via_image_id].groupedRegions.groupBy[rindex])) { + continue; + } + this.createGroupRow(rindex, _via_img_metadata[_via_image_id].groupedRegions.groupBy[rindex]).appendTo(fragment); + $(fragment).append( + this.annotation_editor_get_metadata_row_html(_via_img_metadata[_via_image_id].groupedRegions.groupBy[rindex]) ); - } else { - if (_via_img_metadata[_via_image_id].isGroupable()) { - let tmp = []; - let colspan = 4; - let done_ids = []; - for (rindex = 0; rindex < _via_img_metadata[_via_image_id].groupedRegions.groupBy.length; ++rindex) { - if (!_via_img_metadata[_via_image_id].isGroupedKey(_via_img_metadata[_via_image_id].groupedRegions.groupBy[rindex])) { - continue; - } - $("<tr>", { - id: "ae_row_" + _via_img_metadata[_via_image_id].groupedRegions.groupBy[rindex], - onclick: "plugin.selectAllRegionsInGroup(this)", - style: "height: 40px;", - class: "align-bottom", - }).appendTo(this.aec); - $("<th>", { - scope: "row", - id: "ae_" + _via_img_metadata[_via_image_id].groupedRegions.groupBy[rindex] + "_rid", - html: "O", - }).appendTo("#ae_row_" + _via_img_metadata[_via_image_id].groupedRegions.groupBy[rindex]); - if (_via_img_metadata[_via_image_id].groupedRegions.groupIDs.has(_via_img_metadata[_via_image_id].groupedRegions.groupBy[rindex])) { - $("<td> ", { - id: "ae_row_" + _via_img_metadata[_via_image_id].groupedRegions.groupBy[rindex] + "_group", - colspan: colspan, - html: "<input class='form-control form-control-sm' onchange='plugin.changeGroupIdentifier(this)' type='text' placeholder='" + _via_img_metadata[_via_image_id].groupedRegions.groupIDs.get(_via_img_metadata[_via_image_id].groupedRegions.groupBy[rindex]) + "' aria-label='group identifier' id='group_" + _via_img_metadata[_via_image_id].groupedRegions.groupBy[rindex] + "'>" - }).appendTo("#ae_row_" + _via_img_metadata[_via_image_id].groupedRegions.groupBy[rindex]); - } else { - $("<td> ", { - id: "ae_row_" + _via_img_metadata[_via_image_id].groupedRegions.groupBy[rindex] + "_group", - colspan: colspan, - html: "<input class='form-control form-control-sm' onchange='plugin.changeGroupIdentifier(this)' type='text' placeholder='" + "Group: " + (rindex + 1) + "' aria-label='group identifier' id='group_" + _via_img_metadata[_via_image_id].groupedRegions.groupBy[rindex] + "'>" - }).appendTo("#ae_row_" + _via_img_metadata[_via_image_id].groupedRegions.groupBy[rindex]); - } - - this.aec.append( - this.annotation_editor_get_metadata_row_html(_via_img_metadata[_via_image_id].groupedRegions.groupBy[rindex]) - ); - done_ids.push(_via_img_metadata[_via_image_id].groupedRegions.groupBy[rindex]); - tmp = _via_img_metadata[_via_image_id].getGroupedRegion(_via_img_metadata[_via_image_id].groupedRegions.groupBy[rindex]); - for (const element of tmp) { - this.aec.append( - this.annotation_editor_get_metadata_row_html(element) - ); - done_ids.push(element); - } - } - $("<tr>", { - id: "ae_no_group", - style: "height: 40px;", - class: "align-bottom", - }).appendTo(this.aec); - $("<th>", { - scope: "row", - id: "ae_no_group_rid", - html: "X", - }).appendTo("#ae_no_group"); - $("<td> ", { - id: "ae_row_no_group", - colspan: colspan, - html: "Other", - }).appendTo("#ae_no_group"); - for ( - rindex = 0; - rindex < _via_img_metadata[_via_image_id].regions.length; - ++rindex - ) { - if (!done_ids.includes(rindex)) { - this.aec.append( - this.annotation_editor_get_metadata_row_html(rindex) - ); - } - } - } else { - for ( - rindex = 0; - rindex < _via_img_metadata[_via_image_id].regions.length; - ++rindex - ) { - this.aec.append( - this.annotation_editor_get_metadata_row_html(rindex) - ); - } + done_ids.push(_via_img_metadata[_via_image_id].groupedRegions.groupBy[rindex]); + let tmp = _via_img_metadata[_via_image_id].getGroupedRegion(_via_img_metadata[_via_image_id].groupedRegions.groupBy[rindex]); + for (const element of tmp) { + $(fragment).append( + this.annotation_editor_get_metadata_row_html(element) + ); + done_ids.push(element); + } + } + this.aec.append(fragment); + const row = $("<tr>", { + id: "ae_no_group", + style: "height: 40px;", + class: "align-bottom", + }); + const header = $("<th>", { + scope: "row", + id: "ae_no_group_rid", + html: "X", + }) + const cell = $("<td> ", { + id: "ae_row_no_group", + colspan: colspan, + html: "Other", + }); + row.append(header, cell); + $(fragment).append(row); + for (rindex = 0; rindex < _via_img_metadata[_via_image_id].regions.length; ++rindex) { + if (!done_ids.includes(rindex)) { + $(fragment).append( + this.annotation_editor_get_metadata_row_html(rindex) + ); } } + this.aec.append(fragment); + } else { + const fragment = document.createDocumentFragment(); + for ( + rindex = 0; + rindex < _via_img_metadata[_via_image_id].regions.length; + ++rindex + ) { + $(fragment).append( + this.annotation_editor_get_metadata_row_html(rindex) + ); + } + this.aec.append(fragment); } } + } + } + } + + async annotation_editor_update_metadata_html() { + if (!_via_img_count) { + return; + } + + this.ensureTableBodyExists(); // experiment + + switch (_via_metadata_being_updated) { + case "region": + await this.updateRegionMetadata(); break; case "file": @@ -998,10 +1030,8 @@ class Sidebar { } annotation_editor_update_row(row_id) { - if (!this.ae.has("tbody").length) { - this.ae.append('<tbody id="annotation_editor_content"></tbody>'); - this.aec = $("#annotation_editor_content"); - } + + this.ensureTableBodyExists(); // experiment let new_row = this.annotation_editor_get_metadata_row_html(row_id); let id = new_row.attr("id"); @@ -1012,10 +1042,7 @@ class Sidebar { annotation_editor_add_row(row_id) { if (this.is_annotation_editor_visible()) { - if (!this.ae.has("tbody").length) { - this.ae.append('<tbody id="annotation_editor_content"></tbody>'); - this.aec = $("#annotation_editor_content"); - } + this.ensureTableBodyExists(); // experiment let new_row = this.annotation_editor_get_metadata_row_html(row_id); let penultimate_row_id = parseInt(row_id) - 1; if (penultimate_row_id >= 0) {