@datagrok/helm 2.1.34 → 2.2.1

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@datagrok/helm",
3
3
  "friendlyName": "Helm",
4
- "version": "2.1.34",
4
+ "version": "2.2.1",
5
5
  "author": {
6
6
  "name": "Oleksandra Serhiienko",
7
7
  "email": "oserhiienko@datagrok.ai"
@@ -12,33 +12,33 @@
12
12
  "https://ajax.googleapis.com/ajax/libs/dojo/1.10.4/dojo/dojo.js",
13
13
  "helm/JSDraw/Scilligence.JSDraw2.Lite.js",
14
14
  "helm/JSDraw/Scilligence.JSDraw2.Resources.js",
15
- "helm/JSDraw/Pistoia.HELM-uncompressed.js"
15
+ "helm/JSDraw/Pistoia.HELM.js"
16
16
  ],
17
17
  "dependencies": {
18
- "@datagrok-libraries/bio": "^5.40.8",
18
+ "@datagrok-libraries/bio": "^5.41.2",
19
19
  "@datagrok-libraries/chem-meta": "^1.2.5",
20
- "@datagrok-libraries/utils": "^4.2.1",
20
+ "@datagrok-libraries/utils": "^4.2.2",
21
21
  "cash-dom": "^8.1.1",
22
- "datagrok-api": "^1.17.0",
22
+ "datagrok-api": "^1.17.4",
23
23
  "dayjs": "^1.10.6",
24
24
  "rxjs": "^6.5.5",
25
25
  "wu": "latest"
26
26
  },
27
27
  "devDependencies": {
28
+ "@datagrok/bio": "^2.12.18",
29
+ "@datagrok/chem": "^1.9.2",
28
30
  "@types/node": "17.0.45",
29
31
  "@types/wu": "latest",
32
+ "@typescript-eslint/eslint-plugin": "^5.11.0",
33
+ "@typescript-eslint/parser": "^5.11.0",
34
+ "eslint": "^8.18.0",
35
+ "eslint-config-google": "^0.14.0",
30
36
  "path": "^0.12.7",
31
37
  "source-map-loader": "^4.0.1",
32
38
  "ts-loader": "^9.2.6",
33
39
  "typescript": "^4.8.4",
34
40
  "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.11",
41
- "@datagrok/chem": "^1.9.0"
41
+ "webpack-cli": "^4.9.1"
42
42
  },
43
43
  "scripts": {
44
44
  "link-all": "npm link @datagrok-libraries/chem-meta datagrok-api @datagrok-libraries/utils @datagrok-libraries/bio",
@@ -2,16 +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
6
  import wu from 'wu';
6
7
 
7
8
  import {printLeftOrCentered} from '@datagrok-libraries/bio/src/utils/cell-renderer';
8
9
  import {errorToConsole} from '@datagrok-libraries/utils/src/to-console';
10
+ import {getGridCellRendererBack} from '@datagrok-libraries/bio/src/utils/cell-renderer-back-base';
9
11
 
10
12
  import {findMonomers, parseHelm, removeGapsFromHelm} from './utils';
11
- import {IEditor, HelmMonomerPlacer, IEditorMolAtom, ISeqMonomer, Temps} from './helm-monomer-placer';
12
- import {IMonomerLib} from '@datagrok-libraries/bio/src/types/index';
13
+ import {HelmMonomerPlacer, ISeqMonomer} from './helm-monomer-placer';
14
+ import {getHoveredMonomerFallback, getHoveredMonomerFromEditorMol} from './utils/get-hovered';
13
15
 
14
- // import {_package} from './package'; // NullError: method not found: '_package' on null
16
+ import {getMonomerLib} from './package';
15
17
 
16
18
  const enum tempTAGS {
17
19
  helmSumMaxLengthWords = 'helm-sum-maxLengthWords',
@@ -20,145 +22,6 @@ const enum tempTAGS {
20
22
  helmPlacer = 'bio-helmPlacer',
21
23
  }
22
24
 
23
- function getSeqMonomerFromHelm(
24
- helmPrefix: string, symbol: string, monomerLib: IMonomerLib
25
- ): ISeqMonomer {
26
- let resSeqMonomer: ISeqMonomer | undefined = undefined;
27
- for (const polymerType of monomerLib.getPolymerTypes()) {
28
- if (helmPrefix.startsWith(polymerType))
29
- resSeqMonomer = {symbol: symbol, polymerType: polymerType};
30
- }
31
- if (!resSeqMonomer)
32
- throw new Error(`Monomer not found for symbol = '${symbol}' and helmPrefix = '${helmPrefix}'.`);
33
- return resSeqMonomer;
34
- }
35
-
36
- function getSeqMonomerFromHelmAtom(atom: IEditorMolAtom): ISeqMonomer {
37
- let polymerType: string | undefined = undefined;
38
- // @ts-ignore
39
- switch (atom.bio.type) {
40
- case 'HELM_BASE':
41
- case 'HELM_SUGAR': // r - ribose, d - deoxyribose
42
- case 'HELM_LINKER': // p - phosphate
43
- polymerType = 'RNA';
44
- break;
45
- case 'HELM_AA':
46
- polymerType = 'PEPTIDE';
47
- break;
48
- default:
49
- polymerType = 'PEPTIDE';
50
- }
51
- return {symbol: atom.elem, polymerType: polymerType};
52
- }
53
-
54
- function getHoveredMonomerFromEditor(
55
- argsX: number, argsY: number, gridCell: DG.GridCell, editor: IEditor
56
- ): ISeqMonomer | null {
57
- let hoveredSeqMonomer: ISeqMonomer | null = null;
58
-
59
- /** @return {[number, number]} [atom, distance] */
60
- function getNearest(excluded: (number | undefined)[]): [number | undefined, number | undefined] {
61
- let atom: number | undefined = undefined;
62
- let distance: number | undefined = undefined;
63
- for (let atomI = 0; atomI < editor.m.atoms.length; ++atomI) {
64
- if (!excluded.includes(atomI)) {
65
- const aX: number = editor.m.atoms[atomI].p.x;
66
- const aY: number = editor.m.atoms[atomI].p.y;
67
- const distanceToAtomI: number = Math.sqrt((argsX - aX) ** 2 + (argsY - aY) ** 2);
68
- if (distance === undefined || distance > distanceToAtomI) {
69
- atom = atomI;
70
- distance = distanceToAtomI;
71
- }
72
- }
73
- }
74
- return [atom, distance];
75
- }
76
-
77
- const [firstAtomI, firstDistance] = getNearest([]);
78
- const [secondAtomI, secondDistance] = getNearest([firstAtomI]);
79
-
80
- // for (let atomI = 0; atomI < editor.m.atoms.length; ++atomI) {
81
- // const aX: number = editor.m.atoms[atomI].p.x;
82
- // const aY: number = editor.m.atoms[atomI].p.y;
83
- // const distanceToAtomI: number = Math.sqrt((argsX - aX) ** 2 + (argsY - aY) ** 2);
84
- // if (firstDistance === undefined || firstDistance > distanceToAtomI) {
85
- // secondAtomI = firstAtomI;
86
- // firstAtomI = atomI;
87
- //
88
- // secondDistance = firstDistance;
89
- // firstDistance = distanceToAtomI;
90
- // }
91
- // }
92
-
93
- if (firstAtomI !== undefined && firstDistance !== undefined) {
94
- const firstAtom = editor.m.atoms[firstAtomI];
95
- const firstSeqMonomer = getSeqMonomerFromHelmAtom(firstAtom);
96
- if (secondAtomI !== undefined && secondDistance !== undefined) {
97
- if (firstDistance < secondDistance * 0.45)
98
- hoveredSeqMonomer = firstSeqMonomer;
99
- } else {
100
- if (firstDistance < 0.35 * gridCell.bounds.height)
101
- hoveredSeqMonomer = firstSeqMonomer;
102
- }
103
- }
104
- return hoveredSeqMonomer;
105
- }
106
-
107
- function getHoveredMonomerFallback(
108
- argsX: number, _argsY: number, gridCell: DG.GridCell, helmPlacer: HelmMonomerPlacer
109
- ): ISeqMonomer | null {
110
- let hoveredSeqMonomer: ISeqMonomer | null = null;
111
- const [allParts, lengths, sumLengths] = helmPlacer.getCellAllPartsLengths(gridCell.tableRowIndex!);
112
- const maxIndex = Object.values(lengths).length - 1;
113
- let left = 0;
114
- let right = maxIndex;
115
- let found = false;
116
- let iterCount: number = 0;
117
-
118
- let mid = 0;
119
- if (argsX > sumLengths[0]) {
120
- while (!found && iterCount < sumLengths.length) {
121
- mid = Math.floor((right + left) / 2);
122
- if (argsX >= sumLengths[mid] && argsX <= sumLengths[mid + 1]) {
123
- left = mid;
124
- found = true;
125
- } else if (argsX < sumLengths[mid])
126
- right = mid - 1;
127
- else if (argsX > sumLengths[mid + 1])
128
- left = mid + 1;
129
-
130
- if (left == right)
131
- found = true;
132
-
133
- iterCount++;
134
- }
135
- }
136
- left = (argsX >= sumLengths[left]) ? left : left - 1; // correct left to between sumLengths
137
- if (left >= 0)
138
- hoveredSeqMonomer = getSeqMonomerFromHelm(allParts[0], allParts[left], helmPlacer.monomerLib);
139
- return hoveredSeqMonomer;
140
- }
141
-
142
- type RendererGridCellTemp = {
143
- [Temps.helmMonomerPlacer]: HelmMonomerPlacer;
144
- }
145
-
146
- function getRendererGridCellTemp(gridCell: DG.GridCell
147
- ): [DG.GridColumn | null, DG.Column | null, RendererGridCellTemp] {
148
- /** Primarily store/get MonomerPlacer at GridColumn, fallback at (Table) Column for scatter plot tooltip */
149
- let temp: RendererGridCellTemp | null = null;
150
-
151
- let gridCol: DG.GridColumn | null = null;
152
- try { gridCol = gridCell.gridColumn; } catch { gridCol = null; }
153
- temp = gridCol ? gridCol.temp as RendererGridCellTemp : null;
154
-
155
- const tableCol: DG.Column = gridCell.cell.column;
156
- if (!temp) temp = tableCol.temp;
157
-
158
- if (temp === null) throw new Error(`Monomer placer store (GridColumn or Column) not found.`);
159
- return [gridCol, tableCol, temp];
160
- }
161
-
162
25
  /** Helm cell renderer in case of no missed monomer draws with JSDraw2.Editor (webeditor),
163
26
  * in case of missed monomers presented, draws linear sequences aligned in width per monomer.
164
27
  */
@@ -173,8 +36,9 @@ export class HelmCellRenderer extends DG.GridCellRenderer {
173
36
 
174
37
  onMouseMove(gridCell: DG.GridCell, e: MouseEvent): void {
175
38
  try {
176
- const [_gridCol, tableCol, temp] = getRendererGridCellTemp(gridCell);
177
- const helmPlacer = temp[Temps.helmMonomerPlacer];
39
+ const [_gridCol, tableCol, temp] =
40
+ getGridCellRendererBack<string, HelmMonomerPlacer>(gridCell);
41
+ const helmPlacer = temp['rendererBack'];
178
42
  /* Can not do anything without tableColumn */
179
43
  if (!tableCol) return;
180
44
 
@@ -182,11 +46,11 @@ export class HelmCellRenderer extends DG.GridCellRenderer {
182
46
  const argsX = e.offsetX - gcb.x;
183
47
  const argsY = e.offsetY - gcb.y;
184
48
 
185
- const editor: IEditor | null = helmPlacer.getEditor(gridCell.tableRowIndex!);
49
+ const editorMol: JSDraw2.IEditorMol | null = helmPlacer.getEditorMol(gridCell.tableRowIndex!);
186
50
  let seqMonomer: ISeqMonomer | null;
187
51
  let missedMonomers: Set<string> = new Set<string>(); // of .size = 0
188
- if (editor)
189
- seqMonomer = getHoveredMonomerFromEditor(argsX, argsY, gridCell, editor);
52
+ if (editorMol)
53
+ seqMonomer = getHoveredMonomerFromEditorMol(argsX, argsY, gridCell, editorMol);
190
54
  else {
191
55
  const seq: string = !gridCell.cell.value ? '' : removeGapsFromHelm(gridCell.cell.value as string);
192
56
  const monomerList = parseHelm(seq);
@@ -209,7 +73,9 @@ export class HelmCellRenderer extends DG.GridCellRenderer {
209
73
  if (seqMonomer) {
210
74
  if (!missedMonomers.has(seqMonomer.symbol)) {
211
75
  const tooltipElements: HTMLElement[] = [ui.div(seqMonomer.symbol)];
212
- const monomerDiv = helmPlacer.monomerLib.getTooltip(seqMonomer.polymerType, seqMonomer.symbol);
76
+ const monomerLib = getMonomerLib();
77
+ const monomerDiv = monomerLib ? monomerLib.getTooltip(seqMonomer.polymerType, seqMonomer.symbol) :
78
+ ui.divText('Monomer library is not available.');
213
79
  tooltipElements.push(monomerDiv);
214
80
  ui.tooltip.show(ui.divV(tooltipElements), e.x + 16, e.y + 16);
215
81
  } else {
@@ -244,11 +110,12 @@ export class HelmCellRenderer extends DG.GridCellRenderer {
244
110
  ) {
245
111
  g.save();
246
112
  try {
247
- const [gridCol, tableCol, temp] = getRendererGridCellTemp(gridCell);
113
+ const [gridCol, tableCol, temp] =
114
+ getGridCellRendererBack<string, HelmMonomerPlacer>(gridCell);
248
115
  /* Can not do anything without tableColumn containing temp */
249
116
  if (!tableCol) return;
250
- let helmPlacer = temp[Temps.helmMonomerPlacer];
251
- if (!helmPlacer) helmPlacer = temp[Temps.helmMonomerPlacer] = new HelmMonomerPlacer(gridCol, tableCol);
117
+ let helmPlacer = temp['rendererBack'];
118
+ if (!helmPlacer) helmPlacer = temp['rendererBack'] = new HelmMonomerPlacer(gridCol, tableCol);
252
119
 
253
120
  const grid = gridCell.gridRow !== -1 ? gridCell.grid : undefined;
254
121
  const missedColor = 'red';
@@ -273,8 +140,9 @@ export class HelmCellRenderer extends DG.GridCellRenderer {
273
140
  }
274
141
 
275
142
  // Recreate editor to avoid hanging in window.dojox.gfx.svg.Text.prototype.getTextWidth
276
- const editor = new JSDraw2.Editor(host, {width: w, height: h, skin: 'w8', viewonly: true}) as IEditor;
277
- helmPlacer.setEditor(gridCell.tableRowIndex!, editor);
143
+ const editor = new JSDraw2.Editor(host,
144
+ {width: w, height: h, skin: 'w8', viewonly: true});
145
+ helmPlacer.setEditorMol(gridCell.tableRowIndex!, editor.m);
278
146
 
279
147
  helmPlacer.skipCell(gridCell.tableRowIndex!);
280
148
  return;
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,8 +2,12 @@ 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';
7
+
5
8
  import {IHelmHelper} from '@datagrok-libraries/bio/src/helm/helm-helper';
6
- import {IHelmWebEditor, IWebEditorApp} from '@datagrok-libraries/bio/src/helm/types';
9
+ import {IHelmWebEditor} from '@datagrok-libraries/bio/src/helm/types';
10
+
7
11
  import {HelmWebEditor} from './helm-web-editor';
8
12
 
9
13
  type HelmHelperWindowType = Window & {
@@ -16,11 +20,9 @@ export class HelmHelper implements IHelmHelper {
16
20
  return new HelmWebEditor();
17
21
  }
18
22
 
19
- createWebEditorApp(host: HTMLDivElement, helm: string): IWebEditorApp {
20
- // @ts-ignore
23
+ createWebEditorApp(host: HTMLDivElement, helm: string): org.helm.IWebEditorApp {
21
24
  org.helm.webeditor.MolViewer.molscale = 0.8;
22
- // @ts-ignore
23
- const webEditorApp = new scil.helm.App(host, {
25
+ const webEditorApp: org.helm.IWebEditorApp = new org.helm.webeditor.App(host, {
24
26
  showabout: false,
25
27
  mexfontsize: '90%',
26
28
  mexrnapinontab: true,
@@ -29,16 +31,13 @@ export class HelmHelper implements IHelmHelper {
29
31
  sequenceviewonly: false,
30
32
  mexfavoritefirst: true,
31
33
  mexfilter: true
32
- }) as IWebEditorApp;
34
+ });
33
35
  const sizes = webEditorApp.calculateSizes();
34
36
  webEditorApp.canvas.resize(sizes.rightwidth - 100, sizes.topheight - 210);
35
- let s = {width: sizes.rightwidth - 100 + 'px', height: sizes.bottomheight + 'px'};
36
- //@ts-ignore
37
+ let s: Partial<CSSStyleDeclaration> = {width: sizes.rightwidth - 100 + 'px', height: sizes.bottomheight + 'px'};
37
38
  scil.apply(webEditorApp.sequence.style, s);
38
- //@ts-ignore
39
39
  scil.apply(webEditorApp.notation.style, s);
40
40
  s = {width: sizes.rightwidth + 'px', height: (sizes.bottomheight + webEditorApp.toolbarheight) + 'px'};
41
- //@ts-ignore
42
41
  scil.apply(webEditorApp.properties.parent.style, s);
43
42
  webEditorApp.structureview.resize(sizes.rightwidth, sizes.bottomheight + webEditorApp.toolbarheight);
44
43
  webEditorApp.mex.resize(sizes.topheight - 80);
@@ -2,94 +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 org from 'org';
6
+ import * as JSDraw2 from 'JSDraw2';
5
7
  import wu from 'wu';
6
- import {Unsubscribable} from 'rxjs';
7
8
 
8
9
  import {IMonomerLib, Monomer} from '@datagrok-libraries/bio/src/types/index';
10
+ import {CellRendererBackBase} from '@datagrok-libraries/bio/src/utils/cell-renderer-back-base';
11
+ import {IEditorMol} from '@datagrok-libraries/bio/src/types/helm-web-editor';
9
12
 
10
13
  import {getParts, parseHelm} from './utils';
11
14
 
12
15
  import {_package, getMonomerLib} from './package';
13
16
 
14
- export const enum Temps {
15
- helmMonomerPlacer = 'bio-helmMonomerPlacer',
16
- }
17
-
18
- export interface IEditor {
19
- get m(): IEditorMol;
20
-
21
- redraw(): void;
22
- }
23
-
24
- export interface IEditorMol {
25
- get atoms(): IEditorMolAtom[];
26
- }
27
-
28
- export interface IEditorMolAtom {
29
- get p(): IEditorPoint;
30
-
31
- get elem(): string;
32
- }
33
-
34
- export interface IEditorPoint {
35
- get x(): number;
36
-
37
- get y(): number;
38
- }
39
-
40
17
  export interface ISeqMonomer {
41
- polymerType: string
42
- symbol: string,
18
+ polymerType: org.helm.PolymerType;
19
+ symbol: string;
43
20
  }
44
21
 
45
- export class HelmMonomerPlacer {
46
- private readonly grid: DG.Grid | null;
47
- public readonly monomerLib: IMonomerLib;
48
-
22
+ export class HelmMonomerPlacer extends CellRendererBackBase<string> {
49
23
  private _allPartsList: (string[] | null)[];
50
24
  private _lengthsList: (number[] | null)[];
51
- private _editorList: (IEditor | null)[];
25
+ private _editorMolList: (JSDraw2.IEditorMol | null)[];
52
26
 
53
27
  public monomerCharWidth: number = 7;
54
28
  public leftPadding: number = 5;
55
29
  public monomerTextSizeMap: { [p: string]: TextMetrics } = {};
56
30
 
57
- private subs: Unsubscribable[] = [];
58
-
59
31
  public constructor(
60
- public readonly gridCol: DG.GridColumn | null,
61
- public readonly col: DG.Column<string>
32
+ gridCol: DG.GridColumn | null,
33
+ tableCol: DG.Column<string>
62
34
  ) {
63
- this.grid = this.gridCol ? this.gridCol.grid : null;
64
- this.reset();
65
- if (this.grid) {
66
- this.subs.push(this.col.dataFrame.onDataChanged.subscribe(() => {
67
- try {
68
- this.reset();
69
- } catch (err: any) {
70
- console.error(err);
71
- }
72
- }));
73
- this.subs.push(grok.events.onViewRemoved.subscribe((view: DG.View) => {
74
- try {
75
- if (this.grid && this.grid.view?.id === view.id) this.destroy();
76
- } catch (err: any) {
77
- console.error(err);
78
- }
79
- }));
80
- }
81
- this.monomerLib = getMonomerLib();
82
- this.subs.push(this.monomerLib.onChanged.subscribe(this.monomerLibOnChanged.bind(this)));
35
+ super(gridCol, tableCol, _package.logger);
83
36
  }
84
37
 
85
- private reset(): void {
86
- this._allPartsList = new Array<string[] | null>(this.col.length).fill(null);
87
- this._lengthsList = new Array<number[] | null>(this.col.length).fill(null);
88
- this._editorList = new Array<IEditor | null>(this.col.length).fill(null);
89
- }
90
-
91
- private destroy(): void {
92
- for (const sub of this.subs) sub.unsubscribe();
38
+ protected override reset(): void {
39
+ this._allPartsList = new Array<string[] | null>(this.tableCol.length).fill(null);
40
+ this._lengthsList = new Array<number[] | null>(this.tableCol.length).fill(null);
41
+ this._editorMolList = new Array<JSDraw2.IEditorMol | null>(this.tableCol.length).fill(null);
93
42
  }
94
43
 
95
44
  /** Skips cell for the fallback rendering */
@@ -112,7 +61,7 @@ export class HelmMonomerPlacer {
112
61
  private getCellMonomerLengthsForSeq(rowIdx: number): [string[], number[]] {
113
62
  let allParts: string[] | null = this._allPartsList![rowIdx];
114
63
  if (allParts === null) {
115
- const seq = this.col.get(rowIdx);
64
+ const seq = this.tableCol.get(rowIdx);
116
65
  allParts = this._allPartsList![rowIdx] = getAllParts(seq);
117
66
  }
118
67
 
@@ -128,32 +77,19 @@ export class HelmMonomerPlacer {
128
77
  return [allParts, lengths];
129
78
  }
130
79
 
131
- getMonomer(monomer: ISeqMonomer): Monomer | null {
132
- let res: Monomer | null = null;
133
- if (monomer.polymerType)
134
- res = this.monomerLib.getMonomer(monomer.polymerType, monomer.symbol);
135
- else {
136
- for (const polymerType of this.monomerLib.getPolymerTypes()) {
137
- res = this.monomerLib.getMonomer(polymerType, monomer.symbol);
138
- if (res) break;
139
- }
140
- }
141
- return res;
142
- }
143
-
144
80
  // -- Handle events --
145
81
 
146
82
  private monomerLibOnChanged(_value: any): void {
147
83
  this.reset();
148
- if (this.grid) this.grid.invalidate();
84
+ this.invalidateGrid();
149
85
  }
150
86
 
151
- public setEditor(tableRowIndex: number, editor: IEditor) {
152
- this._editorList![tableRowIndex] = editor;
87
+ public setEditorMol(tableRowIndex: number, editorMol: JSDraw2.IEditorMol) {
88
+ this._editorMolList![tableRowIndex] = editorMol.clone(false);
153
89
  }
154
90
 
155
- public getEditor(tableRowIndex: number): IEditor | null {
156
- return this._editorList![tableRowIndex];
91
+ public getEditorMol(tableRowIndex: number): JSDraw2.IEditorMol | null {
92
+ return this._editorMolList![tableRowIndex];
157
93
  }
158
94
  }
159
95
 
@@ -2,11 +2,14 @@ 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
7
  import {IHelmWebEditor} from '@datagrok-libraries/bio/src/helm/types';
6
8
 
7
9
  export class HelmWebEditor implements IHelmWebEditor {
8
- host: any;
9
- editor: any;
10
+ editor: JSDraw2.Editor;
11
+ host: HTMLDivElement;
12
+
10
13
  w = 200;
11
14
  h = 100;
12
15
 
@@ -1,14 +1,17 @@
1
1
  import * as DG from 'datagrok-api/dg';
2
2
  import * as grok from 'datagrok-api/grok';
3
3
 
4
+ import '@datagrok-libraries/bio/src/types/helm';
4
5
  import {runTests, tests, TestContext} from '@datagrok-libraries/utils/src/test';
5
6
 
6
7
  import './tests/helm-tests.ts';
7
8
  import './tests/findMonomers-tests';
9
+ import './tests/helm-service-tests';
8
10
  import './tests/renderers-tests';
9
- import './tests/get-molfiles';
11
+ import './tests/get-molfiles-tests';
10
12
  import './tests/properties-widget-tests';
11
13
  import './tests/get-all-parts-tests';
14
+ import './tests/get-monomer-tests';
12
15
 
13
16
  export const _package = new DG.Package();
14
17
  export {tests};
@@ -20,6 +23,7 @@ export {tests};
20
23
  //input: object testContext {optional: true}
21
24
  //output: dataframe result
22
25
  export async function test(category: string, test: string, testContext: TestContext): Promise<DG.DataFrame> {
23
- const data = await runTests({category, test, testContext});
26
+ // verbose: true - for tests returning dataframe
27
+ const data = await runTests({category, test, testContext, verbose: true});
24
28
  return DG.DataFrame.fromObjects(data)!;
25
29
  }