@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.
- package/CHANGELOG.md +28 -0
- package/dist/package-test.js +1 -1
- package/dist/package-test.js.map +1 -1
- package/dist/package.js +1 -1
- package/dist/package.js.map +1 -1
- package/package.json +15 -16
- package/src/cell-renderer.ts +13 -36
- package/src/constants.ts +0 -11
- package/src/helm-helper.ts +67 -17
- package/src/helm-monomer-placer.ts +8 -26
- package/src/helm-web-editor.ts +33 -3
- package/src/package-test.ts +12 -4
- package/src/package-utils.ts +160 -0
- package/src/package.ts +123 -197
- package/src/tests/findMonomers-tests.ts +2 -0
- package/src/tests/get-all-parts-tests.ts +5 -0
- package/src/tests/{get-molfiles.ts → get-molfiles-tests.ts} +3 -1
- package/src/tests/get-monomer-tests.ts +279 -0
- package/src/tests/helm-service-tests.ts +4 -0
- package/src/tests/helm-tests.ts +8 -1
- package/src/tests/helm-web-editor-tests.ts +55 -0
- package/src/tests/parse-helm-tests.ts +98 -0
- package/src/tests/properties-widget-tests.ts +33 -4
- package/src/tests/renderers-tests.ts +3 -1
- package/src/tests/utils.ts +6 -0
- package/src/types/index.ts +5 -0
- package/src/utils/get-hovered.ts +9 -21
- package/src/utils/get-monomer-dummy.ts +149 -0
- package/src/utils/get-monomer-of-library.ts +90 -0
- package/src/utils/get-monomer.ts +113 -0
- package/src/utils/helm-grid-cell-renderer.ts +12 -7
- package/src/utils/helm-service.ts +19 -45
- package/src/utils/index.ts +11 -17
- package/src/widgets/properties-widget.ts +29 -9
- package/tsconfig.json +1 -1
- package/vendor/helm-web-editor.development.js +39640 -0
- package/vendor/helm-web-editor.production.js +2 -0
- package/vendor/helm-web-editor.production.js.map +1 -0
- package/webpack.config.js +14 -11
- package/helm/JSDraw/Pistoia.HELM-uncompressed.js +0 -9694
- package/helm/JSDraw/Pistoia.HELM.js +0 -27
- package/helm/JSDraw/ReadMe.txt +0 -8
- package/helm/JSDraw/Scilligence.JSDraw2.Lite-uncompressed.js +0 -31126
- package/helm/JSDraw/Scilligence.JSDraw2.Lite.js +0 -12
- package/helm/JSDraw/Scilligence.JSDraw2.Resources.js +0 -762
- package/helm/JSDraw/dojo.js +0 -250
- package/helm/JSDraw/test.html +0 -24
- 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.
|
|
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
|
-
"
|
|
12
|
-
"
|
|
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.
|
|
15
|
+
"@datagrok-libraries/bio": "^5.42.3",
|
|
19
16
|
"@datagrok-libraries/chem-meta": "^1.2.5",
|
|
20
|
-
"@datagrok-libraries/utils": "^4.2.
|
|
17
|
+
"@datagrok-libraries/utils": "^4.2.11",
|
|
21
18
|
"cash-dom": "^8.1.1",
|
|
22
|
-
"datagrok-api": "^1.
|
|
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",
|
package/src/cell-renderer.ts
CHANGED
|
@@ -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 {
|
|
16
|
+
import {JSDraw2HelmModule} from './types';
|
|
17
|
+
|
|
18
|
+
import {getMonomerLib} from './package';
|
|
15
19
|
|
|
16
|
-
|
|
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:
|
|
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
|
|
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
|
-
|
|
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';
|
package/src/helm-helper.ts
CHANGED
|
@@ -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
|
|
6
|
-
|
|
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
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
declare const
|
|
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):
|
|
39
|
+
createWebEditorApp(host: HTMLDivElement, helm: string): App {
|
|
24
40
|
org.helm.webeditor.MolViewer.molscale = 0.8;
|
|
25
|
-
const webEditorApp:
|
|
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
|
-
// --
|
|
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
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
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 {
|
|
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:
|
|
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: (
|
|
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<
|
|
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:
|
|
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):
|
|
89
|
+
public getEditorMol(tableRowIndex: number): Mol<HelmType> | null {
|
|
108
90
|
return this._editorMolList![tableRowIndex];
|
|
109
91
|
}
|
|
110
92
|
}
|
package/src/helm-web-editor.ts
CHANGED
|
@@ -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
|
|
5
|
+
import {
|
|
6
|
+
App, Editor, HelmType, IHelmWebEditor
|
|
7
|
+
} from '@datagrok-libraries/bio/src/helm/types';
|
|
6
8
|
|
|
7
|
-
import {
|
|
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:
|
|
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
|
+
}
|
package/src/package-test.ts
CHANGED
|
@@ -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
|
|
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
|
-
|
|
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
|
}
|
package/src/package-utils.ts
CHANGED
|
@@ -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
|
+
}
|