@datagrok/helm 2.2.0 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/dist/package-test.js +1 -1
  3. package/dist/package-test.js.map +1 -1
  4. package/dist/package.js +1 -1
  5. package/dist/package.js.map +1 -1
  6. package/package.json +15 -16
  7. package/src/cell-renderer.ts +13 -36
  8. package/src/constants.ts +0 -11
  9. package/src/helm-helper.ts +67 -17
  10. package/src/helm-monomer-placer.ts +8 -26
  11. package/src/helm-web-editor.ts +33 -3
  12. package/src/package-test.ts +12 -4
  13. package/src/package-utils.ts +160 -0
  14. package/src/package.ts +123 -197
  15. package/src/tests/findMonomers-tests.ts +2 -0
  16. package/src/tests/get-all-parts-tests.ts +5 -0
  17. package/src/tests/{get-molfiles.ts → get-molfiles-tests.ts} +3 -1
  18. package/src/tests/get-monomer-tests.ts +279 -0
  19. package/src/tests/helm-service-tests.ts +4 -0
  20. package/src/tests/helm-tests.ts +8 -1
  21. package/src/tests/helm-web-editor-tests.ts +55 -0
  22. package/src/tests/parse-helm-tests.ts +98 -0
  23. package/src/tests/properties-widget-tests.ts +33 -4
  24. package/src/tests/renderers-tests.ts +3 -1
  25. package/src/tests/utils.ts +6 -0
  26. package/src/types/index.ts +5 -0
  27. package/src/utils/get-hovered.ts +9 -21
  28. package/src/utils/get-monomer-dummy.ts +149 -0
  29. package/src/utils/get-monomer-of-library.ts +90 -0
  30. package/src/utils/get-monomer.ts +113 -0
  31. package/src/utils/helm-grid-cell-renderer.ts +12 -7
  32. package/src/utils/helm-service.ts +19 -45
  33. package/src/utils/index.ts +11 -17
  34. package/src/widgets/properties-widget.ts +29 -9
  35. package/tsconfig.json +1 -1
  36. package/vendor/helm-web-editor.development.js +39640 -0
  37. package/vendor/helm-web-editor.production.js +2 -0
  38. package/vendor/helm-web-editor.production.js.map +1 -0
  39. package/webpack.config.js +14 -11
  40. package/helm/JSDraw/Pistoia.HELM-uncompressed.js +0 -9694
  41. package/helm/JSDraw/Pistoia.HELM.js +0 -27
  42. package/helm/JSDraw/ReadMe.txt +0 -8
  43. package/helm/JSDraw/Scilligence.JSDraw2.Lite-uncompressed.js +0 -31126
  44. package/helm/JSDraw/Scilligence.JSDraw2.Lite.js +0 -12
  45. package/helm/JSDraw/Scilligence.JSDraw2.Resources.js +0 -762
  46. package/helm/JSDraw/dojo.js +0 -250
  47. package/helm/JSDraw/test.html +0 -24
  48. package/src/utils/dummy-monomer.ts +0 -69
package/package.json CHANGED
@@ -1,44 +1,43 @@
1
1
  {
2
2
  "name": "@datagrok/helm",
3
3
  "friendlyName": "Helm",
4
- "version": "2.2.0",
4
+ "version": "2.3.0",
5
5
  "author": {
6
6
  "name": "Oleksandra Serhiienko",
7
7
  "email": "oserhiienko@datagrok.ai"
8
8
  },
9
9
  "description": "Provides support for HELM notation (importing, detecting, rendering, conversion).",
10
10
  "sources": [
11
- "css/helm.css",
12
- "https://ajax.googleapis.com/ajax/libs/dojo/1.10.4/dojo/dojo.js",
13
- "helm/JSDraw/Scilligence.JSDraw2.Lite.js",
14
- "helm/JSDraw/Scilligence.JSDraw2.Resources.js",
15
- "helm/JSDraw/Pistoia.HELM.js"
11
+ "https://ajax.googleapis.com/ajax/libs/dojo/1.10.4/dojo/dojo.js.uncompressed.js",
12
+ "css/helm.css"
16
13
  ],
17
14
  "dependencies": {
18
- "@datagrok-libraries/bio": "^5.41.0",
15
+ "@datagrok-libraries/bio": "^5.42.3",
19
16
  "@datagrok-libraries/chem-meta": "^1.2.5",
20
- "@datagrok-libraries/utils": "^4.2.2",
17
+ "@datagrok-libraries/utils": "^4.2.11",
21
18
  "cash-dom": "^8.1.1",
22
- "datagrok-api": "^1.17.0",
19
+ "datagrok-api": "^1.18.6",
23
20
  "dayjs": "^1.10.6",
24
21
  "rxjs": "^6.5.5",
25
22
  "wu": "latest"
26
23
  },
27
24
  "devDependencies": {
25
+ "@datagrok-libraries/helm-web-editor": "^1.1.5",
26
+ "@datagrok-libraries/js-draw-lite": "^0.0.3",
27
+ "@datagrok/bio": "^2.13.2",
28
+ "@datagrok/chem": "^1.9.2",
28
29
  "@types/node": "17.0.45",
29
30
  "@types/wu": "latest",
31
+ "@typescript-eslint/eslint-plugin": "^5.11.0",
32
+ "@typescript-eslint/parser": "^5.11.0",
33
+ "eslint": "^8.18.0",
34
+ "eslint-config-google": "^0.14.0",
30
35
  "path": "^0.12.7",
31
36
  "source-map-loader": "^4.0.1",
32
37
  "ts-loader": "^9.2.6",
33
38
  "typescript": "^4.8.4",
34
39
  "webpack": "^5.76.3",
35
- "webpack-cli": "^4.9.1",
36
- "@typescript-eslint/eslint-plugin": "^5.11.0",
37
- "@typescript-eslint/parser": "^5.11.0",
38
- "eslint": "^8.18.0",
39
- "eslint-config-google": "^0.14.0",
40
- "@datagrok/bio": "^2.12.17",
41
- "@datagrok/chem": "^1.9.2"
40
+ "webpack-cli": "^4.9.1"
42
41
  },
43
42
  "scripts": {
44
43
  "link-all": "npm link @datagrok-libraries/chem-meta datagrok-api @datagrok-libraries/utils @datagrok-libraries/bio",
@@ -2,18 +2,22 @@ import * as grok from 'datagrok-api/grok';
2
2
  import * as ui from 'datagrok-api/ui';
3
3
  import * as DG from 'datagrok-api/dg';
4
4
 
5
- import * as JSDraw2 from 'JSDraw2';
6
5
  import wu from 'wu';
7
6
 
7
+ import {HelmType, Mol} from '@datagrok-libraries/bio/src/helm/types';
8
+
8
9
  import {printLeftOrCentered} from '@datagrok-libraries/bio/src/utils/cell-renderer';
9
10
  import {errorToConsole} from '@datagrok-libraries/utils/src/to-console';
11
+ import {getGridCellRendererBack} from '@datagrok-libraries/bio/src/utils/cell-renderer-back-base';
10
12
 
11
13
  import {findMonomers, parseHelm, removeGapsFromHelm} from './utils';
12
14
  import {HelmMonomerPlacer, ISeqMonomer} from './helm-monomer-placer';
13
15
  import {getHoveredMonomerFallback, getHoveredMonomerFromEditorMol} from './utils/get-hovered';
14
- import {getGridCellRendererBack} from '@datagrok-libraries/bio/src/utils/cell-renderer-back-base';
16
+ import {JSDraw2HelmModule} from './types';
17
+
18
+ import {getMonomerLib} from './package';
15
19
 
16
- // import {_package} from './package'; // NullError: method not found: '_package' on null
20
+ declare const JSDraw2: JSDraw2HelmModule;
17
21
 
18
22
  const enum tempTAGS {
19
23
  helmSumMaxLengthWords = 'helm-sum-maxLengthWords',
@@ -46,7 +50,7 @@ export class HelmCellRenderer extends DG.GridCellRenderer {
46
50
  const argsX = e.offsetX - gcb.x;
47
51
  const argsY = e.offsetY - gcb.y;
48
52
 
49
- const editorMol: JSDraw2.IEditorMol | null = helmPlacer.getEditorMol(gridCell.tableRowIndex!);
53
+ const editorMol: Mol<HelmType> | null = helmPlacer.getEditorMol(gridCell.tableRowIndex!);
50
54
  let seqMonomer: ISeqMonomer | null;
51
55
  let missedMonomers: Set<string> = new Set<string>(); // of .size = 0
52
56
  if (editorMol)
@@ -73,7 +77,9 @@ export class HelmCellRenderer extends DG.GridCellRenderer {
73
77
  if (seqMonomer) {
74
78
  if (!missedMonomers.has(seqMonomer.symbol)) {
75
79
  const tooltipElements: HTMLElement[] = [ui.div(seqMonomer.symbol)];
76
- const monomerDiv = helmPlacer.monomerLib.getTooltip(seqMonomer.polymerType, seqMonomer.symbol);
80
+ const monomerLib = getMonomerLib();
81
+ const monomerDiv = monomerLib ? monomerLib.getTooltip(seqMonomer.polymerType, seqMonomer.symbol) :
82
+ ui.divText('Monomer library is not available.');
77
83
  tooltipElements.push(monomerDiv);
78
84
  ui.tooltip.show(ui.divV(tooltipElements), e.x + 16, e.y + 16);
79
85
  } else {
@@ -146,37 +152,8 @@ export class HelmCellRenderer extends DG.GridCellRenderer {
146
152
  return;
147
153
  }
148
154
 
149
- if (missedMonomers.size > 0) {
150
- if (!grid) {
151
- const r = window.devicePixelRatio;
152
- h = 28;
153
- g.canvas.height = h * r;
154
- g.canvas.style.height = `${h}px`;
155
- }
156
-
157
- w = grid ? Math.min(grid.canvas.width - x, w) : g.canvas.width - x;
158
- //g.save();
159
- g.beginPath();
160
- g.rect(x, y, w, h);
161
- g.clip();
162
- g.transform(1, 0, 0, 1, x, y);
163
- g.font = '12px monospace';
164
- g.textBaseline = 'top';
165
- const [allParts, _lengths, sumLengths] = helmPlacer.getCellAllPartsLengths(gridCell.tableRowIndex!);
166
-
167
- for (let i = 0; i < allParts.length; ++i) {
168
- const part: string = allParts[i];
169
- const color: string =
170
- part === '.' || part.endsWith('{') || part.startsWith('}') ? frameColor :
171
- missedMonomers.has(part) ? missedColor :
172
- monomers.has(part) ? monomerColor :
173
- frameColor;
174
- g.fillStyle = color;
175
- printLeftOrCentered(sumLengths[i], 0, w, h, g, allParts[i], color, 0, true, 1.0,
176
- undefined, undefined, undefined, undefined, undefined,
177
- undefined, undefined, undefined, helmPlacer.monomerTextSizeMap);
178
- }
179
- }
155
+ if (missedMonomers.size > 0)
156
+ throw new Error('Unexpected missed monomers');
180
157
  } finally {
181
158
  g.restore();
182
159
  }
package/src/constants.ts CHANGED
@@ -12,17 +12,6 @@ export const jsonSdfMonomerLibDict = {
12
12
  'symbol': 'MonomerCode'
13
13
  };
14
14
 
15
- export type WebEditorMonomer = {
16
- /** symbol */ id: string,
17
- /** name */ n: string,
18
- /** natural analog */ na?: string,
19
- /** polymer type */type: string,
20
- /** monomer type */ mt: string,
21
- /** molfile */ m: string,
22
- /** substituents */ at: { [group: string]: string },
23
- /** number of substituents */ rs: number
24
- };
25
-
26
15
  export const SMILES = 'smiles';
27
16
  export const RGROUPS = 'rgroups';
28
17
  export const MONOMER_SYMBOL = 'symbol';
@@ -2,27 +2,43 @@ import * as grok from 'datagrok-api/grok';
2
2
  import * as ui from 'datagrok-api/ui';
3
3
  import * as DG from 'datagrok-api/dg';
4
4
 
5
- import * as scil from 'scil';
6
- import * as org from 'org';
5
+ import {
6
+ App, Atom, HelmType, GetMonomerFunc, GetMonomerResType
7
+ } from '@datagrok-libraries/bio/src/helm/types';
7
8
 
9
+ import {errInfo} from '@datagrok-libraries/bio/src/utils/err-info';
10
+ import {ILogger} from '@datagrok-libraries/bio/src/utils/logger';
8
11
  import {IHelmHelper} from '@datagrok-libraries/bio/src/helm/helm-helper';
9
12
  import {IHelmWebEditor} from '@datagrok-libraries/bio/src/helm/types';
13
+ import {IMonomerLib} from '@datagrok-libraries/bio/src/types/index';
10
14
 
11
15
  import {HelmWebEditor} from './helm-web-editor';
16
+ import {OrgHelmModule, ScilModule} from './types';
17
+ import {getWebEditorMonomer} from './utils/get-monomer';
12
18
 
13
- type HelmHelperWindowType = Window & {
14
- $helmHelper?: HelmHelper,
15
- }
16
- declare const window: HelmHelperWindowType;
19
+ import {_package} from './package';
20
+
21
+ declare const scil: ScilModule;
22
+ declare const org: OrgHelmModule;
17
23
 
18
24
  export class HelmHelper implements IHelmHelper {
25
+ private static instanceCount: number = 0;
26
+
27
+ constructor(
28
+ private readonly logger: ILogger
29
+ ) {
30
+ // Watchdog for singleton
31
+ if ((++HelmHelper.instanceCount) > 1)
32
+ throw new Error(`HelmHelper must be a single.`);
33
+ }
34
+
19
35
  createHelmWebEditor(): IHelmWebEditor {
20
36
  return new HelmWebEditor();
21
37
  }
22
38
 
23
- createWebEditorApp(host: HTMLDivElement, helm: string): org.helm.IWebEditorApp {
39
+ createWebEditorApp(host: HTMLDivElement, helm: string): App {
24
40
  org.helm.webeditor.MolViewer.molscale = 0.8;
25
- const webEditorApp: org.helm.IWebEditorApp = new org.helm.webeditor.App(host, {
41
+ const webEditorApp: App = new org.helm.webeditor.App(host, {
26
42
  showabout: false,
27
43
  mexfontsize: '90%',
28
44
  mexrnapinontab: true,
@@ -47,15 +63,49 @@ export class HelmHelper implements IHelmHelper {
47
63
  return webEditorApp;
48
64
  }
49
65
 
50
- // -- Instance singleton --
66
+ // -- GetMonomer --
67
+
68
+ public originalGetMonomer: GetMonomerFunc | null = null;
69
+
70
+ public revertOriginalGetMonomer(): GetMonomerFunc {
71
+ const logPrefix = `Helm: revertOriginalGetMonomer()`;
72
+ if (this.originalGetMonomer === null)
73
+ throw new Error('Unable to revert original getMonomer');
74
+
75
+ const monomers = org.helm.webeditor.Monomers;
76
+ const overriddenGetMonomer = monomers.getMonomer = this.originalGetMonomer;
77
+ this.originalGetMonomer = null;
78
+ return overriddenGetMonomer;
79
+ }
80
+
81
+ public overrideGetMonomer(getMonomer: GetMonomerFunc): GetMonomerFunc {
82
+ const logPrefix = `Helm: overrideGetMonomer()`;
83
+
84
+ if (this.originalGetMonomer != null)
85
+ throw new Error('');
86
+
87
+ const monomers = org.helm.webeditor.Monomers;
88
+ this.originalGetMonomer = monomers.getMonomer.bind(monomers);
89
+ monomers.getMonomer = getMonomer;
90
+ return this.originalGetMonomer!;
91
+ }
92
+
93
+ public buildGetMonomerFromLib(monomerLib: IMonomerLib): GetMonomerFunc {
94
+ const logPrefix = `Helm: HelmHelper.buildGetMonomerFromLib()`;
95
+ return (a: Atom<HelmType> | HelmType, name?: string): GetMonomerResType => {
96
+ const logPrefixInt = `${logPrefix}, org.helm.webeditor.Monomers.getMonomer()`;
97
+ try {
98
+ // logger.debug(`${logPrefixInt}, a: ${JSON.stringify(a, helmJsonReplacer)}, name: '${name}'`);
99
+
100
+ // Creates monomers in lib
101
+ const dgWem = getWebEditorMonomer(monomerLib, a, name);
51
102
 
52
- public static async getInstance(): Promise<IHelmHelper> {
53
- let res: HelmHelper = window.$helmHelper!;
54
- if (!res) {
55
- // create & init singleton
56
- window.$helmHelper = res = new HelmHelper();
57
- // await res.init();
58
- }
59
- return res;
103
+ return dgWem; //dgWem;
104
+ } catch (err) {
105
+ const [errMsg, errStack] = errInfo(err);
106
+ this.logger.error(`${logPrefixInt}, Error: ${errMsg}`, undefined, errStack);
107
+ throw err;
108
+ }
109
+ };
60
110
  }
61
111
  }
@@ -2,11 +2,10 @@ import * as grok from 'datagrok-api/grok';
2
2
  import * as ui from 'datagrok-api/ui';
3
3
  import * as DG from 'datagrok-api/dg';
4
4
 
5
- import * as org from 'org';
6
- import * as JSDraw2 from 'JSDraw2';
7
5
  import wu from 'wu';
8
6
 
9
- import {IMonomerLib, Monomer} from '@datagrok-libraries/bio/src/types/index';
7
+ import {HelmType, Mol, PolymerType} from '@datagrok-libraries/bio/src/helm/types';
8
+
10
9
  import {CellRendererBackBase} from '@datagrok-libraries/bio/src/utils/cell-renderer-back-base';
11
10
 
12
11
  import {getParts, parseHelm} from './utils';
@@ -14,16 +13,14 @@ import {getParts, parseHelm} from './utils';
14
13
  import {_package, getMonomerLib} from './package';
15
14
 
16
15
  export interface ISeqMonomer {
17
- polymerType: string
18
- symbol: string,
16
+ polymerType: PolymerType;
17
+ symbol: string;
19
18
  }
20
19
 
21
20
  export class HelmMonomerPlacer extends CellRendererBackBase<string> {
22
- public readonly monomerLib: IMonomerLib;
23
-
24
21
  private _allPartsList: (string[] | null)[];
25
22
  private _lengthsList: (number[] | null)[];
26
- private _editorMolList: (JSDraw2.IEditorMol | null)[];
23
+ private _editorMolList: (Mol<HelmType> | null)[];
27
24
 
28
25
  public monomerCharWidth: number = 7;
29
26
  public leftPadding: number = 5;
@@ -34,14 +31,12 @@ export class HelmMonomerPlacer extends CellRendererBackBase<string> {
34
31
  tableCol: DG.Column<string>
35
32
  ) {
36
33
  super(gridCol, tableCol, _package.logger);
37
- this.monomerLib = getMonomerLib();
38
- this.subs.push(this.monomerLib.onChanged.subscribe(this.monomerLibOnChanged.bind(this)));
39
34
  }
40
35
 
41
36
  protected override reset(): void {
42
37
  this._allPartsList = new Array<string[] | null>(this.tableCol.length).fill(null);
43
38
  this._lengthsList = new Array<number[] | null>(this.tableCol.length).fill(null);
44
- this._editorMolList = new Array<JSDraw2.IEditorMol | null>(this.tableCol.length).fill(null);
39
+ this._editorMolList = new Array<Mol<HelmType> | null>(this.tableCol.length).fill(null);
45
40
  }
46
41
 
47
42
  /** Skips cell for the fallback rendering */
@@ -80,19 +75,6 @@ export class HelmMonomerPlacer extends CellRendererBackBase<string> {
80
75
  return [allParts, lengths];
81
76
  }
82
77
 
83
- getMonomer(monomer: ISeqMonomer): Monomer | null {
84
- let res: Monomer | null = null;
85
- if (monomer.polymerType)
86
- res = this.monomerLib.getMonomer(monomer.polymerType, monomer.symbol);
87
- else {
88
- for (const polymerType of this.monomerLib.getPolymerTypes()) {
89
- res = this.monomerLib.getMonomer(polymerType, monomer.symbol);
90
- if (res) break;
91
- }
92
- }
93
- return res;
94
- }
95
-
96
78
  // -- Handle events --
97
79
 
98
80
  private monomerLibOnChanged(_value: any): void {
@@ -100,11 +82,11 @@ export class HelmMonomerPlacer extends CellRendererBackBase<string> {
100
82
  this.invalidateGrid();
101
83
  }
102
84
 
103
- public setEditorMol(tableRowIndex: number, editorMol: JSDraw2.IEditorMol) {
85
+ public setEditorMol(tableRowIndex: number, editorMol: Mol<HelmType>) {
104
86
  this._editorMolList![tableRowIndex] = editorMol.clone(false);
105
87
  }
106
88
 
107
- public getEditorMol(tableRowIndex: number): JSDraw2.IEditorMol | null {
89
+ public getEditorMol(tableRowIndex: number): Mol<HelmType> | null {
108
90
  return this._editorMolList![tableRowIndex];
109
91
  }
110
92
  }
@@ -2,12 +2,18 @@ import * as grok from 'datagrok-api/grok';
2
2
  import * as ui from 'datagrok-api/ui';
3
3
  import * as DG from 'datagrok-api/dg';
4
4
 
5
- import * as JSDraw2 from 'JSDraw2';
5
+ import {
6
+ App, Editor, HelmType, IHelmWebEditor
7
+ } from '@datagrok-libraries/bio/src/helm/types';
6
8
 
7
- import {IHelmWebEditor} from '@datagrok-libraries/bio/src/helm/types';
9
+ import {JSDraw2HelmModule, OrgHelmModule, ScilModule} from './types';
10
+
11
+ declare const scil: ScilModule;
12
+ declare const JSDraw2: JSDraw2HelmModule;
13
+ declare const org: OrgHelmModule;
8
14
 
9
15
  export class HelmWebEditor implements IHelmWebEditor {
10
- editor: JSDraw2.Editor;
16
+ editor: Editor<HelmType>;
11
17
  host: HTMLDivElement;
12
18
 
13
19
  w = 200;
@@ -23,3 +29,27 @@ export class HelmWebEditor implements IHelmWebEditor {
23
29
  }
24
30
  }
25
31
 
32
+ export function buildWebEditorApp(view: HTMLDivElement): App {
33
+ org.helm.webeditor.MolViewer.molscale = 0.8;
34
+ const app = new org.helm.webeditor.App(view, {
35
+ showabout: false,
36
+ mexfontsize: '90%',
37
+ mexrnapinontab: true,
38
+ topmargin: 20,
39
+ mexmonomerstab: true,
40
+ sequenceviewonly: false,
41
+ mexfavoritefirst: true,
42
+ mexfilter: true
43
+ });
44
+ const sizes = app.calculateSizes();
45
+ app.canvas.resize(sizes.rightwidth - 100, sizes.topheight - 210);
46
+ let s = {width: sizes.rightwidth - 100 + 'px', height: sizes.bottomheight + 'px'};
47
+ scil.apply(app.sequence.style, s);
48
+ scil.apply(app.notation.style, s);
49
+ s = {width: sizes.rightwidth + 'px', height: (sizes.bottomheight + app.toolbarheight) + 'px'};
50
+ scil.apply(app.properties.parent.style, s);
51
+ app.structureview.resize(sizes.rightwidth, sizes.bottomheight + app.toolbarheight);
52
+ app.mex.resize(sizes.topheight - 80);
53
+
54
+ return app;
55
+ }
@@ -1,26 +1,34 @@
1
1
  import * as DG from 'datagrok-api/dg';
2
2
  import * as grok from 'datagrok-api/grok';
3
3
 
4
+ // Do not import anything from JsDrawLite or HelmWebEditor, only to the main Helm package
5
+ // import {JSDraw2ModuleType} from '@datagrok/js-draw-lite/src/types/jsdraw2';
6
+ // import {HelmType, OrgHelmModuleType} from '@datagrok/helm-web-editor/src/types/org-helm';
7
+
4
8
  import {runTests, tests, TestContext} from '@datagrok-libraries/utils/src/test';
9
+ import {getHelmHelper} from '@datagrok-libraries/bio/src/helm/helm-helper';
5
10
 
6
- import './tests/helm-tests.ts';
11
+ import './tests/helm-tests';
7
12
  import './tests/findMonomers-tests';
8
13
  import './tests/helm-service-tests';
9
14
  import './tests/renderers-tests';
10
- import './tests/get-molfiles';
15
+ import './tests/get-molfiles-tests';
11
16
  import './tests/properties-widget-tests';
12
17
  import './tests/get-all-parts-tests';
18
+ import './tests/get-monomer-tests';
19
+ import './tests/parse-helm-tests';
20
+ import './tests/helm-web-editor-tests';
13
21
 
14
22
  export const _package = new DG.Package();
15
23
  export {tests};
16
24
 
17
-
18
25
  //name: test
19
26
  //input: string category {optional: true}
20
27
  //input: string test {optional: true}
21
28
  //input: object testContext {optional: true}
22
29
  //output: dataframe result
23
30
  export async function test(category: string, test: string, testContext: TestContext): Promise<DG.DataFrame> {
24
- const data = await runTests({category, test, testContext});
31
+ // verbose: true - for tests returning dataframe
32
+ const data = await runTests({category, test, testContext, verbose: true});
25
33
  return DG.DataFrame.fromObjects(data)!;
26
34
  }
@@ -2,8 +2,27 @@ import * as ui from 'datagrok-api/ui';
2
2
  import * as grok from 'datagrok-api/grok';
3
3
  import * as DG from 'datagrok-api/dg';
4
4
 
5
+ import {delay, timeout} from '@datagrok-libraries/utils/src/test';
6
+ import {errInfo} from '@datagrok-libraries/bio/src/utils/err-info';
7
+ import type {
8
+ DojoType, DojoxType, IOrgHelmWebEditor, Monomers
9
+ } from '@datagrok-libraries/bio/src/helm/types';
5
10
  import {HelmServiceBase} from '@datagrok-libraries/bio/src/viewers/helm-service';
11
+ import {IMonomerLib} from '@datagrok-libraries/bio/src/types';
12
+
13
+ import {HelmHelper} from './helm-helper';
6
14
  import {HelmService} from './utils/helm-service';
15
+ import {OrgHelmModule, ScilModule} from './types';
16
+
17
+ import {_package} from './package';
18
+
19
+ declare const dojo: DojoType;
20
+ declare const dojox: DojoxType;
21
+ declare const scil: ScilModule;
22
+ declare const org: OrgHelmModule;
23
+
24
+ // eslint-disable-next-line
25
+ var dojoConfig = {async: true};
7
26
 
8
27
  type HelmWindowType = Window & {
9
28
  $helmService?: HelmServiceBase,
@@ -15,3 +34,144 @@ export function _getHelmService(): HelmServiceBase {
15
34
  if (!res) res = window.$helmService = new HelmService();
16
35
  return res;
17
36
  }
37
+
38
+ export async function initHelmLoadAndPatchDojo(): Promise<void> {
39
+ const logPrefix = `Helm: _package.initHelmPatchDojo()`;
40
+ // patch window.dojox.gfx.svg.Text.prototype.getTextWidth hangs
41
+ /** get the text width in pixels */
42
+ // @ts-ignore
43
+ await timeout(async () => {
44
+ const dojoTargetList: { module: string, checker: () => boolean }[] = [
45
+ {module: 'dojo.ready', checker: () => !!dojo?.ready},
46
+ {module: 'dojo.window', checker: () => !!dojo?.window},
47
+ {module: 'dojo.io.script', checker: () => !!dojo?.io?.script},
48
+ // {module: 'dojo.request.iframe', checker: () => !!dojo?.request?.iframe},
49
+ {module: 'dojo.dom', checker: () => !!dojo?.dom},
50
+ {module: 'dojox.gfx', checker: () => !!dojox?.gfx},
51
+ {module: 'dojox.gfx.svg', checker: () => !!dojox?.gfx?.svg},
52
+ {module: 'dojox.gfx.shape', checker: () => !!dojox?.gfx?.shape},
53
+ ];
54
+ for (const dojoTarget of dojoTargetList) {
55
+ try { dojo.require(dojoTarget.module); } catch (err: any) {
56
+ _package.logger.error(err.message);
57
+ }
58
+ }
59
+ const getDojoProgress = (): string[] => {
60
+ return dojoTargetList.filter((dt) => !dt.checker()).map((dt) => dt.module);
61
+ };
62
+ /** List of dojo modules not ready yet */ let dojoProgress: string[];
63
+ while ((dojoProgress = getDojoProgress()).length > 0) {
64
+ _package.logger.debug(`${logPrefix}, dojo loading ... ${dojoProgress.map((m) => `'${m}'`).join(',')} ...`);
65
+ await delay(100);
66
+ }
67
+ _package.logger.debug(`${logPrefix}, dojo ready all modules`);
68
+ }, 60000, 'timeout dojox.gfx.svg');
69
+
70
+ _package.logger.debug(`${logPrefix}, patch window.dojox.gfx.svg.Text.prototype.getTextWidth`);
71
+ // @ts-ignore
72
+ window.dojox.gfx.svg.Text.prototype.getTextWidth = function() {
73
+ // Patched via Datagrok Helm package
74
+ const rawNode = this.rawNode;
75
+ const oldParent = rawNode.parentNode;
76
+ const _measurementNode = rawNode.cloneNode(true);
77
+ _measurementNode.style.visibility = 'hidden';
78
+
79
+ // solution to the "orphan issue" in FF
80
+ let _width = 0;
81
+ const _text = _measurementNode.firstChild.nodeValue;
82
+ oldParent.appendChild(_measurementNode);
83
+
84
+ // solution to the "orphan issue" in Opera
85
+ // (nodeValue == "" hangs firefox)
86
+ if (_text != '') {
87
+ let watchdogCounter = 100;
88
+ while (!_width && --watchdogCounter > 0) { // <-- hangs
89
+ //Yang: work around svgweb bug 417 -- http://code.google.com/p/svgweb/issues/detail?id=417
90
+ if (_measurementNode.getBBox)
91
+ _width = parseInt(_measurementNode.getBBox().width);
92
+ else
93
+ _width = 68;
94
+ }
95
+ }
96
+ oldParent.removeChild(_measurementNode);
97
+ return _width;
98
+ };
99
+ _package.logger.debug(`${logPrefix}, end`);
100
+ }
101
+
102
+ export const helmJsonReplacer = (key: string, value: any): any => {
103
+ switch (key) {
104
+ case '_parent': {
105
+ return `${value.toString()}`;
106
+ }
107
+ default:
108
+ return value;
109
+ }
110
+ };
111
+
112
+ export class HelmPackage extends DG.Package {
113
+ public alertOriginal: (s: string) => void;
114
+ public readonly hh: HelmHelper;
115
+
116
+ constructor() {
117
+ super();
118
+ this.hh = new HelmHelper(this.logger);
119
+ }
120
+
121
+ public initHelmPatchScilAlert(): void {
122
+ const logPrefix: string = 'Helm: initHelmPatchScilAlert()';
123
+ this.alertOriginal = scil.Utils.alert;
124
+ scil.Utils.alert = (s: string): void => {
125
+ this.logger.warning(`${logPrefix}, scil.Utils.alert() s: "${s}".`);
126
+ };
127
+ }
128
+
129
+ /** Patches Pistoia Monomers.getMonomer method to utilize DG Bio monomer Lib */
130
+ public async initHelmPatchPistoia(monomerLib: IMonomerLib): Promise<void> {
131
+ const logPrefix: string = 'Helm: initHelmPatchPistoia()';
132
+ const monomers = org.helm.webeditor.Monomers;
133
+
134
+ this.logger.debug(`${logPrefix}, this.getMonomerOriginal stored`);
135
+
136
+ this.hh.overrideGetMonomer(this.hh.buildGetMonomerFromLib(monomerLib));
137
+
138
+ // @ts-ignore, intercept with proxy to observe access and usage
139
+ org.helm.webeditor.Monomers = new class {
140
+ constructor(base: Monomers) {
141
+ return new Proxy(base, {
142
+ get(target: any, p: string | symbol, _receiver: any): any {
143
+ return target[p];
144
+ },
145
+ set(target: any, p: string | symbol, newValue: any, _receiver: any): boolean {
146
+ if (p != 'sugars' && p != 'linkers' && p != 'bases' && p != 'aas') {
147
+ const k = 11;
148
+ }
149
+ target[p] = newValue;
150
+ return true;
151
+ },
152
+ apply(target: any, thisArg: any, argArray: any[]): any {
153
+ return target[thisArg](...argArray);
154
+ },
155
+ });
156
+ }
157
+ }(org.helm.webeditor.Monomers) as Monomers;
158
+
159
+ // @ts-ignore, intercept with proxy to observe access and usage
160
+ org.helm.webeditor = new class {
161
+ constructor(base: IOrgHelmWebEditor) {
162
+ return new Proxy(base, {
163
+ get(target: any, p: string | symbol, _receiver: any): any {
164
+ return target[p];
165
+ },
166
+ set(target: any, p: string | symbol, newValue: any, _receiver: any): boolean {
167
+ target[p] = newValue;
168
+ return true;
169
+ },
170
+ apply(target: any, thisArg: any, argArray: any[]): any {
171
+ return target[thisArg](...argArray);
172
+ },
173
+ });
174
+ }
175
+ }(org.helm.webeditor) as IOrgHelmWebEditor;
176
+ }
177
+ }