Merge branch 'remove-imjoy' into 'v3'
Remove old unmaintained components Closes #387 See merge request openflexure/openflexure-microscope-server!314
This commit is contained in:
commit
fd4d51401f
17 changed files with 28 additions and 1761 deletions
|
|
@ -2,4 +2,3 @@ NODE_ENV=development
|
|||
VUE_APP_MODE=development
|
||||
VUE_APP_PLATFORM=web
|
||||
VUE_APP_TARGET=web
|
||||
VUE_APP_ENABLE_IMJOY=true
|
||||
|
|
|
|||
|
|
@ -2,4 +2,3 @@ NODE_ENV=production
|
|||
VUE_APP_MODE=production
|
||||
VUE_APP_PLATFORM=web
|
||||
VUE_APP_TARGET=web
|
||||
VUE_APP_ENABLE_IMJOY=true
|
||||
|
|
|
|||
456
webapp/package-lock.json
generated
456
webapp/package-lock.json
generated
|
|
@ -9,7 +9,6 @@
|
|||
"version": "3.0.0-alpha1",
|
||||
"license": "GNU General Public License v3.0 ",
|
||||
"dependencies": {
|
||||
"imjoy-core": "^0.13",
|
||||
"material-design-icons": "^3.0",
|
||||
"material-symbols": "^0.14.3",
|
||||
"mousetrap": "^1.6.5",
|
||||
|
|
@ -34,9 +33,7 @@
|
|||
"prettier": "^1.19",
|
||||
"uikit": "^3.17",
|
||||
"vue": "^2.7",
|
||||
"vue-friendly-iframe": "^0.17",
|
||||
"vue-template-compiler": "^2.7",
|
||||
"vue-tour": "^1.6",
|
||||
"vuejs-paginate": "^2.1",
|
||||
"vuex": "^3.6"
|
||||
}
|
||||
|
|
@ -1445,11 +1442,6 @@
|
|||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/@socket.io/component-emitter": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz",
|
||||
"integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg=="
|
||||
},
|
||||
"node_modules/@soda/friendly-errors-webpack-plugin": {
|
||||
"version": "1.8.1",
|
||||
"resolved": "https://registry.npmjs.org/@soda/friendly-errors-webpack-plugin/-/friendly-errors-webpack-plugin-1.8.1.tgz",
|
||||
|
|
@ -2581,15 +2573,11 @@
|
|||
"node": ">= 10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/after": {
|
||||
"version": "0.8.2",
|
||||
"resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz",
|
||||
"integrity": "sha512-QbJ0NTQ/I9DI3uSJA4cbexiwQeRAfjPScqIbSjUDd9TOrcg6pTkdgziesOqxBMBzit8vFCTwrP27t13vFOORRA=="
|
||||
},
|
||||
"node_modules/ajv": {
|
||||
"version": "6.12.6",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
|
||||
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"fast-deep-equal": "^3.1.1",
|
||||
"fast-json-stable-stringify": "^2.0.0",
|
||||
|
|
@ -2731,15 +2719,11 @@
|
|||
"version": "1.0.10",
|
||||
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
|
||||
"integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"sprintf-js": "~1.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/argsarray": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/argsarray/-/argsarray-0.0.1.tgz",
|
||||
"integrity": "sha512-u96dg2GcAKtpTrBdDoFIM7PjcBA+6rSP0OR94MOReNRyUECL6MtQt5XXmRr4qrftYaef9+l5hcpO5te7sML1Cg=="
|
||||
},
|
||||
"node_modules/arr-diff": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz",
|
||||
|
|
@ -2856,11 +2840,6 @@
|
|||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/arraybuffer.slice": {
|
||||
"version": "0.0.7",
|
||||
"resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz",
|
||||
"integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog=="
|
||||
},
|
||||
"node_modules/asn1": {
|
||||
"version": "0.2.6",
|
||||
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz",
|
||||
|
|
@ -3038,6 +3017,7 @@
|
|||
"version": "0.21.4",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz",
|
||||
"integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"follow-redirects": "^1.14.0"
|
||||
}
|
||||
|
|
@ -3146,11 +3126,6 @@
|
|||
"@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/backo2": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz",
|
||||
"integrity": "sha512-zj6Z6M7Eq+PBZ7PQxl5NT665MvJdAkzp0f60nAJ+sLaSCBPMwVak5ZegFbgVCzFcCJTKFoMizvM5Ld7+JrRJHA=="
|
||||
},
|
||||
"node_modules/balanced-match": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||
|
|
@ -3187,14 +3162,6 @@
|
|||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/base64-arraybuffer": {
|
||||
"version": "0.1.4",
|
||||
"resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.4.tgz",
|
||||
"integrity": "sha512-a1eIFi4R9ySrbiMuyTGx5e92uRH5tQY6kArNcFaKBUleIoLjdjBg7Zxm3Mqm3Kmkf27HLR/1fnxX9q8GQ7Iavg==",
|
||||
"engines": {
|
||||
"node": ">= 0.6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/base64-js": {
|
||||
"version": "1.5.1",
|
||||
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
|
||||
|
|
@ -3274,11 +3241,6 @@
|
|||
"file-uri-to-path": "1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/blob": {
|
||||
"version": "0.0.5",
|
||||
"resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz",
|
||||
"integrity": "sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig=="
|
||||
},
|
||||
"node_modules/bluebird": {
|
||||
"version": "3.7.2",
|
||||
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
|
||||
|
|
@ -4281,24 +4243,15 @@
|
|||
"integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/component-bind": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz",
|
||||
"integrity": "sha512-WZveuKPeKAG9qY+FkYDeADzdHyTYdIboXS59ixDeRJL5ZhxpqUnxSOwop4FQjMsiYm3/Or8cegVbpAHNA7pHxw=="
|
||||
},
|
||||
"node_modules/component-emitter": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.1.tgz",
|
||||
"integrity": "sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==",
|
||||
"dev": true,
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/component-inherit": {
|
||||
"version": "0.0.3",
|
||||
"resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz",
|
||||
"integrity": "sha512-w+LhYREhatpVqTESyGFg3NlP6Iu0kEKUHETY9GoZP/pQyW4mHFZuFWRUCIqVPZ36ueVLtoOEZaAqbCF2RDndaA=="
|
||||
},
|
||||
"node_modules/compressible": {
|
||||
"version": "2.0.18",
|
||||
"resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz",
|
||||
|
|
@ -5131,6 +5084,7 @@
|
|||
"version": "4.3.4",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
||||
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"ms": "2.1.2"
|
||||
},
|
||||
|
|
@ -5642,11 +5596,6 @@
|
|||
"url": "https://github.com/fb55/domhandler?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/dompurify": {
|
||||
"version": "2.4.7",
|
||||
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.4.7.tgz",
|
||||
"integrity": "sha512-kxxKlPEDa6Nc5WJi+qRgPbOAbgTpSULL+vI3NUXsZMlkJxTqYI9wg5ZTay2sFrdZRWHPWNi+EdAhcJf81WtoMQ=="
|
||||
},
|
||||
"node_modules/domutils": {
|
||||
"version": "2.8.0",
|
||||
"resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz",
|
||||
|
|
@ -5801,49 +5750,6 @@
|
|||
"once": "^1.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/engine.io-client": {
|
||||
"version": "3.5.3",
|
||||
"resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.5.3.tgz",
|
||||
"integrity": "sha512-qsgyc/CEhJ6cgMUwxRRtOndGVhIu5hpL5tR4umSpmX/MvkFoIxUTM7oFMDQumHNzlNLwSVy6qhstFPoWTf7dOw==",
|
||||
"dependencies": {
|
||||
"component-emitter": "~1.3.0",
|
||||
"component-inherit": "0.0.3",
|
||||
"debug": "~3.1.0",
|
||||
"engine.io-parser": "~2.2.0",
|
||||
"has-cors": "1.1.0",
|
||||
"indexof": "0.0.1",
|
||||
"parseqs": "0.0.6",
|
||||
"parseuri": "0.0.6",
|
||||
"ws": "~7.4.2",
|
||||
"xmlhttprequest-ssl": "~1.6.2",
|
||||
"yeast": "0.1.2"
|
||||
}
|
||||
},
|
||||
"node_modules/engine.io-client/node_modules/debug": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
|
||||
"integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
|
||||
"dependencies": {
|
||||
"ms": "2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/engine.io-client/node_modules/ms": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
|
||||
},
|
||||
"node_modules/engine.io-parser": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.2.1.tgz",
|
||||
"integrity": "sha512-x+dN/fBH8Ro8TFwJ+rkB2AmuVw9Yu2mockR/p3W8f8YtExwFgDvBDi0GWyb4ZLkpahtDGZgtr3zLovanJghPqg==",
|
||||
"dependencies": {
|
||||
"after": "0.8.2",
|
||||
"arraybuffer.slice": "~0.0.7",
|
||||
"base64-arraybuffer": "0.1.4",
|
||||
"blob": "0.0.5",
|
||||
"has-binary2": "~1.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/enhanced-resolve": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz",
|
||||
|
|
@ -6318,6 +6224,7 @@
|
|||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
|
||||
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"esparse": "bin/esparse.js",
|
||||
"esvalidate": "bin/esvalidate.js"
|
||||
|
|
@ -6732,7 +6639,8 @@
|
|||
"node_modules/fast-deep-equal": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
||||
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
|
||||
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/fast-diff": {
|
||||
"version": "1.3.0",
|
||||
|
|
@ -6760,7 +6668,8 @@
|
|||
"node_modules/fast-json-stable-stringify": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
|
||||
"integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="
|
||||
"integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/fast-levenshtein": {
|
||||
"version": "2.0.6",
|
||||
|
|
@ -6856,11 +6765,6 @@
|
|||
"node": ">=4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/file-saver": {
|
||||
"version": "1.3.8",
|
||||
"resolved": "https://registry.npmjs.org/file-saver/-/file-saver-1.3.8.tgz",
|
||||
"integrity": "sha512-spKHSBQIxxS81N/O21WmuXA2F6wppUCsutpzenOeZzOCCJ5gEfcbqJP983IrpLXzYmXnMUa6J03SubcNPdKrlg=="
|
||||
},
|
||||
"node_modules/file-uri-to-path": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
|
||||
|
|
@ -7096,6 +7000,7 @@
|
|||
"version": "1.15.4",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.4.tgz",
|
||||
"integrity": "sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
|
|
@ -7581,24 +7486,6 @@
|
|||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/has-binary2": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.3.tgz",
|
||||
"integrity": "sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw==",
|
||||
"dependencies": {
|
||||
"isarray": "2.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/has-binary2/node_modules/isarray": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz",
|
||||
"integrity": "sha512-c2cu3UxbI+b6kR3fy0nRnAhodsvR9dx7U5+znCOzdj6IfP3upFURTr0Xl5BlQZNKZjEtxrmVyfSdeE3O57smoQ=="
|
||||
},
|
||||
"node_modules/has-cors": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz",
|
||||
"integrity": "sha512-g5VNKdkFuUuVCP9gYfDJHjK2nqdQJ7aDLTnycnc2+RvsOQbuLdF5pm7vuE5J76SEBIQjs4kQY/BWq74JUmjbXA=="
|
||||
},
|
||||
"node_modules/has-flag": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
|
||||
|
|
@ -8182,112 +8069,6 @@
|
|||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/imjoy-core": {
|
||||
"version": "0.13.82",
|
||||
"resolved": "https://registry.npmjs.org/imjoy-core/-/imjoy-core-0.13.82.tgz",
|
||||
"integrity": "sha512-uXf1YnWXfzQu/DluVfXQDdttEadDt81QOYEfVnRbxeNXV1xtYYpsQxdXCA3aiIju36Zvh/V3zQ4y4uTEQj00VQ==",
|
||||
"dependencies": {
|
||||
"ajv": "^6.9.1",
|
||||
"axios": "^0.21.1",
|
||||
"dompurify": "^2.0.8",
|
||||
"file-saver": "^1.3.3",
|
||||
"imjoy-rpc": "^0.3.16",
|
||||
"js-yaml": "^3.13.1",
|
||||
"lodash": "^4.17.15",
|
||||
"lz-string": "^1.4.4",
|
||||
"minibus": "^3.1.0",
|
||||
"pouchdb-browser": "^7.0.0",
|
||||
"socket.io-client": "^2.3.0",
|
||||
"spark-md5": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/imjoy-rpc": {
|
||||
"version": "0.3.42",
|
||||
"resolved": "https://registry.npmjs.org/imjoy-rpc/-/imjoy-rpc-0.3.42.tgz",
|
||||
"integrity": "sha512-DgkBKL33fkKDV3nPtMZHSJ1FBYr8oay9p6HkOxnKm/MB7IzEi5VJcQJIbyLc8IuDJEsTBCDguZdkGuBSeKKU/w==",
|
||||
"dependencies": {
|
||||
"socket.io-client": "^4.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/imjoy-rpc/node_modules/engine.io-client": {
|
||||
"version": "6.5.3",
|
||||
"resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.5.3.tgz",
|
||||
"integrity": "sha512-9Z0qLB0NIisTRt1DZ/8U2k12RJn8yls/nXMZLn+/N8hANT3TcYjKFKcwbw5zFQiN4NTde3TSY9zb79e1ij6j9Q==",
|
||||
"dependencies": {
|
||||
"@socket.io/component-emitter": "~3.1.0",
|
||||
"debug": "~4.3.1",
|
||||
"engine.io-parser": "~5.2.1",
|
||||
"ws": "~8.11.0",
|
||||
"xmlhttprequest-ssl": "~2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/imjoy-rpc/node_modules/engine.io-parser": {
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.1.tgz",
|
||||
"integrity": "sha512-9JktcM3u18nU9N2Lz3bWeBgxVgOKpw7yhRaoxQA3FUDZzzw+9WlA6p4G4u0RixNkg14fH7EfEc/RhpurtiROTQ==",
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/imjoy-rpc/node_modules/socket.io-client": {
|
||||
"version": "4.7.2",
|
||||
"resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.7.2.tgz",
|
||||
"integrity": "sha512-vtA0uD4ibrYD793SOIAwlo8cj6haOeMHrGvwPxJsxH7CeIksqJ+3Zc06RvWTIFgiSqx4A3sOnTXpfAEE2Zyz6w==",
|
||||
"dependencies": {
|
||||
"@socket.io/component-emitter": "~3.1.0",
|
||||
"debug": "~4.3.2",
|
||||
"engine.io-client": "~6.5.2",
|
||||
"socket.io-parser": "~4.2.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/imjoy-rpc/node_modules/socket.io-parser": {
|
||||
"version": "4.2.4",
|
||||
"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz",
|
||||
"integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==",
|
||||
"dependencies": {
|
||||
"@socket.io/component-emitter": "~3.1.0",
|
||||
"debug": "~4.3.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/imjoy-rpc/node_modules/ws": {
|
||||
"version": "8.11.0",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz",
|
||||
"integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==",
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"bufferutil": "^4.0.1",
|
||||
"utf-8-validate": "^5.0.2"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"bufferutil": {
|
||||
"optional": true
|
||||
},
|
||||
"utf-8-validate": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/imjoy-rpc/node_modules/xmlhttprequest-ssl": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz",
|
||||
"integrity": "sha512-QKxVRxiRACQcVuQEYFsI1hhkrMlrXHPegbbd1yn9UHOmRxY+si12nQYzri3vbzt8VdTTRviqcKxcyllFas5z2A==",
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/immediate": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/immediate/-/immediate-3.3.0.tgz",
|
||||
"integrity": "sha512-HR7EVodfFUdQCTIeySw+WDRFJlPcLOJbXfwwZ7Oom6tjsvZ3bOkCDJHehQC3nxJrv7+f9XecwazynjU8e4Vw3Q=="
|
||||
},
|
||||
"node_modules/import-cwd": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/import-cwd/-/import-cwd-2.1.0.tgz",
|
||||
|
|
@ -8405,11 +8186,6 @@
|
|||
"integrity": "sha512-bup+4tap3Hympa+JBJUG7XuOsdNQ6fxt0MHyXMKuLBKn0OqsTfvUxkUrroEX1+B2VsSHvCjiIcZVxRtYa4nllA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/indexof": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz",
|
||||
"integrity": "sha512-i0G7hLJ1z0DE8dsqJa2rycj9dBmNKgXBvotXtZYXakU9oivfB9Uj2ZBC27qqef2U58/ZLwalxa1X/RDCdkHtVg=="
|
||||
},
|
||||
"node_modules/infer-owner": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz",
|
||||
|
|
@ -8429,7 +8205,8 @@
|
|||
"node_modules/inherits": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/inquirer": {
|
||||
"version": "7.3.3",
|
||||
|
|
@ -9283,6 +9060,7 @@
|
|||
"version": "3.14.1",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
|
||||
"integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"argparse": "^1.0.7",
|
||||
"esprima": "^4.0.0"
|
||||
|
|
@ -9330,7 +9108,8 @@
|
|||
"node_modules/json-schema-traverse": {
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
|
||||
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
|
||||
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/json-stable-stringify-without-jsonify": {
|
||||
"version": "1.0.1",
|
||||
|
|
@ -9380,12 +9159,6 @@
|
|||
"node": ">=0.6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/jump.js": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/jump.js/-/jump.js-1.0.2.tgz",
|
||||
"integrity": "sha512-oUkJJ/Y4ATU5qjkXBntCZSKctbSyS3ewe2jrLaUu/cc9jsQiAn0fnTUxQnZz3mJdDdem1Q279zrD6h3n+Cgxtg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/killable": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz",
|
||||
|
|
@ -9637,7 +9410,8 @@
|
|||
"node_modules/lodash": {
|
||||
"version": "4.17.21",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
||||
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
|
||||
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/lodash.debounce": {
|
||||
"version": "4.0.8",
|
||||
|
|
@ -9733,14 +9507,6 @@
|
|||
"yallist": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/lz-string": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz",
|
||||
"integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==",
|
||||
"bin": {
|
||||
"lz-string": "bin/bin.js"
|
||||
}
|
||||
},
|
||||
"node_modules/magic-string": {
|
||||
"version": "0.30.5",
|
||||
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.5.tgz",
|
||||
|
|
@ -10057,11 +9823,6 @@
|
|||
"node": ">= 4"
|
||||
}
|
||||
},
|
||||
"node_modules/minibus": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/minibus/-/minibus-3.1.0.tgz",
|
||||
"integrity": "sha512-VVhbxJ0DrlHepHS8a8vzGxPhZkBbX1Rjk0LU5gR7mEuDBD8+z8953+mMd/GQtntySTE1l7cOvKAqjEdodDIryQ=="
|
||||
},
|
||||
"node_modules/minimalistic-assert": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",
|
||||
|
|
@ -10181,7 +9942,8 @@
|
|||
"node_modules/ms": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/multicast-dns": {
|
||||
"version": "6.2.3",
|
||||
|
|
@ -11045,16 +10807,6 @@
|
|||
"integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/parseqs": {
|
||||
"version": "0.0.6",
|
||||
"resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.6.tgz",
|
||||
"integrity": "sha512-jeAGzMDbfSHHA091hr0r31eYfTig+29g3GKKE/PPbEQ65X0lmMwlEoqmhzu0iztID5uJpZsFlUPDP8ThPL7M8w=="
|
||||
},
|
||||
"node_modules/parseuri": {
|
||||
"version": "0.0.6",
|
||||
"resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.6.tgz",
|
||||
"integrity": "sha512-AUjen8sAkGgao7UyCX6Ahv0gIK2fABKmYjvP4xmy5JaKvcbTRueIqIPHLAfq30xJddqSE033IOMUSOMCcK3Sow=="
|
||||
},
|
||||
"node_modules/parseurl": {
|
||||
"version": "1.3.3",
|
||||
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
|
||||
|
|
@ -11325,17 +11077,6 @@
|
|||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/popper.js": {
|
||||
"version": "1.16.1",
|
||||
"resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1.tgz",
|
||||
"integrity": "sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ==",
|
||||
"deprecated": "You can find the new Popper v2 at @popperjs/core, this package is dedicated to the legacy v1",
|
||||
"dev": true,
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/popperjs"
|
||||
}
|
||||
},
|
||||
"node_modules/portfinder": {
|
||||
"version": "1.0.32",
|
||||
"resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.32.tgz",
|
||||
|
|
@ -12043,19 +11784,6 @@
|
|||
"integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/pouchdb-browser": {
|
||||
"version": "7.3.1",
|
||||
"resolved": "https://registry.npmjs.org/pouchdb-browser/-/pouchdb-browser-7.3.1.tgz",
|
||||
"integrity": "sha512-qZ8awkXl/woBHvEVqNHjDtwPDA7A9v4ItHtX1y1eVpKel4mlYqnIJ8K6pRcFUZmVaHinJW8K3uS32eHC1q0yOA==",
|
||||
"dependencies": {
|
||||
"argsarray": "0.0.1",
|
||||
"immediate": "3.3.0",
|
||||
"inherits": "2.0.4",
|
||||
"spark-md5": "3.0.2",
|
||||
"uuid": "8.3.2",
|
||||
"vuvuzela": "1.0.3"
|
||||
}
|
||||
},
|
||||
"node_modules/prelude-ls": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
|
||||
|
|
@ -12224,6 +11952,7 @@
|
|||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
|
||||
"integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
|
|
@ -13402,65 +13131,6 @@
|
|||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/socket.io-client": {
|
||||
"version": "2.5.0",
|
||||
"resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.5.0.tgz",
|
||||
"integrity": "sha512-lOO9clmdgssDykiOmVQQitwBAF3I6mYcQAo7hQ7AM6Ny5X7fp8hIJ3HcQs3Rjz4SoggoxA1OgrQyY8EgTbcPYw==",
|
||||
"dependencies": {
|
||||
"backo2": "1.0.2",
|
||||
"component-bind": "1.0.0",
|
||||
"component-emitter": "~1.3.0",
|
||||
"debug": "~3.1.0",
|
||||
"engine.io-client": "~3.5.0",
|
||||
"has-binary2": "~1.0.2",
|
||||
"indexof": "0.0.1",
|
||||
"parseqs": "0.0.6",
|
||||
"parseuri": "0.0.6",
|
||||
"socket.io-parser": "~3.3.0",
|
||||
"to-array": "0.1.4"
|
||||
}
|
||||
},
|
||||
"node_modules/socket.io-client/node_modules/debug": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
|
||||
"integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
|
||||
"dependencies": {
|
||||
"ms": "2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/socket.io-client/node_modules/ms": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
|
||||
},
|
||||
"node_modules/socket.io-parser": {
|
||||
"version": "3.3.3",
|
||||
"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.3.3.tgz",
|
||||
"integrity": "sha512-qOg87q1PMWWTeO01768Yh9ogn7chB9zkKtQnya41Y355S0UmpXgpcrFwAgjYJxu9BdKug5r5e9YtVSeWhKBUZg==",
|
||||
"dependencies": {
|
||||
"component-emitter": "~1.3.0",
|
||||
"debug": "~3.1.0",
|
||||
"isarray": "2.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/socket.io-parser/node_modules/debug": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
|
||||
"integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
|
||||
"dependencies": {
|
||||
"ms": "2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/socket.io-parser/node_modules/isarray": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz",
|
||||
"integrity": "sha512-c2cu3UxbI+b6kR3fy0nRnAhodsvR9dx7U5+znCOzdj6IfP3upFURTr0Xl5BlQZNKZjEtxrmVyfSdeE3O57smoQ=="
|
||||
},
|
||||
"node_modules/socket.io-parser/node_modules/ms": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
|
||||
},
|
||||
"node_modules/sockjs": {
|
||||
"version": "0.3.24",
|
||||
"resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz",
|
||||
|
|
@ -13576,11 +13246,6 @@
|
|||
"deprecated": "See https://github.com/lydell/source-map-url#deprecated",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/spark-md5": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/spark-md5/-/spark-md5-3.0.2.tgz",
|
||||
"integrity": "sha512-wcFzz9cDfbuqe0FZzfi2or1sgyIrsDwmPwfZC4hiNidPdPINjeUwNfv5kldczoEAcjl9Y1L3SM7Uz2PUEQzxQw=="
|
||||
},
|
||||
"node_modules/spdx-correct": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz",
|
||||
|
|
@ -13672,7 +13337,8 @@
|
|||
"node_modules/sprintf-js": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
|
||||
"integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g=="
|
||||
"integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/sshpk": {
|
||||
"version": "1.18.0",
|
||||
|
|
@ -14459,11 +14125,6 @@
|
|||
"node": ">=0.6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/to-array": {
|
||||
"version": "0.1.4",
|
||||
"resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz",
|
||||
"integrity": "sha512-LhVdShQD/4Mk4zXNroIQZJC+Ap3zgLcDuwEdcmLv9CCO73NWockQDwyUnW/m8VX/EElfL6FcYx7EeutN4HJA6A=="
|
||||
},
|
||||
"node_modules/to-arraybuffer": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz",
|
||||
|
|
@ -14988,6 +14649,7 @@
|
|||
"version": "4.4.1",
|
||||
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
|
||||
"integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"punycode": "^2.1.0"
|
||||
}
|
||||
|
|
@ -15160,6 +14822,7 @@
|
|||
"version": "8.3.2",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
|
||||
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"uuid": "dist/bin/uuid"
|
||||
}
|
||||
|
|
@ -15260,25 +14923,6 @@
|
|||
"eslint": ">=5.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/vue-friendly-iframe": {
|
||||
"version": "0.17.0",
|
||||
"resolved": "https://registry.npmjs.org/vue-friendly-iframe/-/vue-friendly-iframe-0.17.0.tgz",
|
||||
"integrity": "sha512-2IEHRpz2KIZ7wSXd3h1n6EEQ9HEU6GRC4DNdQ7w5Dm31Udf/xGjWfHErXJUsUw3Qal0fga8SrA6aOPTOX7mg+Q==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"uuid": "3.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/vue-friendly-iframe/node_modules/uuid": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz",
|
||||
"integrity": "sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g==",
|
||||
"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,
|
||||
"bin": {
|
||||
"uuid": "bin/uuid"
|
||||
}
|
||||
},
|
||||
"node_modules/vue-hot-reload-api": {
|
||||
"version": "2.3.4",
|
||||
"resolved": "https://registry.npmjs.org/vue-hot-reload-api/-/vue-hot-reload-api-2.3.4.tgz",
|
||||
|
|
@ -15500,18 +15144,6 @@
|
|||
"integrity": "sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/vue-tour": {
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/vue-tour/-/vue-tour-1.6.0.tgz",
|
||||
"integrity": "sha512-INVkuv3kIqulM3R90W1EF4XzFzOt34y6F0BEOunH+DcIwRVrWvBT/HXBu+Dq0RDJswxYbak2JQto58ep3rULRw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"hash-sum": "^2.0.0",
|
||||
"jump.js": "^1.0.2",
|
||||
"popper.js": "^1.16.0",
|
||||
"vue": "^2.6.10"
|
||||
}
|
||||
},
|
||||
"node_modules/vue/node_modules/@vue/compiler-sfc": {
|
||||
"version": "2.7.16",
|
||||
"resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-2.7.16.tgz",
|
||||
|
|
@ -15575,11 +15207,6 @@
|
|||
"vue": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/vuvuzela": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/vuvuzela/-/vuvuzela-1.0.3.tgz",
|
||||
"integrity": "sha512-Tm7jR1xTzBbPW+6y1tknKiEhz04Wf/1iZkcTJjSFcpNko43+dFW6+OOeQe9taJIug3NdfUAjFKgUSyQrIKaDvQ=="
|
||||
},
|
||||
"node_modules/watchpack": {
|
||||
"version": "1.7.5",
|
||||
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.5.tgz",
|
||||
|
|
@ -16545,34 +16172,6 @@
|
|||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/ws": {
|
||||
"version": "7.4.6",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz",
|
||||
"integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==",
|
||||
"engines": {
|
||||
"node": ">=8.3.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"bufferutil": "^4.0.1",
|
||||
"utf-8-validate": "^5.0.2"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"bufferutil": {
|
||||
"optional": true
|
||||
},
|
||||
"utf-8-validate": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/xmlhttprequest-ssl": {
|
||||
"version": "1.6.3",
|
||||
"resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.6.3.tgz",
|
||||
"integrity": "sha512-3XfeQE/wNkvrIktn2Kf0869fC0BN6UpydVasGIeSm2B1Llihf7/0UfZM+eCkOw3P7bP4+qPgqhm7ZoxuJtFU0Q==",
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/xtend": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
|
||||
|
|
@ -16691,11 +16290,6 @@
|
|||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/yeast": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz",
|
||||
"integrity": "sha512-8HFIh676uyGYP6wP13R/j6OJ/1HwJ46snpvzE7aHAN3Ryqh2yX6Xox2B4CUmTwwOIzlG3Bs7ocsP5dZH/R1Qbg=="
|
||||
},
|
||||
"node_modules/yorkie": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yorkie/-/yorkie-2.0.0.tgz",
|
||||
|
|
|
|||
|
|
@ -7,14 +7,11 @@
|
|||
"scripts": {
|
||||
"gv": "genversion src/version.js",
|
||||
"serve": "npm run gv && vue-cli-service serve --mode development",
|
||||
"serve-without-imjoy": "npm run gv && VUE_APP_ENABLE_IMJOY=false vue-cli-service serve --mode development",
|
||||
"build": "npm run gv && vue-cli-service build --openssl-legacy-provider --mode production",
|
||||
"build-without-imjoy": "npm run gv && VUE_APP_ENABLE_IMJOY=false vue-cli-service build --mode production",
|
||||
"lint": "vue-cli-service lint",
|
||||
"lint:fix": "vue-cli-service lint --fix"
|
||||
},
|
||||
"dependencies": {
|
||||
"imjoy-core": "^0.13",
|
||||
"material-design-icons": "^3.0",
|
||||
"material-symbols": "^0.14.3",
|
||||
"mousetrap": "^1.6.5",
|
||||
|
|
@ -39,9 +36,7 @@
|
|||
"prettier": "^1.19",
|
||||
"uikit": "^3.17",
|
||||
"vue": "^2.7",
|
||||
"vue-friendly-iframe": "^0.17",
|
||||
"vue-template-compiler": "^2.7",
|
||||
"vue-tour": "^1.6",
|
||||
"vuejs-paginate": "^2.1",
|
||||
"vuex": "^3.6"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,43 +0,0 @@
|
|||
<docs>
|
||||
[TODO: write documentation for this plugin.]
|
||||
</docs>
|
||||
|
||||
<config lang="json">
|
||||
{
|
||||
"name": "List services",
|
||||
"type": "web-worker",
|
||||
"tags": [],
|
||||
"ui": "",
|
||||
"version": "0.1.0",
|
||||
"cover": "",
|
||||
"description": "List the available ImJoy services in the console",
|
||||
"icon": "extension",
|
||||
"inputs": null,
|
||||
"outputs": null,
|
||||
"api_version": "0.1.8",
|
||||
"env": "",
|
||||
"permissions": [],
|
||||
"requirements": [],
|
||||
"dependencies": []
|
||||
}
|
||||
</config>
|
||||
|
||||
<script lang="javascript">
|
||||
class ImJoyPlugin {
|
||||
async setup() {
|
||||
api.log('initialized')
|
||||
}
|
||||
|
||||
async run(ctx) {
|
||||
// get a list of service
|
||||
const services = await api.getServices({name: "OpenFlexure"});
|
||||
console.log("OpenFlexure services:");
|
||||
console.log(services);
|
||||
const allservices = await api.getServices();
|
||||
console.log("All services:");
|
||||
console.log(allservices);
|
||||
}
|
||||
}
|
||||
|
||||
api.export(new ImJoyPlugin())
|
||||
</script>
|
||||
|
|
@ -1,131 +0,0 @@
|
|||
<config lang="json">
|
||||
{
|
||||
"name": "Script Editor",
|
||||
"type": "web-worker",
|
||||
"tags": [],
|
||||
"ui": "",
|
||||
"version": "0.1.0",
|
||||
"cover": "",
|
||||
"description": "A Script Editor for Controlling OpenFlexure Microscope with ImJoy",
|
||||
"icon": "extension",
|
||||
"inputs": null,
|
||||
"outputs": null,
|
||||
"api_version": "0.1.8",
|
||||
"env": "",
|
||||
"permissions": [],
|
||||
"requirements": [],
|
||||
"dependencies": []
|
||||
}
|
||||
</config>
|
||||
|
||||
<script lang="javascript">
|
||||
class ImJoyPlugin {
|
||||
async setup() {
|
||||
api.log('initialized')
|
||||
}
|
||||
|
||||
async run(ctx) {
|
||||
let pluginInEditor, stopped, editorWindow;
|
||||
const config = {lang: 'javascript'}
|
||||
config.templates = [
|
||||
{
|
||||
name: "New",
|
||||
url: null,
|
||||
lang: 'javascript',
|
||||
},
|
||||
{
|
||||
name: "Snap Image Template",
|
||||
url: "./OpenFlexureSnapImageTemplate.imjoy.html",
|
||||
lang: "html",
|
||||
}
|
||||
]
|
||||
config.ui_elements = {
|
||||
save: {
|
||||
_rintf: true,
|
||||
type: 'button',
|
||||
label: "Save",
|
||||
visible: false,
|
||||
icon: "content-save",
|
||||
callback(content) {
|
||||
console.log(content)
|
||||
}
|
||||
},
|
||||
run: {
|
||||
_rintf: true,
|
||||
type: 'button',
|
||||
label: "Run",
|
||||
icon: "play",
|
||||
visible: true,
|
||||
shortcut: 'Shift-Enter',
|
||||
async callback(content) {
|
||||
try {
|
||||
editorWindow.setLoader(true);
|
||||
editorWindow.updateUIElement('stop', {
|
||||
visible: true
|
||||
})
|
||||
api.showProgress(0);
|
||||
pluginInEditor = await api.getPlugin({src: content, hot_reloading: true})
|
||||
|
||||
if (stopped) {
|
||||
pluginInEditor = null;
|
||||
return;
|
||||
}
|
||||
if (pluginInEditor && pluginInEditor.run) {
|
||||
return await pluginInEditor.run({
|
||||
config: {},
|
||||
data: {}
|
||||
});
|
||||
}
|
||||
if (stopped) {
|
||||
pluginInEditor = null;
|
||||
return;
|
||||
}
|
||||
} catch (e) {
|
||||
api.showMessage("Failed to load plugin, error: " + e.toString());
|
||||
} finally {
|
||||
editorWindow.updateUIElement('stop', {
|
||||
visible: false
|
||||
})
|
||||
editorWindow.setLoader(false);
|
||||
api.showProgress(100);
|
||||
}
|
||||
}
|
||||
},
|
||||
stop: {
|
||||
_rintf: true,
|
||||
type: 'button',
|
||||
label: "Stop",
|
||||
style: "color: #ff0080cf;",
|
||||
icon: "stop",
|
||||
visible: false,
|
||||
async callback() {
|
||||
stopped = true;
|
||||
await editorWindow.setLoader(false);
|
||||
await editorWindow.updateUIElement('stop', {
|
||||
visible: false
|
||||
})
|
||||
}
|
||||
},
|
||||
export: {
|
||||
_rintf: true,
|
||||
type: 'button',
|
||||
label: "Export",
|
||||
icon: "file-download-outline",
|
||||
visible: true,
|
||||
async callback(content) {
|
||||
const fileName = (pluginInEditor && pluginInEditor.config.name && pluginInEditor.config.name + '.imjoy.html') || config.name + '.imjoy.html' || "myPlugin.imjoy.html";
|
||||
await api.exportFile(content, fileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
editorWindow = await api.createWindow({
|
||||
src: 'https://if.imjoy.io',
|
||||
name: (ctx && ctx.data && ctx.data.name) ||'OpenFlexure Script Editor',
|
||||
config,
|
||||
data: {code: ctx && ctx.data && ctx.data.code}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
api.export(new ImJoyPlugin())
|
||||
</script>
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
<docs>
|
||||
[TODO: write documentation for this plugin.]
|
||||
</docs>
|
||||
|
||||
<config lang="json">
|
||||
{
|
||||
"name": "OpenFlexureSnapImageTemplate",
|
||||
"type": "web-worker",
|
||||
"tags": [],
|
||||
"ui": "",
|
||||
"version": "0.1.0",
|
||||
"cover": "",
|
||||
"description": "[TODO: describe this plugin with one sentence.]",
|
||||
"icon": "extension",
|
||||
"inputs": null,
|
||||
"outputs": null,
|
||||
"api_version": "0.1.8",
|
||||
"env": "",
|
||||
"permissions": [],
|
||||
"requirements": [],
|
||||
"dependencies": []
|
||||
}
|
||||
</config>
|
||||
|
||||
<script lang="javascript">
|
||||
class ImJoyPlugin {
|
||||
async setup() {
|
||||
api.log('initialized')
|
||||
}
|
||||
|
||||
async run(ctx) {
|
||||
// get a list of service
|
||||
const services = await api.getServices({name: "OpenFlexure"});
|
||||
// get the first service
|
||||
const ofm = services[0];
|
||||
// snap an image
|
||||
await ofm.snapImage();
|
||||
console.log("snapped an image");
|
||||
}
|
||||
}
|
||||
|
||||
api.export(new ImJoyPlugin())
|
||||
</script>
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
<docs>
|
||||
[TODO: write documentation for this plugin.]
|
||||
</docs>
|
||||
|
||||
<config lang="json">
|
||||
{
|
||||
"name": "Test OFM Stage",
|
||||
"type": "web-worker",
|
||||
"tags": [],
|
||||
"ui": "",
|
||||
"version": "0.1.0",
|
||||
"cover": "",
|
||||
"description": "Move the OFM stage to test the API works",
|
||||
"icon": "extension",
|
||||
"inputs": null,
|
||||
"outputs": null,
|
||||
"api_version": "0.1.8",
|
||||
"env": "",
|
||||
"permissions": [],
|
||||
"requirements": [],
|
||||
"dependencies": []
|
||||
}
|
||||
</config>
|
||||
|
||||
<script lang="javascript">
|
||||
class ImJoyPlugin {
|
||||
async setup() {
|
||||
api.log('initialized')
|
||||
}
|
||||
|
||||
async run(ctx) {
|
||||
// get a list of service
|
||||
const services = await api.getServices({name: "OpenFlexure"});
|
||||
// get the first service
|
||||
const ofm = services[0];
|
||||
// snap an image
|
||||
const start = await ofm.getXYZPosition();
|
||||
console.log(`Starting position: ${start}`);
|
||||
// move the Z axis up and down
|
||||
await ofm.setPosition(start[2] + 100);
|
||||
console.log(`Moved Z to ${await ofm.getPosition()}`);
|
||||
await ofm.setPosition(start[2]);
|
||||
console.log(`Moved Z to ${await ofm.getPosition()}`);
|
||||
await ofm.fullFocus();
|
||||
console.log("Ran a full autofocus");
|
||||
}
|
||||
}
|
||||
|
||||
api.export(new ImJoyPlugin())
|
||||
</script>
|
||||
|
|
@ -5,7 +5,6 @@
|
|||
:class="handleTheme"
|
||||
>
|
||||
<loadingContent v-if="!$store.getters.ready" />
|
||||
<div v-if="$store.getters.ready" id="tour-header"></div>
|
||||
<appContent v-if="$store.getters.ready" />
|
||||
<!-- Runtime modals -->
|
||||
<div
|
||||
|
|
@ -27,13 +26,6 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<v-tour
|
||||
v-show="$store.getters.ready"
|
||||
name="guidedTour"
|
||||
:steps="tourSteps"
|
||||
:callbacks="tourCallbacks"
|
||||
:options="{ highlight: true }"
|
||||
></v-tour>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
@ -79,12 +71,7 @@ export default {
|
|||
arrowKeysDown: {},
|
||||
keyboardManual: [],
|
||||
systemDark: undefined,
|
||||
themeObserver: undefined,
|
||||
tourCallbacks: {
|
||||
onStop: () => {
|
||||
this.setLocalStorageObj("completedTour", true);
|
||||
}
|
||||
}
|
||||
themeObserver: undefined
|
||||
};
|
||||
},
|
||||
|
||||
|
|
@ -112,68 +99,6 @@ export default {
|
|||
"uk-light": isDark,
|
||||
"uk-background-secondary": isDark
|
||||
};
|
||||
},
|
||||
tourSteps: function() {
|
||||
let tabPopperParams = {
|
||||
modifiers: {
|
||||
preventOverflow: {
|
||||
boundariesElement: "window"
|
||||
}
|
||||
},
|
||||
placement: "right"
|
||||
};
|
||||
return [
|
||||
{
|
||||
target: "#tour-header", // We're using document.querySelector() under the hood
|
||||
header: {
|
||||
title: "Welcome to the OpenFlexure Microscope"
|
||||
},
|
||||
content: `Click Next to learn how to use your microscope`,
|
||||
params: {
|
||||
placement: "bottom"
|
||||
}
|
||||
},
|
||||
{
|
||||
target: "#gallery-tab-icon",
|
||||
header: {
|
||||
title: "Capture gallery"
|
||||
},
|
||||
content: `View and download your microscope images from the gallery tab`,
|
||||
params: tabPopperParams
|
||||
},
|
||||
{
|
||||
target: "#navigate-tab-icon",
|
||||
header: {
|
||||
title: "Navigate around your sample"
|
||||
},
|
||||
content: `Move your microscope stage and perform autofocus from the navigate tab`,
|
||||
params: tabPopperParams
|
||||
},
|
||||
{
|
||||
target: "#capture-tab-icon",
|
||||
header: {
|
||||
title: "Capture microscope images"
|
||||
},
|
||||
content: `Take images and simple tile scans from the capture tab`,
|
||||
params: tabPopperParams
|
||||
},
|
||||
{
|
||||
target: "#settings-tab-icon",
|
||||
header: {
|
||||
title: "Change settings"
|
||||
},
|
||||
content: `Change app and microscope settings, including microscope calibration, from the settings tab`,
|
||||
params: tabPopperParams
|
||||
},
|
||||
{
|
||||
target: "#extension-tab-divider",
|
||||
header: {
|
||||
title: "Microscope extensions"
|
||||
},
|
||||
content: `Extensions installed on your microscope will appear below this line`,
|
||||
params: tabPopperParams
|
||||
}
|
||||
];
|
||||
}
|
||||
},
|
||||
|
||||
|
|
@ -194,12 +119,6 @@ export default {
|
|||
});
|
||||
// Check connection to API
|
||||
this.checkConnection();
|
||||
// Handle guided tour
|
||||
// If the user has already completed or skipped the guided tour
|
||||
var completedTour = this.getLocalStorageObj("completedTour") || true;
|
||||
if (!completedTour) {
|
||||
this.$tours["guidedTour"].start();
|
||||
}
|
||||
},
|
||||
|
||||
created: function() {
|
||||
|
|
@ -443,57 +362,4 @@ html {
|
|||
overflow-y: hidden;
|
||||
}
|
||||
|
||||
// Style tour
|
||||
.v-tour__target--highlighted {
|
||||
box-shadow: 0px 40px 200px 30px rgba(0, 0, 0, 0.5),
|
||||
0px 0px 0px 4px rgba(128, 128, 128, 0.5) !important;
|
||||
border-radius: 5px;
|
||||
opacity: 100% !important;
|
||||
pointer-events: none !important;
|
||||
}
|
||||
|
||||
.v-step {
|
||||
background: @global-primary-background !important;
|
||||
}
|
||||
|
||||
.v-step__header {
|
||||
background-color: darken(@global-primary-background, 7%) !important;
|
||||
}
|
||||
|
||||
.v-step__button {
|
||||
font-size: 0.9rem !important;
|
||||
}
|
||||
|
||||
// Change step arrow colour
|
||||
// This is awful and hacky and makes me sad, but needs must
|
||||
.v-step .v-step__arrow {
|
||||
border-color: darken(@global-primary-background, 7%) !important;
|
||||
&--dark {
|
||||
border-color: darken(@global-primary-background, 7%) !important;
|
||||
}
|
||||
}
|
||||
|
||||
.v-step[x-placement^="top"] .v-step__arrow {
|
||||
border-left-color: transparent !important;
|
||||
border-right-color: transparent !important;
|
||||
border-bottom-color: transparent !important;
|
||||
}
|
||||
|
||||
.v-step[x-placement^="bottom"] .v-step__arrow {
|
||||
border-left-color: transparent !important;
|
||||
border-right-color: transparent !important;
|
||||
border-top-color: transparent !important;
|
||||
}
|
||||
|
||||
.v-step[x-placement^="right"] .v-step__arrow {
|
||||
border-left-color: transparent !important;
|
||||
border-top-color: transparent !important;
|
||||
border-bottom-color: transparent !important;
|
||||
}
|
||||
|
||||
.v-step[x-placement^="left"] .v-step__arrow {
|
||||
border-top-color: transparent !important;
|
||||
border-right-color: transparent !important;
|
||||
border-bottom-color: transparent !important;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -40,25 +40,6 @@
|
|||
<hr v-if="item.divide" :key="'tab-divider-' + index" />
|
||||
</template>
|
||||
|
||||
<tabIcon
|
||||
v-for="imjoyTab in imjoyTabs"
|
||||
:key="imjoyTab.id"
|
||||
:tab-i-d="'ImJoy-Plugin-' + imjoyTab.id"
|
||||
:title="imjoyTab.name"
|
||||
:require-connection="false"
|
||||
:current-tab="currentTab"
|
||||
@set-tab="setTab"
|
||||
>
|
||||
<img
|
||||
v-if="imjoyTab.iconURL"
|
||||
style="filter: grayscale(100%);width: 22px;margin-top: 5px;margin-bottom: 8px;"
|
||||
:src="imjoyTab.iconURL"
|
||||
/>
|
||||
<span v-if="!imjoyTab.iconURL" class="material-symbols-outlined">
|
||||
{{ imjoyTab.iconName || "extension" }}
|
||||
</span>
|
||||
</tabIcon>
|
||||
|
||||
<hr id="extension-tab-divider" />
|
||||
|
||||
<!-- For each bottom tab -->
|
||||
|
|
@ -98,15 +79,6 @@
|
|||
<component :is="item.component"></component>
|
||||
</tabContent>
|
||||
|
||||
<tabContent
|
||||
v-for="imjoyTab in imjoyTabs"
|
||||
:key="imjoyTab.id"
|
||||
:tab-i-d="'ImJoy-Plugin-' + imjoyTab.id"
|
||||
:require-connection="false"
|
||||
:current-tab="currentTab"
|
||||
>
|
||||
<div :id="imjoyTab.window_id" class="window-container">Loading...</div>
|
||||
</tabContent>
|
||||
|
||||
<!-- For each bottom tab -->
|
||||
<tabContent
|
||||
|
|
@ -124,7 +96,6 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { mapState } from "vuex";
|
||||
|
||||
// Import generic components
|
||||
import tabIcon from "./genericComponents/tabIcon";
|
||||
|
|
@ -139,11 +110,6 @@ import settingsContent from "./tabContentComponents/settingsContent.vue";
|
|||
import aboutContent from "./tabContentComponents/aboutContent.vue";
|
||||
import loggingContent from "./tabContentComponents/loggingContent.vue";
|
||||
import powerContent from "./tabContentComponents/powerContent.vue";
|
||||
// ImJoy is loaded asynchronously to allow it to be disabled if needed
|
||||
const imjoyContent = () =>
|
||||
import(
|
||||
/* webpackChunkName: "imjoy" */ "./tabContentComponents/imjoyContent.vue"
|
||||
);
|
||||
|
||||
// Import modal components for device initialisation
|
||||
import calibrationModal from "./modalComponents/calibrationModal.vue";
|
||||
|
|
@ -166,7 +132,6 @@ export default {
|
|||
loggingContent,
|
||||
TabIcon,
|
||||
powerContent,
|
||||
imjoyContent
|
||||
},
|
||||
data: function() {
|
||||
return {
|
||||
|
|
@ -240,24 +205,12 @@ export default {
|
|||
if (!this.$store.state.galleryEnabled) {
|
||||
tabs = tabs.filter(tab => tab.id != "gallery");
|
||||
}
|
||||
if (this.$store.state.imjoyEnabled) {
|
||||
tabs.push({
|
||||
id: "imjoy",
|
||||
iconURL: "https://imjoy.io/static/img/imjoy-icon.svg",
|
||||
component: imjoyContent,
|
||||
divide: true
|
||||
});
|
||||
}
|
||||
return tabs;
|
||||
},
|
||||
|
||||
currentTabIndex: function() {
|
||||
return this.tabOrder.indexOf(this.currentTab);
|
||||
},
|
||||
|
||||
// Map the tabs from ImJoy's store module so we can display them
|
||||
...mapState("imjoy", { imjoyTabs: "tabs" }),
|
||||
...mapState({ imjoyEnabled: "imjoyEnabled" })
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
|
|
|
|||
|
|
@ -62,10 +62,6 @@ export default {
|
|||
this.$store.commit("changeOrigin", this.newOrigin);
|
||||
event.preventDefault();
|
||||
}
|
||||
},
|
||||
resetTour: function() {
|
||||
// Make the introduction tour run next time the app loads
|
||||
this.setLocalStorageObj("completedTour", false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,25 +0,0 @@
|
|||
<template>
|
||||
<!-- Grid managing tab content -->
|
||||
<div uk-grid class="uk-height-1-1 uk-margin-remove uk-padding-remove">
|
||||
<div class="control-component">
|
||||
<paneCapture />
|
||||
</div>
|
||||
<div class="view-component uk-width-expand">
|
||||
<streamDisplay />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import paneCapture from "./captureComponents/paneCapture";
|
||||
import streamDisplay from "./streamContent.vue";
|
||||
|
||||
export default {
|
||||
name: "CaptureContent",
|
||||
|
||||
components: {
|
||||
paneCapture,
|
||||
streamDisplay
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
@ -1,58 +0,0 @@
|
|||
<template>
|
||||
<!-- Grid managing tab content -->
|
||||
<div uk-grid class="uk-height-1-1 uk-margin-remove uk-padding-remove">
|
||||
<div class="control-component">
|
||||
<vue-friendly-iframe v-if="frame" :src="frame.href"></vue-friendly-iframe>
|
||||
<!-- OpenFlexure Forms used to be handled here - should now be done another way. -->
|
||||
</div>
|
||||
<div class="view-component uk-width-expand">
|
||||
<galleryContent v-if="viewPanel == 'gallery'" />
|
||||
<settingsContent v-else-if="viewPanel == 'settings'" />
|
||||
<streamDisplay v-else />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import streamDisplay from "./streamContent.vue";
|
||||
import galleryContent from "../tabContentComponents/galleryContent.vue";
|
||||
import settingsContent from "../tabContentComponents/settingsContent.vue";
|
||||
|
||||
export default {
|
||||
name: "ExtensionContent",
|
||||
|
||||
components: {
|
||||
streamDisplay,
|
||||
galleryContent,
|
||||
settingsContent
|
||||
},
|
||||
|
||||
props: {
|
||||
forms: {
|
||||
type: Array,
|
||||
required: false,
|
||||
default: () => []
|
||||
},
|
||||
frame: {
|
||||
type: Object,
|
||||
required: false,
|
||||
default: null
|
||||
},
|
||||
viewPanel: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: "stream"
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.vue-friendly-iframe {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.vue-friendly-iframe iframe {
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,62 +0,0 @@
|
|||
<template>
|
||||
<div
|
||||
class="uk-card uk-card-hover uk-card-small uk-card-default uk-margin"
|
||||
:class="{ 'uk-card-secondary': $store.state.darkMode }"
|
||||
>
|
||||
<div class="uk-card-body">
|
||||
<div class="uk-grid-small uk-flex-middle" uk-grid>
|
||||
<div class="uk-width-auto">
|
||||
<img
|
||||
v-if="iconURL"
|
||||
style="height:50px"
|
||||
:data-src="iconURL"
|
||||
:alt="name + ' icon'"
|
||||
uk-img
|
||||
/>
|
||||
<span
|
||||
v-if="!iconURL"
|
||||
class="material-symbols-outlined"
|
||||
style="font-size:50px"
|
||||
>
|
||||
{{ iconName }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="uk-width-expand">
|
||||
<h3 class="uk-card-title uk-margin-remove-bottom">{{ name }}</h3>
|
||||
<p class="uk-text-meta uk-margin-remove-top">
|
||||
<slot name="subtitle"></slot>
|
||||
</p>
|
||||
</div>
|
||||
<div class="uk-width-auto">
|
||||
<button class="uk-button" @click="$emit('click')">
|
||||
<slot name="buttonText">Launch</slot>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<slot></slot>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "ImjoyPluginCard",
|
||||
|
||||
props: {
|
||||
name: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
iconURL: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: () => ""
|
||||
},
|
||||
iconName: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: () => "extension"
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
@ -1,644 +0,0 @@
|
|||
<template>
|
||||
<!-- Grid managing tab content -->
|
||||
<div class="uk-height-1-1 view-component">
|
||||
<progress
|
||||
ref="imjoyProgressbar"
|
||||
style="height: 4px; margin-bottom:0!important"
|
||||
class="uk-progress"
|
||||
max="100"
|
||||
></progress>
|
||||
|
||||
<div
|
||||
class="uk-flex uk-flex-column uk-margin uk-margin-left uk-margin-right"
|
||||
>
|
||||
<imjoy-plugin-card
|
||||
name="Load From URL"
|
||||
icon-u-r-l="https://imjoy.io/static/img/imjoy-icon.svg"
|
||||
@click="loadPluginDialog()"
|
||||
>
|
||||
<template v-slot:buttonText>Open</template>
|
||||
</imjoy-plugin-card>
|
||||
<imjoy-plugin-card
|
||||
name="ImageJ.JS"
|
||||
icon-u-r-l="https://ij.imjoy.io/assets/icons/chrome/chrome-installprocess-128-128.png"
|
||||
@click="openImageJ()"
|
||||
/>
|
||||
<imjoy-plugin-card
|
||||
name="Kaibu"
|
||||
icon-u-r-l="https://kaibu.org/static/img/kaibu-icon.svg"
|
||||
@click="startKaibu()"
|
||||
/>
|
||||
<imjoy-plugin-card
|
||||
v-for="(p, name) in loadedPlugins"
|
||||
:key="p.id"
|
||||
:name="name"
|
||||
icon-name="extension"
|
||||
@click="runPlugin(p)"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div v-show="loading" class="progress uk-margin-small">
|
||||
<div class="indeterminate"></div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as imjoyCore from "imjoy-core";
|
||||
import axios from "axios";
|
||||
import UIkit from "uikit";
|
||||
import { mapState } from "vuex";
|
||||
import ImjoyPluginCard from "./imjoyComponents/imjoyPluginCard.vue";
|
||||
|
||||
// TODO: move this to a module or something...
|
||||
async function pollAction(response) {
|
||||
// Poll an action until its status is completed
|
||||
// TODO: raise an error if it fails or is cancelled
|
||||
// For ease, this accepts and returns a response object from
|
||||
// axios.get
|
||||
// FIXME: this could be an infinite loop if the task is cancelled/errored
|
||||
let r = response;
|
||||
while ((r.data.status == "running") | (r.data.status == "pending")) {
|
||||
await new Promise(resolve => setTimeout(resolve, 100));
|
||||
r = await axios.get(r.data.href);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new Image element and wait for it to load.
|
||||
*
|
||||
* This returns a Promise, so you can "await" the image
|
||||
* element rather than needing to add a callback.
|
||||
*/
|
||||
function loadImageFromUrl(src) {
|
||||
// Create an Image, and return it once it has loaded
|
||||
// see https://stackoverflow.com/a/66180709
|
||||
// no need to declare async, as it returns a Promise
|
||||
return new Promise((resolve, reject) => {
|
||||
const img = new Image();
|
||||
// We must set crossOrigin="anonymous" in order
|
||||
// to avoid security errors when we get the pixel
|
||||
// data
|
||||
img.crossOrigin = "anonymous";
|
||||
img.onload = () => resolve(img);
|
||||
img.onerror = reject;
|
||||
img.src = src;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve an image from a URL, and return the RGB data
|
||||
* in a format that can be cast to an ndarray
|
||||
*
|
||||
* This follows a slightly convoluted recipe, where we
|
||||
* "draw" the image, and then extract the pixels from the
|
||||
* 2D canvas.
|
||||
*/
|
||||
async function imageUrlToNdarray(url) {
|
||||
// see https://stackoverflow.com/questions/934012/get-image-data-url-in-javascript
|
||||
const img = await loadImageFromUrl(url);
|
||||
const canvas = document.createElement("canvas");
|
||||
canvas.width = img.width;
|
||||
canvas.height = img.height;
|
||||
const ctx = canvas.getContext("2d");
|
||||
ctx.drawImage(img, 0, 0, img.width, img.height);
|
||||
const imageData = ctx.getImageData(0, 0, img.width, img.height);
|
||||
const rgbaData = imageData.data; // This gets the RGBA values as an ArrayBuffer
|
||||
// convert RGBA to RGB
|
||||
const rgbData = new Uint8Array(new ArrayBuffer(img.height * img.width * 3));
|
||||
for (let i = 0; i < img.height; i++) {
|
||||
for (let j = 0; j < img.width; j++) {
|
||||
const pos = i * img.width + j;
|
||||
rgbData[pos * 3] = rgbaData[pos * 4];
|
||||
rgbData[pos * 3 + 1] = rgbaData[pos * 4 + 1];
|
||||
rgbData[pos * 3 + 2] = rgbaData[pos * 4 + 2];
|
||||
}
|
||||
}
|
||||
return {
|
||||
_rtype: "ndarray",
|
||||
_rdtype: "uint8",
|
||||
_rshape: [img.height, img.width, 3],
|
||||
_rvalue: rgbData.buffer
|
||||
};
|
||||
}
|
||||
|
||||
export default {
|
||||
name: "ImJoyContent",
|
||||
|
||||
components: { ImjoyPluginCard },
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
loadedPlugins: {},
|
||||
viewers: {}
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
captureActionUri: function() {
|
||||
return `${this.$store.getters.baseUri}/api/v2/actions/camera/capture`;
|
||||
},
|
||||
snapshotStreamUri: function() {
|
||||
return `${this.$store.getters.baseUri}/api/v2/streams/snapshot`;
|
||||
},
|
||||
getPositionUri: function() {
|
||||
return `${this.$store.getters.baseUri}/api/v2/instrument/state/stage/position`;
|
||||
},
|
||||
moveActionUri: function() {
|
||||
return `${this.$store.getters.baseUri}/api/v2/actions/stage/move`;
|
||||
},
|
||||
baseUri: function() {
|
||||
return this.$store.getters.baseUri;
|
||||
},
|
||||
...mapState("imjoy", { windows: "tabs" })
|
||||
},
|
||||
mounted() {
|
||||
const self = this;
|
||||
const imjoy = new imjoyCore.ImJoy({
|
||||
// We will load the ImJoy plugin base frame via http (instead of https)
|
||||
// such that imjoy plugins can access insecured urls
|
||||
// however, some browser features won't work (e.g. webrtc)
|
||||
// unless we explicitly set `base_frame` in the plugin to
|
||||
// https://lib.imjoy.io/default_base_frame.html
|
||||
default_base_frame: "http://lib.imjoy.io/default_base_frame.html",
|
||||
imjoy_api: {
|
||||
async showDialog(plugin, config, exta_config) {
|
||||
return await imjoy.pm.createWindow(plugin, config, exta_config);
|
||||
},
|
||||
async showSnackbar(plugin, msg, duration) {
|
||||
duration = duration || 5;
|
||||
UIkit.notification.closeAll();
|
||||
UIkit.notification({
|
||||
message: msg.slice(0, 100),
|
||||
status: "primary",
|
||||
pos: "bottom-center",
|
||||
timeout: duration * 1000
|
||||
});
|
||||
},
|
||||
async showMessage(plugin, msg) {
|
||||
imjoy.imjoy_api.showSnackbar(plugin, msg, 5);
|
||||
},
|
||||
async showStatus(plugin, status) {
|
||||
imjoy.imjoy_api.showSnackbar(plugin, status, 5);
|
||||
},
|
||||
async showProgress(plugin, p) {
|
||||
p = p || 0;
|
||||
if (p < 1.0) p = p * 100;
|
||||
if (p > 100) p = 100;
|
||||
if (p) {
|
||||
self.$refs.imjoyProgressbar.style.display = "block";
|
||||
self.$refs.imjoyProgressbar.value = parseInt(p);
|
||||
} else {
|
||||
self.$refs.imjoyProgressbar.style.display = "none";
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
imjoy.start({ workspace: "default" }).then(async () => {
|
||||
console.log("ImJoy started");
|
||||
imjoy.event_bus.on("add_window", w => {
|
||||
this.addWindow(w);
|
||||
});
|
||||
this.setupMicroscopeAPI();
|
||||
this.setupViewers();
|
||||
const origin = window.location.origin;
|
||||
const localPlugins = [
|
||||
"OpenFlexureSnapImageTemplate",
|
||||
"OpenFlexureScriptEditor",
|
||||
"OpenFlexureTestMoveStage",
|
||||
"ListServices"
|
||||
];
|
||||
for (let fname of localPlugins) {
|
||||
await this.loadPlugin(`${origin}/${fname}.imjoy.html`);
|
||||
}
|
||||
this.setupPluginEngine();
|
||||
});
|
||||
this.imjoy = imjoy;
|
||||
},
|
||||
methods: {
|
||||
setupPluginEngine() {
|
||||
// setup a plugin engine for Python plugins
|
||||
this.imjoy.pm
|
||||
.reloadPluginRecursively({
|
||||
uri:
|
||||
"https://imjoy-team.github.io/jupyter-engine-manager/Jupyter-Engine-Manager.imjoy.html"
|
||||
})
|
||||
.then(enginePlugin => {
|
||||
// TODO: currently the url query are not preserved for ImJoy
|
||||
const queryString = window.location.search;
|
||||
const urlParams = new URLSearchParams(queryString);
|
||||
const engine = urlParams.get("engine");
|
||||
const spec = urlParams.get("spec");
|
||||
if (engine) {
|
||||
enginePlugin.api
|
||||
.createEngine({
|
||||
name: "MyCustomEngine",
|
||||
nbUrl: engine,
|
||||
url: engine.split("?")[0]
|
||||
})
|
||||
.then(() => {
|
||||
console.log("Jupyter Engine connected!");
|
||||
})
|
||||
.catch(e => {
|
||||
console.error("Failed to connect to Jupyter Engine", e);
|
||||
});
|
||||
} else {
|
||||
enginePlugin.api
|
||||
.createEngine({
|
||||
name: "MyBinder Engine",
|
||||
url: "https://mybinder.org",
|
||||
spec: spec || "oeway/imjoy-binder-image/master"
|
||||
})
|
||||
.then(() => {
|
||||
console.log("Binder Engine connected!");
|
||||
})
|
||||
.catch(e => {
|
||||
console.error("Failed to connect to MyBinder Engine", e);
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
async setupMicroscopeAPI() {
|
||||
// Here we register a set of API for controlling the microscope as a service
|
||||
// For interoperatability, it might be good to reuse a subset of the function names defined in MicroManager
|
||||
// See here: https://valelab4.ucsf.edu/~MM/doc/MMCore/html/class_c_m_m_core.html
|
||||
const snapshotUri = this.snapshotStreamUri;
|
||||
const captureActionUri = this.captureActionUri;
|
||||
const modalError = this.modalError;
|
||||
const getPositionAsObject = this.getStagePosition;
|
||||
const setPositionAsObject = this.setStagePosition;
|
||||
const getInstrumentSettings = this.getInstrumentSettings;
|
||||
const setInstrumentSettings = this.setInstrumentSettings;
|
||||
const runAutofocus = this.runAutofocus;
|
||||
|
||||
const service = {
|
||||
_rintf: true, // this will make sure the function can be called multiple times
|
||||
type: "#microscope-control",
|
||||
name: "OpenFlexure",
|
||||
lastSnapResponse: null,
|
||||
snapPreviewImage() {
|
||||
// The "proper" capture method is more involved - this one pulls a frame out of the preview stream
|
||||
return axios
|
||||
.get(snapshotUri)
|
||||
.then(response => {
|
||||
return response.data;
|
||||
})
|
||||
.catch(modalError);
|
||||
},
|
||||
snapImage() {
|
||||
// Do capture
|
||||
return axios.post(captureActionUri, {}).then(response => {
|
||||
service.lastSnapResponse = response;
|
||||
// TODO: send the events to flash the stream and update captures
|
||||
// Flash the stream (capture animation)
|
||||
//this.$root.$emit("globalFlashStream");
|
||||
// Update the global capture list
|
||||
//this.$root.$emit("globalUpdateCaptures");
|
||||
});
|
||||
//.catch(modalError);
|
||||
},
|
||||
async getImage() {
|
||||
// FIXME: handle nicely getImage() being called before snapImage()
|
||||
// Wait until the capture has completed and we can retrieve it
|
||||
service.lastSnapResponse = await pollAction(service.lastSnapResponse);
|
||||
let capture = service.lastSnapResponse.data.output;
|
||||
// TODO: check links.download.href exists and is JPEG
|
||||
let jpeg = await axios
|
||||
.get(capture.links.download.href, {
|
||||
responseType: "arraybuffer",
|
||||
headers: {
|
||||
"Content-Type": "image/jpeg"
|
||||
}
|
||||
})
|
||||
.then(r => r.data);
|
||||
console.log(
|
||||
"Downloaded ",
|
||||
jpeg.byteLength,
|
||||
" bytes of JPEG image data"
|
||||
);
|
||||
return jpeg; //TODO: what is the expected output format???
|
||||
},
|
||||
setPosition(z) {
|
||||
// The C api suggests this defaults to just Z, and can accept a "label" to
|
||||
// select the stage.
|
||||
return setPositionAsObject({
|
||||
z: z,
|
||||
absolute: true
|
||||
});
|
||||
},
|
||||
async getPosition() {
|
||||
const { z } = await getPositionAsObject();
|
||||
return z;
|
||||
},
|
||||
async setXYPosition(x, y) {
|
||||
return setPositionAsObject({
|
||||
x: x,
|
||||
y: y,
|
||||
absolute: true
|
||||
});
|
||||
},
|
||||
async getXYPosition() {
|
||||
const { x, y } = await getPositionAsObject();
|
||||
return [x, y];
|
||||
},
|
||||
async getXYZPosition() {
|
||||
const { x, y, z } = await getPositionAsObject();
|
||||
return [x, y, z];
|
||||
},
|
||||
async setXYZPosition(x, y, z) {
|
||||
return setPositionAsObject({
|
||||
x: x,
|
||||
y: y,
|
||||
z: z,
|
||||
absolute: true
|
||||
});
|
||||
},
|
||||
async getExposure() {
|
||||
const settings = await getInstrumentSettings();
|
||||
if (settings.camera.picamera) {
|
||||
if (settings.camera.picamera.shutter_speed) {
|
||||
return settings.camera.picamera.shutter_speed / 1000;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
},
|
||||
async setExposure(exposure) {
|
||||
setInstrumentSettings({
|
||||
camera: {
|
||||
picamera: {
|
||||
shutter_speed: exposure * 1000
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
async fullFocus() {
|
||||
return runAutofocus();
|
||||
}
|
||||
};
|
||||
const ref = await this.imjoy.pm.registerService(
|
||||
{ type: "#microscope-control", name: "OpenFlexure" },
|
||||
service
|
||||
);
|
||||
console.log("registered service");
|
||||
console.log(ref);
|
||||
},
|
||||
closeWindow(w) {
|
||||
if (w) {
|
||||
w.api.close();
|
||||
this.$store.commit("imjoy/removeTab", w);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Activate a window - you can pass the window object, its name, or its id.
|
||||
*/
|
||||
selectWindow(window) {
|
||||
for (let w of this.windows) {
|
||||
if ((w === window) | (w.name === window) | (w.id === window)) {
|
||||
// Make the relevant window visible by switching to its tab
|
||||
this.$root.$emit("globalSwitchTab", `ImJoy-Plugin-${w.id}`);
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
setWindowIconUrl(window, iconURL) {
|
||||
this.$store.commit("imjoy/setTabProperty", {
|
||||
tab: window,
|
||||
key: "iconURL",
|
||||
value: iconURL
|
||||
});
|
||||
},
|
||||
async startKaibu() {
|
||||
this.viewers.kaibu = await this.imjoy.pm.createWindow(null, {
|
||||
name: "Kaibu",
|
||||
src: "https://kaibu.org/#/app"
|
||||
});
|
||||
this.viewers.kaibu.on("close", () => {
|
||||
delete this.viewers.kaibu;
|
||||
});
|
||||
this.setWindowIconUrl(
|
||||
this.viewers.kaibu.config.id,
|
||||
"https://kaibu.org/static/img/kaibu-icon.svg"
|
||||
);
|
||||
this.viewers.kaibu.set_mode("full");
|
||||
},
|
||||
async startImageJ() {
|
||||
this.viewers.imagej = await this.imjoy.pm.createWindow(null, {
|
||||
name: "ImageJ.JS",
|
||||
src: "https://ij.imjoy.io"
|
||||
});
|
||||
this.viewers.imagej.on("close", () => {
|
||||
delete this.viewers.imagej;
|
||||
});
|
||||
this.setWindowIconUrl(
|
||||
this.viewers.imagej.config.id,
|
||||
"https://ij.imjoy.io/assets/icons/chrome/chrome-installprocess-128-128.png"
|
||||
);
|
||||
// load the ITK/VTK viewer for imagej.js
|
||||
this.loadPlugin(
|
||||
"https://gist.githubusercontent.com/oeway/e5c980fbf6582f25fde795262a7e33ec/raw/itk-vtk-viewer-imagej.imjoy.html"
|
||||
);
|
||||
},
|
||||
/**
|
||||
* Switch to the ImageJ window, starting it if necessary.
|
||||
*/
|
||||
async openImageJ() {
|
||||
if (!this.viewers.imagej) {
|
||||
await this.startImageJ();
|
||||
}
|
||||
this.selectWindow("ImageJ.JS");
|
||||
return this.viewers.imagej;
|
||||
},
|
||||
/**
|
||||
* Switch to the Kaibu window, starting it if necessary.
|
||||
*/
|
||||
async openKaibu() {
|
||||
if (!this.viewers.kaibu) {
|
||||
await this.startKaibu();
|
||||
}
|
||||
this.selectWindow("Kaibu"); // TODO: make this behave more nicely when we have multiple Kaibu windows
|
||||
return this.viewers.kaibu;
|
||||
},
|
||||
async setupViewers() {
|
||||
this.loading = true;
|
||||
// TODO: improve this using the ImJoy `api.getServices`
|
||||
// See here: https://imjoy.io/docs/#/api?id=apigetservices
|
||||
// The idea is that plugins can register custom services via `api.registerService`
|
||||
// For example, we can have a image visualization service
|
||||
// Then other plugins can use `api.getServices` to get a list of services
|
||||
// And this can be used for render our "Open In ImJoy" menu
|
||||
try {
|
||||
const self = this;
|
||||
|
||||
this.$store.commit("imjoy/addOpenImageItem", {
|
||||
title: "Kaibu",
|
||||
async callback(name, imageUrl) {
|
||||
const viewer = await self.openKaibu();
|
||||
await viewer.view_image(imageUrl, { type: "2d-image", name });
|
||||
await viewer.add_shapes([]);
|
||||
}
|
||||
});
|
||||
|
||||
this.$store.commit("imjoy/addOpenImageItem", {
|
||||
title: "ImageJ.JS",
|
||||
async callback(name, imageUrl) {
|
||||
const viewer = await self.openImageJ();
|
||||
const response = await fetch(imageUrl);
|
||||
const buffer = await response.arrayBuffer();
|
||||
await viewer.viewImage(buffer, {
|
||||
name: name.replace(".jpeg", ".jpg")
|
||||
});
|
||||
}
|
||||
});
|
||||
this.$store.commit("imjoy/addOpenImageItem", {
|
||||
title: "ImageJ.JS [ndarray]",
|
||||
async callback(name, imageUrl) {
|
||||
const viewer = await self.openImageJ();
|
||||
const ndarray = await imageUrlToNdarray(imageUrl);
|
||||
await viewer.viewImage(ndarray, {
|
||||
name: name.replace(".jpeg", "")
|
||||
});
|
||||
}
|
||||
});
|
||||
this.$store.commit("imjoy/addOpenScanItem", {
|
||||
title: "ImageJ.JS [stack]",
|
||||
async callback(name, allURLs) {
|
||||
const viewer = await self.openImageJ();
|
||||
// allURLs is a list of URLs for *capture objects*, so
|
||||
// first we need to retrieve them, then extract image URLs
|
||||
// and finally turn image URLs into "numpy arrays" (RGB data).
|
||||
const imagesAsNdarrays = await Promise.all(
|
||||
allURLs.map(async url => {
|
||||
const r = await axios.get(url);
|
||||
return await imageUrlToNdarray(r.data.links.download.href);
|
||||
})
|
||||
);
|
||||
// Construct an array to hold all the images, based on the first image
|
||||
// TODO: assert that _rdtype is uint8, _rshape is the same, _rtype is ndarray
|
||||
const shape = imagesAsNdarrays[0]._rshape;
|
||||
const totalSize = imagesAsNdarrays.reduce(
|
||||
(total, image) => total + image._rvalue.byteLength,
|
||||
0
|
||||
);
|
||||
const stackData = new Uint8Array(new ArrayBuffer(totalSize));
|
||||
const transferredBytes = imagesAsNdarrays.reduce((total, image) => {
|
||||
console.log(`inserting image at ${total} bytes`);
|
||||
// TODO: is it bad to populate stackData as a "side effect"?
|
||||
stackData.set(new Uint8Array(image._rvalue), total);
|
||||
//assert image._rshape == shape;
|
||||
return total + image._rvalue.byteLength;
|
||||
}, 0);
|
||||
const stackNdarray = {
|
||||
_rtype: "ndarray",
|
||||
_rdtype: "uint8",
|
||||
_rshape: [imagesAsNdarrays.length, shape[0], shape[1], shape[2]],
|
||||
_rvalue: stackData.buffer
|
||||
};
|
||||
console.log(
|
||||
`Stack is ${transferredBytes} and will have shape: ${stackNdarray._rshape}`
|
||||
);
|
||||
await viewer.viewImage(stackNdarray, {
|
||||
name
|
||||
});
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
alert(`Failed to setup viewers, error: ${e}`);
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
async addWindow(w) {
|
||||
// Here we can add check w.standalone if we want to allow the plugin to decide whether to open in a new tab.
|
||||
this.$store.commit("imjoy/addTab", w);
|
||||
await this.$nextTick();
|
||||
//this.$forceUpdate();
|
||||
this.selectWindow(w);
|
||||
},
|
||||
loadPlugin(uri) {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.loading = true;
|
||||
this.imjoy.pm
|
||||
.reloadPluginRecursively({
|
||||
uri
|
||||
})
|
||||
.then(async plugin => {
|
||||
this.loadedPlugins[plugin.name] = plugin;
|
||||
this.loading = false;
|
||||
resolve(plugin);
|
||||
})
|
||||
.catch(e => {
|
||||
console.error(e);
|
||||
this.loading = false;
|
||||
reject(e);
|
||||
alert(`failed to load the plugin, error: ${e}`);
|
||||
});
|
||||
});
|
||||
},
|
||||
async runPlugin(plugin) {
|
||||
await plugin.api.run();
|
||||
},
|
||||
loadPluginDialog() {
|
||||
const uri = prompt(
|
||||
"Paste the ImJoy plugin url here",
|
||||
"imjoy-team/imjoy-plugins:Welcome"
|
||||
);
|
||||
if (uri) {
|
||||
this.loadPlugin(uri);
|
||||
}
|
||||
},
|
||||
async getStagePosition() {
|
||||
return axios.get(this.getPositionUri).then(r => r.data);
|
||||
},
|
||||
async setStagePosition(payload) {
|
||||
return axios.post(this.moveActionUri, payload).then(pollAction);
|
||||
},
|
||||
async getInstrumentSettings() {
|
||||
return axios
|
||||
.get(`${this.baseUri}/api/v2/instrument/settings/`)
|
||||
.then(r => r.data);
|
||||
},
|
||||
async setInstrumentSettings(payload) {
|
||||
return axios.put(`${this.baseUri}/api/v2/instrument/settings/`, payload);
|
||||
},
|
||||
runAutofocus() {
|
||||
// This mechanism is also used by the keybinding for autofocus.
|
||||
// It means we don't have a way to poll, but that's not a problem.
|
||||
this.$root.$emit("globalFastAutofocusEvent");
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style scoped>
|
||||
.window-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.imjoy-container-card {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.window-title {
|
||||
height: 26px;
|
||||
text-align: center;
|
||||
font-size: 1.2rem;
|
||||
background-color: #efefef;
|
||||
color: #482727;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.plugins-button {
|
||||
position: absolute;
|
||||
right: 1px;
|
||||
height: 26px;
|
||||
line-height: 11px;
|
||||
}
|
||||
|
||||
.close-button {
|
||||
position: absolute;
|
||||
right: 100px;
|
||||
height: 26px;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -3,11 +3,9 @@ import App from "./App.vue";
|
|||
import store from "./store";
|
||||
import axios from "axios";
|
||||
import UIkit from "uikit";
|
||||
import VueTour from "vue-tour";
|
||||
import VueFriendlyIframe from "vue-friendly-iframe";
|
||||
|
||||
import VueObserveVisibility from "vue-observe-visibility";
|
||||
|
||||
require("vue-tour/dist/vue-tour.css");
|
||||
|
||||
// Import MD icons
|
||||
import "material-symbols/outlined.css";
|
||||
|
|
@ -23,12 +21,6 @@ UIkit.mixin(
|
|||
"accordion"
|
||||
);
|
||||
|
||||
// Use vue-tour module
|
||||
Vue.use(VueTour);
|
||||
|
||||
// Use Friendly Iframe module
|
||||
Vue.use(VueFriendlyIframe);
|
||||
|
||||
// Use visibility observer
|
||||
Vue.use(VueObserveVisibility);
|
||||
|
||||
|
|
|
|||
|
|
@ -4,64 +4,6 @@ import wotStoreModule from "./wot-client";
|
|||
|
||||
Vue.use(Vuex);
|
||||
|
||||
const moduleImjoy = {
|
||||
namespaced: true,
|
||||
state: () => ({
|
||||
tabs: [],
|
||||
openImageMenu: [],
|
||||
openScanMenu: []
|
||||
}),
|
||||
mutations: {
|
||||
addOpenImageItem(state, newItem) {
|
||||
state.openImageMenu.push(newItem);
|
||||
}, // TODO: add a mutation to remove items when plugins are unloaded
|
||||
addOpenScanItem(state, newItem) {
|
||||
state.openScanMenu.push(newItem);
|
||||
}, // TODO: add a mutation to remove items when plugins are unloaded
|
||||
clearMenus(state) {
|
||||
// This is primarily useful to reset the state in hot-reloads of
|
||||
// imjoyContent.vue
|
||||
state.openImageMenu = [];
|
||||
state.openScanMenu = [];
|
||||
},
|
||||
addTab(state, newItem) {
|
||||
// Add a tab to the list of ImJoy tabs
|
||||
state.tabs.push(newItem);
|
||||
},
|
||||
removeTab(state, tabToRemove) {
|
||||
const index = state.tabs.indexOf(tabToRemove);
|
||||
if (index > -1) {
|
||||
state.tabs.splice(index, 1);
|
||||
} else {
|
||||
console.warn(
|
||||
`Attempted to remove a non-existing ImJoy tab ${tabToRemove}`
|
||||
);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Set a parameter on the tab with a given id
|
||||
*
|
||||
* Payload should contain:
|
||||
* tab: ID of the tab to modify (not window_id)
|
||||
* key: name of the property to add/change
|
||||
* value: value of the property to add/change
|
||||
*/
|
||||
setTabProperty(state, payload) {
|
||||
let tab = payload.tab;
|
||||
let key = payload.key;
|
||||
let value = payload.value;
|
||||
state.tabs = state.tabs.map(t => {
|
||||
if (t.id === tab) {
|
||||
t[key] = value;
|
||||
}
|
||||
return t;
|
||||
});
|
||||
}
|
||||
},
|
||||
actions: {},
|
||||
getters: {}
|
||||
};
|
||||
|
||||
function getOriginFromLocation() {
|
||||
// This will default to the same origin that's serving
|
||||
// the web app - but can be overridden by the URL.
|
||||
|
|
@ -77,7 +19,6 @@ function getOriginFromLocation() {
|
|||
|
||||
export default new Vuex.Store({
|
||||
modules: {
|
||||
imjoy: moduleImjoy,
|
||||
wot: wotStoreModule
|
||||
},
|
||||
state: {
|
||||
|
|
@ -88,7 +29,6 @@ export default new Vuex.Store({
|
|||
disableStream: false,
|
||||
autoGpuPreview: false,
|
||||
trackWindow: true,
|
||||
imjoyEnabled: false,
|
||||
galleryEnabled: true,
|
||||
appTheme: "system",
|
||||
activeStreams: {},
|
||||
|
|
@ -114,17 +54,6 @@ export default new Vuex.Store({
|
|||
changeAppTheme(state, theme) {
|
||||
state.appTheme = theme;
|
||||
},
|
||||
changeImjoyEnabled(state, enabled) {
|
||||
if (process.env.VUE_APP_ENABLE_IMJOY === "true") {
|
||||
state.imjoyEnabled = enabled;
|
||||
} else {
|
||||
state.imjoyEnabled = false;
|
||||
if (enabled)
|
||||
console.warn(
|
||||
"Attempted to enable ImJoy, but it's disabled by VUE_APP_ENABLE_IMJOY."
|
||||
);
|
||||
}
|
||||
},
|
||||
changeGalleryEnabled(state, enabled) {
|
||||
state.galleryEnabled = enabled;
|
||||
},
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue