diff --git a/package.json b/package.json index d5446f0..1eb8237 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,7 @@ "@mui/icons-material": "^5.15.10", "clustal-js": "^2.0.1", "g2p_mapper": "^1.0.3", + "load-script": "^2.0.0", "molstar": "^4.0.0", "pako": "^2.1.0" }, diff --git a/src/ProteinView/components/Icn3dProteinView.tsx b/src/ProteinView/components/Icn3dProteinView.tsx new file mode 100644 index 0000000..57f7ad5 --- /dev/null +++ b/src/ProteinView/components/Icn3dProteinView.tsx @@ -0,0 +1,115 @@ +import React, { useEffect, useState } from 'react' +import { observer } from 'mobx-react' +import { ErrorMessage, LoadingEllipses } from '@jbrowse/core/ui' +import { PluginContext } from 'molstar/lib/mol-plugin/context' +import domLoadScript from 'load-script' + +// locals +import { JBrowsePluginProteinViewModel } from '../model' +import Header from './Header' + +// hooks +import useProteinView from '../useProteinView' +import useProteinViewClickBehavior from '../useProteinViewClickBehavior' +import useProteinViewHoverBehavior from '../useProteinViewHoverBehavior' + +// utils +import selectResidue from '../selectResidue' +import highlightResidue from '../highlightResidue' +import clearSelection from '../clearSelection' +import ProteinViewer from '../..' + +function injectStylesheet(param: string) { + if (document?.head) { + const link = document.createElement('link') + link.type = 'text/css' + link.rel = 'stylesheet' + + //link.href = 'http://fonts.googleapis.com/css?family=Oswald&effect=neon'; + document.head.appendChild(link) + + link.href = param + } +} + +injectStylesheet( + 'https://www.ncbi.nlm.nih.gov/Structure/icn3d/lib/jquery-ui.min.css', +) + +injectStylesheet('https://www.ncbi.nlm.nih.gov/Structure/icn3d/icn3d.css') + +function promisifiedLoadScript(src: string) { + return new Promise((resolve, reject) => { + domLoadScript(src, (err, script) => { + if (err) { + reject(err) + } else { + resolve(script.src) + } + }) + }) +} + +function Icn3dProteinPanel({ model }: { model: ProteinViewer }) { + const { url } = model + const [error, setError] = useState() + useEffect(() => { + // eslint-disable-next-line @typescript-eslint/no-floating-promises + ;(async () => { + try { + const icn3dui = new icn3d.iCn3DUI({ + divid: 'viewer', + mobilemenu: true, + url: 'mmcif|' + url, + }) + await icn3dui.show3DStructure() + } catch (e) { + console.error(e) + setError(e) + } + })() + }, [url]) + return error ? :
+} + +const Icn3dProteinView = observer(function ({ + model, +}: { + model: JBrowsePluginProteinViewModel +}) { + const [error, setError] = useState() + const [completed, setCompleted] = useState(false) + useEffect(() => { + // eslint-disable-next-line @typescript-eslint/no-floating-promises + ;(async () => { + try { + await promisifiedLoadScript( + 'https://www.ncbi.nlm.nih.gov/Structure/icn3d/lib/jquery.min.js', + ) + await promisifiedLoadScript( + 'https://www.ncbi.nlm.nih.gov/Structure/icn3d/lib/jquery-ui.min.js', + ) + await promisifiedLoadScript( + 'https://www.ncbi.nlm.nih.gov/Structure/icn3d/lib/threeClass.min.js', + ) + await promisifiedLoadScript( + 'https://www.ncbi.nlm.nih.gov/Structure/icn3d/icn3d.min.js', + ) + setCompleted(true) + } catch (e) { + console.error(e) + setError(e) + } + })() + }, []) + + return error ? ( + + ) : completed ? ( + + ) : ( + + ) +}) + +export default Icn3dProteinView diff --git a/src/ProteinView/components/ProteinView.tsx b/src/ProteinView/components/ProteinView.tsx index f08aa3f..e0c6645 100644 --- a/src/ProteinView/components/ProteinView.tsx +++ b/src/ProteinView/components/ProteinView.tsx @@ -19,6 +19,7 @@ import clearSelection from '../clearSelection' // css import css from '../css/molstar' +import Icn3dViewer from './Icn3dProteinView' if (document?.head) { const style = document.createElement('style') @@ -40,12 +41,13 @@ const ProteinView = observer(function ({ return error ? ( ) : ( - + // + ) }) diff --git a/src/ProteinView/components/dependencies.js b/src/ProteinView/components/dependencies.js new file mode 100644 index 0000000..2706efb --- /dev/null +++ b/src/ProteinView/components/dependencies.js @@ -0,0 +1,9 @@ +import * as THREE from 'icn3d/three' +import $ from 'jquery' +import 'jquery-ui-bundle' + +import 'jquery-ui-bundle/jquery-ui.min.css' + +global.THREE = THREE +global.$ = $ +global.jQuery = $ diff --git a/yarn.lock b/yarn.lock index e947a58..a270b21 100644 --- a/yarn.lock +++ b/yarn.lock @@ -494,7 +494,7 @@ dependencies: eslint-visitor-keys "^3.3.0" -"@eslint-community/regexpp@^4.10.0", "@eslint-community/regexpp@^4.6.1": +"@eslint-community/regexpp@^4.10.0", "@eslint-community/regexpp@^4.11.0": version "4.11.0" resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.11.0.tgz#b0ffd0312b4a3fd2d6f77237e7248a5ad3a680ae" integrity sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A== @@ -528,10 +528,10 @@ minimatch "^3.1.2" strip-json-comments "^3.1.1" -"@eslint/js@9.6.0": - version "9.6.0" - resolved "https://registry.yarnpkg.com/@eslint/js/-/js-9.6.0.tgz#5b0cb058cc13d9c92d4e561d3538807fa5127c95" - integrity sha512-D9B0/3vNg44ZeWbYMpBoXqNP4j6eQD5vNwIlGAuFRRzK/WtT/jvDQW3Bi9kkf3PMDMlM7Yi+73VLUsn5bJcl8A== +"@eslint/js@9.7.0": + version "9.7.0" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-9.7.0.tgz#b712d802582f02b11cfdf83a85040a296afec3f0" + integrity sha512-ChuWDQenef8OSFnvuxv0TCVxEwmu3+hPNKvM9B34qpM0rDRbjL8t5QkQeHHeAfsKQjuH9wS82WeCi1J/owatng== "@eslint/object-schema@^2.1.4": version "2.1.4" @@ -1897,9 +1897,9 @@ camelcase@^6.2.0: integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== caniuse-lite@^1.0.30001640: - version "1.0.30001641" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001641.tgz#3572862cd18befae3f637f2a1101cc033c6782ac" - integrity sha512-Phv5thgl67bHYo1TtMY/MurjkHhV4EDaCosezRXgZ8jzA/Ub+wjxAvbGvjoFENStinwi5kCyOYV3mi5tOGykwA== + version "1.0.30001642" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001642.tgz#6aa6610eb24067c246d30c57f055a9d0a7f8d05f" + integrity sha512-3XQ0DoRgLijXJErLSl+bLnJ+Et4KqV1PY6JJBGAFlsNsz31zeAIncyeZfLCabHK/jtSh+671RM9YMldxjUPZtA== canvas-sequencer@^3.1.0: version "3.1.0" @@ -2249,7 +2249,7 @@ define-data-property@^1.0.1, define-data-property@^1.1.4: es-errors "^1.3.0" gopd "^1.0.1" -define-properties@^1.2.0, define-properties@^1.2.1: +define-properties@^1.1.3, define-properties@^1.2.0, define-properties@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.1.tgz#10781cc616eb951a80a034bafcaa7377f6af2b6c" integrity sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg== @@ -2381,7 +2381,7 @@ error-ex@^1.3.1: dependencies: is-arrayish "^0.2.1" -es-abstract@^1.22.1, es-abstract@^1.22.3, es-abstract@^1.23.0, es-abstract@^1.23.1, es-abstract@^1.23.2, es-abstract@^1.23.3: +es-abstract@^1.17.5, es-abstract@^1.22.1, es-abstract@^1.22.3, es-abstract@^1.23.0, es-abstract@^1.23.1, es-abstract@^1.23.2, es-abstract@^1.23.3: version "1.23.3" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.23.3.tgz#8f0c5a35cd215312573c5a27c87dfd6c881a0aa0" integrity sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A== @@ -2591,9 +2591,9 @@ eslint-plugin-react-refresh@^0.4.3: integrity sha512-MIKAclwaDFIiYtVBLzDdm16E+Ty4GwhB6wZlCAG1R3Ur+F9Qbo6PRxpA5DK7XtDgm+WlCoAY2WxAwqhmIDHg6Q== eslint-plugin-react@^7.20.3: - version "7.34.3" - resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.34.3.tgz#9965f27bd1250a787b5d4cfcc765e5a5d58dcb7b" - integrity sha512-aoW4MV891jkUulwDApQbPYTVZmeuSyFrudpbTAQuj5Fv8VL+o6df2xIGpw8B0hPjAaih1/Fb0om9grCdyFYemA== + version "7.34.4" + resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.34.4.tgz#1f0dc313a0937db7ce15fd1f6c3d77e70f3e02fb" + integrity sha512-Np+jo9bUwJNxCsT12pXtrGhJgT3T44T1sHhn1Ssr42XFn8TES0267wPGo5nNrMHi8qkyimDAX2BUmkf9pSaVzA== dependencies: array-includes "^3.1.8" array.prototype.findlast "^1.2.5" @@ -2603,16 +2603,17 @@ eslint-plugin-react@^7.20.3: doctrine "^2.1.0" es-iterator-helpers "^1.0.19" estraverse "^5.3.0" + hasown "^2.0.2" jsx-ast-utils "^2.4.1 || ^3.0.0" minimatch "^3.1.2" object.entries "^1.1.8" object.fromentries "^2.0.8" - object.hasown "^1.1.4" object.values "^1.2.0" prop-types "^15.8.1" resolve "^2.0.0-next.5" semver "^6.3.1" string.prototype.matchall "^4.0.11" + string.prototype.repeat "^1.0.0" eslint-plugin-unicorn@^54.0.0: version "54.0.0" @@ -2636,10 +2637,10 @@ eslint-plugin-unicorn@^54.0.0: semver "^7.6.1" strip-indent "^3.0.0" -eslint-scope@^8.0.1: - version "8.0.1" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-8.0.1.tgz#a9601e4b81a0b9171657c343fb13111688963cfc" - integrity sha512-pL8XjgP4ZOmmwfFE8mEhSxA7ZY4C+LWyqjQ3o4yWkkmD0qcMT9kkW3zWHOczhWcjTSgqycYAgwSlXvZltv65og== +eslint-scope@^8.0.2: + version "8.0.2" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-8.0.2.tgz#5cbb33d4384c9136083a71190d548158fe128f94" + integrity sha512-6E4xmrTw5wtxnLA5wYL3WDfhZ/1bUBGOXV0zQvVRDOtrR8D0p6W7fs3JweNYhwRYeGvd/1CKX2se0/2s7Q/nJA== dependencies: esrecurse "^4.3.0" estraverse "^5.2.0" @@ -2655,15 +2656,15 @@ eslint-visitor-keys@^4.0.0: integrity sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw== eslint@^9.0.0: - version "9.6.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-9.6.0.tgz#9f54373afa15e1ba356656a8d96233182027fb49" - integrity sha512-ElQkdLMEEqQNM9Njff+2Y4q2afHk7JpkPvrd7Xh7xefwgQynqPxwf55J7di9+MEibWUGdNjFF9ITG9Pck5M84w== + version "9.7.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-9.7.0.tgz#bedb48e1cdc2362a0caaa106a4c6ed943e8b09e4" + integrity sha512-FzJ9D/0nGiCGBf8UXO/IGLTgLVzIxze1zpfA8Ton2mjLovXdAPlYDv+MQDcqj3TmrhAGYfOpz9RfR+ent0AgAw== dependencies: "@eslint-community/eslint-utils" "^4.2.0" - "@eslint-community/regexpp" "^4.6.1" + "@eslint-community/regexpp" "^4.11.0" "@eslint/config-array" "^0.17.0" "@eslint/eslintrc" "^3.1.0" - "@eslint/js" "9.6.0" + "@eslint/js" "9.7.0" "@humanwhocodes/module-importer" "^1.0.1" "@humanwhocodes/retry" "^0.3.0" "@nodelib/fs.walk" "^1.2.8" @@ -2672,7 +2673,7 @@ eslint@^9.0.0: cross-spawn "^7.0.2" debug "^4.3.2" escape-string-regexp "^4.0.0" - eslint-scope "^8.0.1" + eslint-scope "^8.0.2" eslint-visitor-keys "^4.0.0" espree "^10.1.0" esquery "^1.5.0" @@ -4561,11 +4562,16 @@ micromatch@^4.0.4: braces "^3.0.3" picomatch "^2.3.1" -mime-db@1.52.0, "mime-db@>= 1.43.0 < 2": +mime-db@1.52.0: version "1.52.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== +"mime-db@>= 1.43.0 < 2": + version "1.53.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.53.0.tgz#3cb63cd820fc29896d9d4e8c32ab4fcd74ccb447" + integrity sha512-oHlN/w+3MQ3rba9rqFr6V/ypF10LSkdwUysQL7GkXoTgIWeV+tcXGA852TBxH+gsh8UWoyhR1hKcoMJTuWflpg== + mime-types@^2.1.12, mime-types@~2.1.24, mime-types@~2.1.34: version "2.1.35" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" @@ -4808,15 +4814,6 @@ object.getownpropertydescriptors@^2.1.6: gopd "^1.0.1" safe-array-concat "^1.1.2" -object.hasown@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/object.hasown/-/object.hasown-1.1.4.tgz#e270ae377e4c120cdcb7656ce66884a6218283dc" - integrity sha512-FZ9LZt9/RHzGySlBARE3VF+gE26TxR38SdmqOqliuTnl9wrKulaQs+4dee1V+Io8VfxqzAfHu6YuRgUy8OHoTg== - dependencies: - define-properties "^1.2.1" - es-abstract "^1.23.2" - es-object-atoms "^1.0.0" - object.values@^1.1.6, object.values@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.2.0.tgz#65405a9d92cee68ac2d303002e0b8470a4d9ab1b" @@ -5061,9 +5058,9 @@ prettier-linter-helpers@^1.0.0: fast-diff "^1.1.2" prettier@^3.2.5: - version "3.3.2" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.3.2.tgz#03ff86dc7c835f2d2559ee76876a3914cec4a90a" - integrity sha512-rAVeHYMcv8ATV5d508CFdn+8/pHPpXeIid1DdrPwXnaAdH7cqjVbpJaT5eq4yRAFU/lsbwYwSF/n5iNrdJHPQA== + version "3.3.3" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.3.3.tgz#30c54fe0be0d8d12e6ae61dbb10109ea00d53105" + integrity sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew== pretty-bytes@^6.1.1: version "6.1.1" @@ -5693,6 +5690,14 @@ string.prototype.padend@^3.0.0: es-abstract "^1.23.2" es-object-atoms "^1.0.0" +string.prototype.repeat@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz#e90872ee0308b29435aa26275f6e1b762daee01a" + integrity sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.5" + string.prototype.trim@^1.2.9: version "1.2.9" resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz#b6fa326d72d2c78b6df02f7759c73f8f6274faa4"