@datagrok/helm 2.1.14 → 2.1.16
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/.eslintrc.json +10 -20
- 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 +3 -3
- package/src/cell-renderer.ts +5 -4
- package/src/constants.ts +32 -28
- package/src/helm-monomer-placer.ts +10 -10
- package/src/helm-web-editor.ts +3 -0
- package/src/package-test.ts +1 -0
- package/src/package.ts +45 -35
- package/src/tests/renderers-tests.ts +35 -0
- package/src/utils.ts +3 -3
- package/tsconfig.json +1 -1
- package/webpack.config.js +2 -2
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@datagrok/helm",
|
|
3
3
|
"friendlyName": "Helm",
|
|
4
|
-
"version": "2.1.
|
|
4
|
+
"version": "2.1.16",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Oleksandra Serhiienko",
|
|
7
7
|
"email": "oserhiienko@datagrok.ai"
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
],
|
|
17
17
|
"dependencies": {
|
|
18
18
|
"@datagrok-libraries/bio": "^5.33.2",
|
|
19
|
-
"@datagrok-libraries/utils": "^
|
|
19
|
+
"@datagrok-libraries/utils": "^4.0.17",
|
|
20
20
|
"cash-dom": "^8.1.1",
|
|
21
21
|
"datagrok-api": "^1.10.2",
|
|
22
22
|
"dayjs": "^1.10.6",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"path": "^0.12.7",
|
|
28
28
|
"source-map-loader": "^4.0.1",
|
|
29
29
|
"ts-loader": "^9.2.6",
|
|
30
|
-
"typescript": "^4.
|
|
30
|
+
"typescript": "^4.8.4",
|
|
31
31
|
"webpack": "^5.59.1",
|
|
32
32
|
"webpack-cli": "^4.9.1",
|
|
33
33
|
"@typescript-eslint/eslint-plugin": "^5.11.0",
|
package/src/cell-renderer.ts
CHANGED
|
@@ -44,7 +44,7 @@ export class HelmCellRenderer extends DG.GridCellRenderer {
|
|
|
44
44
|
if (!tableCol) return;
|
|
45
45
|
|
|
46
46
|
const helmPlacer = HelmMonomerPlacer.getOrCreate(tableCol);
|
|
47
|
-
const [allParts, lengths, sumLengths] = helmPlacer.getCellAllPartsLengths(gridCell.tableRowIndex);
|
|
47
|
+
const [allParts, lengths, sumLengths] = helmPlacer.getCellAllPartsLengths(gridCell.tableRowIndex!);
|
|
48
48
|
|
|
49
49
|
const maxIndex = Object.values(lengths).length - 1;
|
|
50
50
|
const argsX = e.offsetX - gridCell.bounds.x;
|
|
@@ -122,8 +122,9 @@ export class HelmCellRenderer extends DG.GridCellRenderer {
|
|
|
122
122
|
const frameColor: string = '#C0C0C0';
|
|
123
123
|
|
|
124
124
|
const seq = gridCell.cell.value;
|
|
125
|
-
const
|
|
126
|
-
const
|
|
125
|
+
const monomerList = parseHelm(seq);
|
|
126
|
+
const monomers: Set<string> = new Set<string>(monomerList);
|
|
127
|
+
const missedMonomers: Set<string> = findMonomers(monomerList);
|
|
127
128
|
|
|
128
129
|
if (missedMonomers.size == 0) {
|
|
129
130
|
const host = ui.div([], {style: {width: `${w}px`, height: `${h}px`}});
|
|
@@ -152,7 +153,7 @@ export class HelmCellRenderer extends DG.GridCellRenderer {
|
|
|
152
153
|
g.font = '12px monospace';
|
|
153
154
|
g.textBaseline = 'top';
|
|
154
155
|
const helmPlacer = HelmMonomerPlacer.getOrCreate(tableCol);
|
|
155
|
-
const [allParts, lengths, sumLengths] = helmPlacer.getCellAllPartsLengths(gridCell.
|
|
156
|
+
const [allParts, lengths, sumLengths] = helmPlacer.getCellAllPartsLengths(gridCell.tableRowIndex!);
|
|
156
157
|
|
|
157
158
|
for (let i = 0; i < allParts.length; ++i) {
|
|
158
159
|
const part: string = allParts[i];
|
package/src/constants.ts
CHANGED
|
@@ -1,33 +1,37 @@
|
|
|
1
1
|
export const jsonSdfMonomerLibDict = {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
}
|
|
2
|
+
'monomerType': null,
|
|
3
|
+
'smiles': null,
|
|
4
|
+
'name': 'MonomerName',
|
|
5
|
+
'author': null,
|
|
6
|
+
'molfile': 'molecule',
|
|
7
|
+
'naturalAnalog': 'MonomerNaturalAnalogCode',
|
|
8
|
+
'rgroups': 'MonomerCaps',
|
|
9
|
+
'createDate': null,
|
|
10
|
+
'id': null,
|
|
11
|
+
'polymerType': 'MonomerType',
|
|
12
|
+
'symbol': 'MonomerCode'
|
|
13
|
+
};
|
|
14
14
|
|
|
15
15
|
export type WebEditorMonomer = {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
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
25
|
|
|
26
26
|
export const SMILES = 'smiles';
|
|
27
|
-
export const RGROUPS =
|
|
28
|
-
export const MONOMER_SYMBOL =
|
|
29
|
-
export const RGROUP_CAP_GROUP_SMILES =
|
|
30
|
-
export const RGROUP_ALTER_ID =
|
|
31
|
-
export const RGROUP_CAP_GROUP_NAME =
|
|
32
|
-
export const RGROUP_LABEL =
|
|
33
|
-
export const SDF_MONOMER_NAME =
|
|
27
|
+
export const RGROUPS = 'rgroups';
|
|
28
|
+
export const MONOMER_SYMBOL = 'symbol';
|
|
29
|
+
export const RGROUP_CAP_GROUP_SMILES = 'capGroupSmiles';
|
|
30
|
+
export const RGROUP_ALTER_ID = 'alternateId';
|
|
31
|
+
export const RGROUP_CAP_GROUP_NAME = 'capGroupName';
|
|
32
|
+
export const RGROUP_LABEL = 'label';
|
|
33
|
+
export const SDF_MONOMER_NAME = 'MonomerName';
|
|
34
|
+
|
|
35
|
+
export const enum TAGS {
|
|
36
|
+
cellRendererRenderError = '.cell-renderer.render.error',
|
|
37
|
+
}
|
|
@@ -14,8 +14,8 @@ export const enum Temps {
|
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
export class HelmMonomerPlacer {
|
|
17
|
-
private _allPartsList: string[][] = null;
|
|
18
|
-
private _lengthsList: number[][] = null;
|
|
17
|
+
private _allPartsList: (string[] | null)[] | null = null;
|
|
18
|
+
private _lengthsList: (number[] | null) [] | null = null;
|
|
19
19
|
|
|
20
20
|
private monomerLib: IMonomerLib;
|
|
21
21
|
|
|
@@ -30,10 +30,10 @@ export class HelmMonomerPlacer {
|
|
|
30
30
|
/** @param rowIdx Row index of the table {@link DG.DataFrame}, HelmMonomerPlacer is {@link DG.Column} based */
|
|
31
31
|
public getCellAllPartsLengths(rowIdx: number): [string[], number[], number[]] {
|
|
32
32
|
if (this._allPartsList === null)
|
|
33
|
-
this._allPartsList = new Array<string[]>(this.col.length).fill(null);
|
|
33
|
+
this._allPartsList = new Array<string[] | null>(this.col.length).fill(null);
|
|
34
34
|
|
|
35
35
|
if (this._lengthsList === null)
|
|
36
|
-
this._lengthsList = new Array<number[]>(this.col.length).fill(null);
|
|
36
|
+
this._lengthsList = new Array<number[] | null>(this.col.length).fill(null);
|
|
37
37
|
|
|
38
38
|
const [allParts, lengths] = this.getCellMonomerLengthsForSeq(rowIdx);
|
|
39
39
|
|
|
@@ -45,8 +45,8 @@ export class HelmMonomerPlacer {
|
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
private getCellMonomerLengthsForSeq(rowIdx: number): [string[], number[]] {
|
|
48
|
-
const allParts: string[] = this._allPartsList[rowIdx] = this.getAllParts(rowIdx);
|
|
49
|
-
const lengths: number[] = this._lengthsList[rowIdx] = new Array<number>(allParts.length);
|
|
48
|
+
const allParts: string[] = this._allPartsList![rowIdx] = this.getAllParts(rowIdx);
|
|
49
|
+
const lengths: number[] = this._lengthsList![rowIdx] = new Array<number>(allParts.length);
|
|
50
50
|
|
|
51
51
|
for (const [part, partI] of wu.enumerate(allParts)) {
|
|
52
52
|
const partWidth: number = part.length * this.monomerCharWidth;
|
|
@@ -58,17 +58,17 @@ export class HelmMonomerPlacer {
|
|
|
58
58
|
|
|
59
59
|
getAllParts(rowIdx: number): string[] {
|
|
60
60
|
const seq: string | null = this.col.get(rowIdx);
|
|
61
|
-
const
|
|
62
|
-
return seq ? getParts(
|
|
61
|
+
const monomerList: string[] = seq ? parseHelm(seq) : [];
|
|
62
|
+
return seq ? getParts(monomerList, seq) : [];
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
getMonomer(monomerSymbol: any): Monomer | null {
|
|
66
|
-
let res: Monomer = null;
|
|
66
|
+
let res: Monomer | null = null;
|
|
67
67
|
for (const polymerType of this.monomerLib.getPolymerTypes()) {
|
|
68
68
|
res = this.monomerLib.getMonomer(polymerType, monomerSymbol);
|
|
69
69
|
if (res) break;
|
|
70
70
|
}
|
|
71
|
-
return res
|
|
71
|
+
return res;
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
public static getOrCreate(col: DG.Column<string>): HelmMonomerPlacer {
|
package/src/helm-web-editor.ts
CHANGED
|
@@ -7,6 +7,7 @@ export class HelmWebEditor {
|
|
|
7
7
|
editor: any;
|
|
8
8
|
w = 200;
|
|
9
9
|
h = 100;
|
|
10
|
+
|
|
10
11
|
constructor() {
|
|
11
12
|
this.host = ui.div([], {style: {width: `${this.w}px`, height: `${this.h}px`}});
|
|
12
13
|
this.editor = new JSDraw2.Editor(this.host, {width: this.w, height: this.h, viewonly: true});
|
|
@@ -18,7 +19,9 @@ export class HelmWebEditor {
|
|
|
18
19
|
|
|
19
20
|
createWebEditor(value: string) {
|
|
20
21
|
const editorView = ui.div();
|
|
22
|
+
// @ts-ignore
|
|
21
23
|
org.helm.webeditor.MolViewer.molscale = 0.8;
|
|
24
|
+
// @ts-ignore
|
|
22
25
|
const webEditor = new scil.helm.App(editorView, {
|
|
23
26
|
showabout: false,
|
|
24
27
|
mexfontsize: '90%',
|
package/src/package-test.ts
CHANGED
package/src/package.ts
CHANGED
|
@@ -8,7 +8,7 @@ import {HelmWebEditor} from './helm-web-editor';
|
|
|
8
8
|
import {HelmCellRenderer} from './cell-renderer';
|
|
9
9
|
import {IMonomerLib, Monomer} from '@datagrok-libraries/bio/src/types';
|
|
10
10
|
import {NotationConverter} from '@datagrok-libraries/bio/src/utils/notation-converter';
|
|
11
|
-
import {findMonomers} from './utils';
|
|
11
|
+
import {findMonomers, parseHelm} from './utils';
|
|
12
12
|
import {errorToConsole} from '@datagrok-libraries/utils/src/to-console';
|
|
13
13
|
import {NOTATION} from '@datagrok-libraries/bio/src/utils/macromolecule';
|
|
14
14
|
|
|
@@ -24,17 +24,17 @@ export async function initHelm(): Promise<void> {
|
|
|
24
24
|
}),
|
|
25
25
|
grok.functions.call('Bio:getBioLib'),
|
|
26
26
|
])
|
|
27
|
-
.then(([_, lib]: [
|
|
27
|
+
.then(([_, lib]: [unknown, IMonomerLib]) => {
|
|
28
28
|
monomerLib = lib;
|
|
29
29
|
rewriteLibraries(); // initHelm()
|
|
30
30
|
monomerLib.onChanged.subscribe((_) => {
|
|
31
31
|
try {
|
|
32
32
|
rewriteLibraries(); // initHelm()
|
|
33
33
|
|
|
34
|
-
const monTypeList: string[] = monomerLib
|
|
34
|
+
const monTypeList: string[] = monomerLib!.getPolymerTypes();
|
|
35
35
|
const msgStr: string = 'Monomer lib updated:<br />' + (
|
|
36
36
|
monTypeList.length == 0 ? 'empty' : monTypeList.map((monType) => {
|
|
37
|
-
return `${monType} ${monomerLib
|
|
37
|
+
return `${monType} ${monomerLib!.getMonomerSymbolsByType(monType).length}`;
|
|
38
38
|
}).join('<br />'));
|
|
39
39
|
|
|
40
40
|
grok.shell.info(msgStr);
|
|
@@ -55,16 +55,17 @@ export async function initHelm(): Promise<void> {
|
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
export function getMonomerLib(): IMonomerLib {
|
|
58
|
-
return monomerLib
|
|
58
|
+
return monomerLib!;
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
function rewriteLibraries() {
|
|
62
|
+
// @ts-ignore
|
|
62
63
|
org.helm.webeditor.Monomers.clear();
|
|
63
|
-
monomerLib
|
|
64
|
-
const monomerSymbols = monomerLib
|
|
64
|
+
monomerLib!.getPolymerTypes().forEach((polymerType) => {
|
|
65
|
+
const monomerSymbols = monomerLib!.getMonomerSymbolsByType(polymerType);
|
|
65
66
|
monomerSymbols.forEach((monomerSymbol) => {
|
|
66
67
|
let isBroken = false;
|
|
67
|
-
const monomer: Monomer = monomerLib
|
|
68
|
+
const monomer: Monomer = monomerLib!.getMonomer(polymerType, monomerSymbol)!;
|
|
68
69
|
const webEditorMonomer: WebEditorMonomer = {
|
|
69
70
|
id: monomerSymbol,
|
|
70
71
|
m: monomer.molfile,
|
|
@@ -78,7 +79,7 @@ function rewriteLibraries() {
|
|
|
78
79
|
|
|
79
80
|
if (monomer.rgroups.length > 0) {
|
|
80
81
|
webEditorMonomer.rs = monomer.rgroups.length;
|
|
81
|
-
const at = {};
|
|
82
|
+
const at: { [prop: string]: any } = {};
|
|
82
83
|
monomer.rgroups.forEach((it) => {
|
|
83
84
|
at[it[RGROUP_LABEL]] = it[RGROUP_CAP_GROUP_NAME];
|
|
84
85
|
});
|
|
@@ -90,8 +91,10 @@ function rewriteLibraries() {
|
|
|
90
91
|
isBroken = true;
|
|
91
92
|
}
|
|
92
93
|
|
|
93
|
-
if (!isBroken)
|
|
94
|
+
if (!isBroken) {
|
|
95
|
+
// @ts-ignore
|
|
94
96
|
org.helm.webeditor.Monomers.addOneMonomer(webEditorMonomer);
|
|
97
|
+
}
|
|
95
98
|
});
|
|
96
99
|
});
|
|
97
100
|
|
|
@@ -110,8 +113,9 @@ export function helmCellRenderer(): HelmCellRenderer {
|
|
|
110
113
|
}
|
|
111
114
|
|
|
112
115
|
function checkMonomersAndOpenWebEditor(cell?: DG.Cell, value?: string, units?: string) {
|
|
113
|
-
const cellValue =
|
|
114
|
-
const
|
|
116
|
+
const cellValue: string = !!cell && units === undefined ? cell.value : value;
|
|
117
|
+
const monomerList: string[] = parseHelm(cellValue);
|
|
118
|
+
const monomers = findMonomers(monomerList);
|
|
115
119
|
if (monomers.size == 0) { webEditor(cell, value, units); } else {
|
|
116
120
|
grok.shell.warning(`Monomers ${Array.from(monomers).join(', ')} are absent! <br/>` +
|
|
117
121
|
`Please, upload the monomer library! <br/>` +
|
|
@@ -133,7 +137,7 @@ export function editMoleculeCell(cell: DG.GridCell): void {
|
|
|
133
137
|
//input: string mol { semType: Macromolecule }
|
|
134
138
|
export function openEditor(mol: string): void {
|
|
135
139
|
const df = grok.shell.tv.grid.dataFrame;
|
|
136
|
-
const col = df.columns.bySemType('Macromolecule')
|
|
140
|
+
const col = df.columns.bySemType('Macromolecule')!;
|
|
137
141
|
const colUnits = col.getTag(DG.TAGS.UNITS);
|
|
138
142
|
if (colUnits === NOTATION.HELM)
|
|
139
143
|
checkMonomersAndOpenWebEditor(df.currentCell, undefined, undefined);
|
|
@@ -148,7 +152,7 @@ export function openEditor(mol: string): void {
|
|
|
148
152
|
//output: widget result
|
|
149
153
|
export async function propertiesPanel(helmString: string) {
|
|
150
154
|
const grid = grok.shell.tv.grid;
|
|
151
|
-
const parent = grid.root.parentElement
|
|
155
|
+
const parent = grid.root.parentElement!;
|
|
152
156
|
const host = ui.div([]);
|
|
153
157
|
parent.appendChild(host);
|
|
154
158
|
const editor = new JSDraw2.Editor(host, {viewonly: true});
|
|
@@ -158,7 +162,7 @@ export async function propertiesPanel(helmString: string) {
|
|
|
158
162
|
const formula = editor.getFormula(true);
|
|
159
163
|
const molWeight = Math.round(editor.getMolWeight() * 100) / 100;
|
|
160
164
|
const coef = Math.round(editor.getExtinctionCoefficient(true) * 100) / 100;
|
|
161
|
-
parent.lastChild
|
|
165
|
+
parent.lastChild!.remove();
|
|
162
166
|
return new DG.Widget(
|
|
163
167
|
ui.tableFromMap({
|
|
164
168
|
'formula': formula.replace(/<sub>/g, '').replace(/<\/sub>/g, ''),
|
|
@@ -171,8 +175,10 @@ export async function propertiesPanel(helmString: string) {
|
|
|
171
175
|
function webEditor(cell?: DG.Cell, value?: string, units?: string) {
|
|
172
176
|
const view = ui.div();
|
|
173
177
|
const df = grok.shell.tv.grid.dataFrame;
|
|
174
|
-
const converter = new NotationConverter(df.columns.bySemType('Macromolecule'));
|
|
178
|
+
const converter = new NotationConverter(df.columns.bySemType('Macromolecule')!);
|
|
179
|
+
// @ts-ignore
|
|
175
180
|
org.helm.webeditor.MolViewer.molscale = 0.8;
|
|
181
|
+
// @ts-ignore
|
|
176
182
|
const app = new scil.helm.App(view, {
|
|
177
183
|
showabout: false,
|
|
178
184
|
mexfontsize: '90%',
|
|
@@ -196,7 +202,7 @@ function webEditor(cell?: DG.Cell, value?: string, units?: string) {
|
|
|
196
202
|
app.structureview.resize(sizes.rightwidth, sizes.bottomheight + app.toolbarheight);
|
|
197
203
|
app.mex.resize(sizes.topheight - 80);
|
|
198
204
|
setTimeout(() => {
|
|
199
|
-
if (
|
|
205
|
+
if (!!cell && units === undefined)
|
|
200
206
|
app.canvas.helm.setSequence(cell.value, 'HELM');
|
|
201
207
|
else
|
|
202
208
|
app.canvas.helm.setSequence(value, 'HELM');
|
|
@@ -207,31 +213,35 @@ function webEditor(cell?: DG.Cell, value?: string, units?: string) {
|
|
|
207
213
|
.onOK(() => {
|
|
208
214
|
const helmValue = app.canvas.getHelm(true).replace(/<\/span>/g, '')
|
|
209
215
|
.replace(/<span style='background:#bbf;'>/g, '');
|
|
210
|
-
if (
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
216
|
+
if (!!cell) {
|
|
217
|
+
if (units === undefined) {
|
|
218
|
+
cell.value = helmValue;
|
|
219
|
+
} else {
|
|
220
|
+
const convertedRes = converter.convertHelmToFastaSeparator(helmValue, units!);
|
|
221
|
+
cell.value = convertedRes;
|
|
222
|
+
}
|
|
215
223
|
}
|
|
216
224
|
}).show({modal: true, fullScreen: true});
|
|
217
225
|
}
|
|
218
226
|
|
|
219
227
|
function getRS(smiles: string) {
|
|
220
228
|
const newS = smiles.match(/(?<=\[)[^\][]*(?=])/gm);
|
|
221
|
-
const res = {};
|
|
229
|
+
const res: { [name: string]: string } = {};
|
|
222
230
|
let el = '';
|
|
223
231
|
let digit;
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
if (
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
+
if (!!newS) {
|
|
233
|
+
for (let i = 0; i < newS.length; i++) {
|
|
234
|
+
if (newS[i] != null) {
|
|
235
|
+
if (/\d/.test(newS[i])) {
|
|
236
|
+
digit = newS[i][newS[i].length - 1];
|
|
237
|
+
newS[i] = newS[i].replace(/[0-9]/g, '');
|
|
238
|
+
for (let j = 0; j < newS[i].length; j++) {
|
|
239
|
+
if (newS[i][j] != ':')
|
|
240
|
+
el += newS[i][j];
|
|
241
|
+
}
|
|
242
|
+
res['R' + digit] = el;
|
|
243
|
+
el = '';
|
|
232
244
|
}
|
|
233
|
-
res['R' + digit] = el;
|
|
234
|
-
el = '';
|
|
235
245
|
}
|
|
236
246
|
}
|
|
237
247
|
}
|
|
@@ -243,7 +253,7 @@ function getRS(smiles: string) {
|
|
|
243
253
|
//output: column res
|
|
244
254
|
export function getMolfiles(col: DG.Column): DG.Column {
|
|
245
255
|
const grid = grok.shell.tv.grid;
|
|
246
|
-
const parent = grid.root.parentElement
|
|
256
|
+
const parent = grid.root.parentElement!;
|
|
247
257
|
const res = DG.Column.string('mols', col.length);
|
|
248
258
|
const host = ui.div([]);
|
|
249
259
|
parent.appendChild(host);
|
|
@@ -255,7 +265,7 @@ export function getMolfiles(col: DG.Column): DG.Column {
|
|
|
255
265
|
const mol = editor.getMolfile();
|
|
256
266
|
return mol;
|
|
257
267
|
});
|
|
258
|
-
parent.lastChild
|
|
268
|
+
parent.lastChild!.remove();
|
|
259
269
|
return res;
|
|
260
270
|
}
|
|
261
271
|
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import * as grok from 'datagrok-api/grok';
|
|
2
|
+
import * as ui from 'datagrok-api/ui';
|
|
3
|
+
import * as DG from 'datagrok-api/dg';
|
|
4
|
+
|
|
5
|
+
import $ from 'cash-dom';
|
|
6
|
+
|
|
7
|
+
import {category, expect, test, awaitCheck, delay} from '@datagrok-libraries/utils/src/test';
|
|
8
|
+
import {NOTATION} from '@datagrok-libraries/bio/src/utils/macromolecule';
|
|
9
|
+
import {TAGS as helmTAGS} from '../constants';
|
|
10
|
+
|
|
11
|
+
category('renderers', () => {
|
|
12
|
+
test('missedInLib', async () => { await _testMissedInLib(); });
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
async function _testMissedInLib() {
|
|
16
|
+
const df: DG.DataFrame = await grok.dapi.files.readCsv('System:AppData/Helm/tests/sample_HELM-missedInLib.csv');
|
|
17
|
+
const helmCol: DG.Column<string> = df.getCol('HELM');
|
|
18
|
+
|
|
19
|
+
const tv: DG.TableView = grok.shell.addTableView(df);
|
|
20
|
+
await awaitCheck(() => {
|
|
21
|
+
return $(tv.root).find('.d4-grid canvas').length > 0;
|
|
22
|
+
}, 'Table view canvas not found', 100);
|
|
23
|
+
|
|
24
|
+
expect(helmCol.semType, DG.SEMTYPE.MACROMOLECULE);
|
|
25
|
+
expect(helmCol.getTag(DG.TAGS.UNITS), NOTATION.HELM);
|
|
26
|
+
expect(helmCol.getTag(DG.TAGS.CELL_RENDERER), 'helm');
|
|
27
|
+
|
|
28
|
+
const cellRendererErrorJson: string = helmCol.getTag(helmTAGS.cellRendererRenderError);
|
|
29
|
+
if (!!cellRendererErrorJson) {
|
|
30
|
+
const cellRendererError: any = JSON.parse(cellRendererErrorJson);
|
|
31
|
+
const err = new Error(cellRendererError['message']);
|
|
32
|
+
err.stack = cellRendererError['stack'];
|
|
33
|
+
throw err;
|
|
34
|
+
}
|
|
35
|
+
}
|
package/src/utils.ts
CHANGED
|
@@ -24,7 +24,7 @@ export function getParts(subParts: string[], s: string): string[] {
|
|
|
24
24
|
return allParts;
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
export function parseHelm(s: string) {
|
|
27
|
+
export function parseHelm(s: string): string[] {
|
|
28
28
|
const sections = split(s, '$');
|
|
29
29
|
s = sections[0];
|
|
30
30
|
const monomers = [];
|
|
@@ -181,8 +181,8 @@ function _detachAppendix(s: string, c: string) {
|
|
|
181
181
|
}
|
|
182
182
|
}
|
|
183
183
|
if (tag != null)
|
|
184
|
-
tag = tag.replace(new RegExp('\\' + c, 'g'), c);
|
|
185
|
-
return {tag:
|
|
184
|
+
tag = unescape(tag.replace(new RegExp('\\' + c, 'g'), c));
|
|
185
|
+
return {tag: tag, str: s};
|
|
186
186
|
}
|
|
187
187
|
|
|
188
188
|
function unescape(s: string) {
|
package/tsconfig.json
CHANGED
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
// "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
|
|
26
26
|
|
|
27
27
|
/* Strict Type-Checking Options */
|
|
28
|
-
"strict":
|
|
28
|
+
"strict": true, /* Enable all strict type-checking options. */
|
|
29
29
|
// "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
|
|
30
30
|
// "strictNullChecks": true, /* Enable strict null checks. */
|
|
31
31
|
// "strictFunctionTypes": true, /* Enable strict checking of function types. */
|
package/webpack.config.js
CHANGED
|
@@ -13,11 +13,11 @@ module.exports = {
|
|
|
13
13
|
},
|
|
14
14
|
resolve: {
|
|
15
15
|
fallback: {'url': false},
|
|
16
|
-
extensions: ['.
|
|
16
|
+
extensions: ['.ts', '.tsx', '.js', '.wasm', '.mjs', '.json'],
|
|
17
17
|
},
|
|
18
18
|
module: {
|
|
19
19
|
rules: [
|
|
20
|
-
{test: /\.js$/, enforce: 'pre', use: ['source-map-loader']},
|
|
20
|
+
{test: /\.js$/, enforce: 'pre', use: ['source-map-loader'], exclude: /node_modules/},
|
|
21
21
|
{test: /\.ts(x?)$/, use: 'ts-loader', exclude: /node_modules/},
|
|
22
22
|
{test: /\.css$/, use: ['style-loader', 'css-loader'], exclude: /node_modules/},
|
|
23
23
|
],
|