@datagrok/bio 2.6.1 → 2.7.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/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 +7 -1
- package/src/package-types.ts +10 -0
- package/src/package.ts +18 -48
- package/src/utils/macromolecule-column-widget.ts +47 -0
- package/src/utils/monomer-lib.ts +41 -2
- package/src/viewers/web-logo-viewer.ts +14 -11
- package/src/widgets/package-settings-editor-widget.ts +11 -1
package/package.json
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"name": "Leonid Stolbov",
|
|
6
6
|
"email": "lstolbov@datagrok.ai"
|
|
7
7
|
},
|
|
8
|
-
"version": "2.
|
|
8
|
+
"version": "2.7.0",
|
|
9
9
|
"description": "Bioinformatics support (import/export of sequences, conversion, visualization, analysis). [See more](https://github.com/datagrok-ai/public/blob/master/packages/Bio/README.md) for details.",
|
|
10
10
|
"repository": {
|
|
11
11
|
"type": "git",
|
|
@@ -18,6 +18,12 @@
|
|
|
18
18
|
"propertyType": "int",
|
|
19
19
|
"defaultValue": 3,
|
|
20
20
|
"nullable": false
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"name": "TooltipWebLogo",
|
|
24
|
+
"propertyType": "bool",
|
|
25
|
+
"defaultValue": "true",
|
|
26
|
+
"nullable": false
|
|
21
27
|
}
|
|
22
28
|
],
|
|
23
29
|
"dependencies": {
|
package/src/package-types.ts
CHANGED
|
@@ -8,6 +8,7 @@ import {ObjectPropertyBag} from 'datagrok-api/dg';
|
|
|
8
8
|
/** Names of package properties/settings declared in properties section of {@link './package.json'} */
|
|
9
9
|
export const enum BioPackagePropertiesNames {
|
|
10
10
|
MaxMonomerLength = 'MaxMonomerLength',
|
|
11
|
+
TooltipWebLogo = 'TooltipWebLogo',
|
|
11
12
|
}
|
|
12
13
|
|
|
13
14
|
|
|
@@ -26,6 +27,15 @@ export class BioPackageProperties extends Map<string, any> {
|
|
|
26
27
|
this._onPropertyChanged.next(BioPackagePropertiesNames.MaxMonomerLength);
|
|
27
28
|
}
|
|
28
29
|
|
|
30
|
+
public get tooltipWebLogo(): boolean {
|
|
31
|
+
return super.get(BioPackagePropertiesNames.TooltipWebLogo) as unknown as boolean;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
public set tooltipWebLogo(value: boolean) {
|
|
35
|
+
super.set(BioPackagePropertiesNames.TooltipWebLogo, value as unknown as boolean);
|
|
36
|
+
this._onPropertyChanged.next(BioPackagePropertiesNames.TooltipWebLogo);
|
|
37
|
+
}
|
|
38
|
+
|
|
29
39
|
constructor(source: any) {
|
|
30
40
|
super(Object.entries(source));
|
|
31
41
|
}
|
package/src/package.ts
CHANGED
|
@@ -33,7 +33,13 @@ import {SeqPalette} from '@datagrok-libraries/bio/src/seq-palettes';
|
|
|
33
33
|
import {UnitsHandler} from '@datagrok-libraries/bio/src/utils/units-handler';
|
|
34
34
|
import {WebLogoViewer} from './viewers/web-logo-viewer';
|
|
35
35
|
import {createJsonMonomerLibFromSdf, IMonomerLibHelper} from '@datagrok-libraries/bio/src/monomer-works/monomer-utils';
|
|
36
|
-
import {
|
|
36
|
+
import {
|
|
37
|
+
MonomerLibHelper,
|
|
38
|
+
getUserLibSettings,
|
|
39
|
+
setUserLibSetting,
|
|
40
|
+
getLibFileNameList,
|
|
41
|
+
getLibraryPanelUI
|
|
42
|
+
} from './utils/monomer-lib';
|
|
37
43
|
import {getMacromoleculeColumn} from './utils/ui-utils';
|
|
38
44
|
import {DimReductionMethods, ITSNEOptions, IUMAPOptions} from '@datagrok-libraries/ml/src/reduce-dimensionality';
|
|
39
45
|
import {SequenceSpaceFunctionEditor} from '@datagrok-libraries/ml/src/functionEditors/seq-space-editor';
|
|
@@ -55,9 +61,9 @@ import {splitToMonomersUI} from './utils/split-to-monomers';
|
|
|
55
61
|
import {MonomerCellRenderer} from './utils/monomer-cell-renderer';
|
|
56
62
|
import {BioPackage, BioPackageProperties} from './package-types';
|
|
57
63
|
import {RDModule} from '@datagrok-libraries/chem-meta/src/rdkit-api';
|
|
58
|
-
import {ObjectPropertyBag} from 'datagrok-api/dg';
|
|
59
64
|
import {PackageSettingsEditorWidget} from './widgets/package-settings-editor-widget';
|
|
60
65
|
import {getCompositionAnalysisWidget} from './widgets/composition-analysis-widget';
|
|
66
|
+
import {MacromoleculeColumnWidget} from './utils/macromolecule-column-widget';
|
|
61
67
|
|
|
62
68
|
export const _package = new BioPackage();
|
|
63
69
|
|
|
@@ -126,17 +132,14 @@ export async function initBio() {
|
|
|
126
132
|
//tags: tooltip
|
|
127
133
|
//input: column col {semType: Macromolecule}
|
|
128
134
|
//output: widget result
|
|
129
|
-
export
|
|
130
|
-
const
|
|
131
|
-
const
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
});
|
|
138
|
-
viewer.root.style.height = '50px';
|
|
139
|
-
return viewer;
|
|
135
|
+
export function sequenceTooltip(col: DG.Column): DG.Widget<any> {
|
|
136
|
+
const resWidget = new MacromoleculeColumnWidget(col);
|
|
137
|
+
const _resPromise = resWidget.init().then(() => { })
|
|
138
|
+
.catch((err: any) => {
|
|
139
|
+
const errMsg = err instanceof Error ? err.message : err.toString();
|
|
140
|
+
grok.shell.error(errMsg);
|
|
141
|
+
});
|
|
142
|
+
return resWidget;
|
|
140
143
|
}
|
|
141
144
|
|
|
142
145
|
//name: getBioLib
|
|
@@ -145,46 +148,12 @@ export function getBioLib(): IMonomerLib {
|
|
|
145
148
|
return MonomerLibHelper.instance.getBioLib();
|
|
146
149
|
}
|
|
147
150
|
|
|
148
|
-
//name: manageFiles
|
|
149
|
-
export async function manageFiles() {
|
|
150
|
-
const a = ui.dialog({title: 'Manage files'})
|
|
151
|
-
//@ts-ignore
|
|
152
|
-
.add(ui.fileBrowser({path: 'System:AppData/Bio/libraries'}).root)
|
|
153
|
-
.addButton('OK', () => a.close())
|
|
154
|
-
.show();
|
|
155
|
-
}
|
|
156
|
-
|
|
157
151
|
//name: Manage Libraries
|
|
158
152
|
//input: column seqColumn {semType: Macromolecule}
|
|
159
153
|
//tags: panel, exclude-actions-panel
|
|
160
154
|
//output: widget result
|
|
161
155
|
export async function libraryPanel(_seqColumn: DG.Column): Promise<DG.Widget> {
|
|
162
|
-
|
|
163
|
-
const filesButton: HTMLButtonElement = ui.button('Manage', manageFiles);
|
|
164
|
-
const inputsForm: HTMLDivElement = ui.inputs([]);
|
|
165
|
-
const libFileNameList: string[] = await getLibFileNameList();
|
|
166
|
-
|
|
167
|
-
let userStoragePromise: Promise<void> = Promise.resolve();
|
|
168
|
-
for (const libFileName of libFileNameList) {
|
|
169
|
-
const settings = await getUserLibSettings();
|
|
170
|
-
const libInput: DG.InputBase<boolean | null> = ui.boolInput(libFileName, !settings.exclude.includes(libFileName),
|
|
171
|
-
() => {
|
|
172
|
-
userStoragePromise = userStoragePromise.then(async () => {
|
|
173
|
-
if (libInput.value == true) {
|
|
174
|
-
// Checked library remove from excluded list
|
|
175
|
-
settings.exclude = settings.exclude.filter((l) => l != libFileName);
|
|
176
|
-
} else {
|
|
177
|
-
// Unchecked library add to excluded list
|
|
178
|
-
if (!settings.exclude.includes(libFileName)) settings.exclude.push(libFileName);
|
|
179
|
-
}
|
|
180
|
-
await setUserLibSetting(settings);
|
|
181
|
-
await MonomerLibHelper.instance.loadLibraries(true); // from libraryPanel()
|
|
182
|
-
grok.shell.info('Monomer library user settings saved.');
|
|
183
|
-
});
|
|
184
|
-
});
|
|
185
|
-
inputsForm.append(libInput.root);
|
|
186
|
-
}
|
|
187
|
-
return new DG.Widget(ui.divV([inputsForm, ui.div(filesButton)]));
|
|
156
|
+
return getLibraryPanelUI();
|
|
188
157
|
}
|
|
189
158
|
|
|
190
159
|
// -- Package settings editor --
|
|
@@ -614,6 +583,7 @@ export function importFasta(fileContent: string): DG.DataFrame [] {
|
|
|
614
583
|
const ffh = new FastaFileHandler(fileContent);
|
|
615
584
|
return ffh.importFasta();
|
|
616
585
|
}
|
|
586
|
+
|
|
617
587
|
//name: importBam
|
|
618
588
|
//description: Opens Bam file
|
|
619
589
|
//tags: file-handler
|
|
@@ -0,0 +1,47 @@
|
|
|
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 {TAGS as wlTAGS} from '@datagrok-libraries/bio/src/viewers/web-logo';
|
|
6
|
+
import {WebLogoViewer} from '../viewers/web-logo-viewer';
|
|
7
|
+
|
|
8
|
+
import {_package} from '../package';
|
|
9
|
+
import {UnitsHandler} from '@datagrok-libraries/bio/src/utils/units-handler';
|
|
10
|
+
|
|
11
|
+
/** Used in Macromolecule column tooltip */
|
|
12
|
+
export class MacromoleculeColumnWidget extends DG.Widget {
|
|
13
|
+
private viewed: boolean = false;
|
|
14
|
+
|
|
15
|
+
private seqCol: DG.Column<string>;
|
|
16
|
+
|
|
17
|
+
private wlViewer: WebLogoViewer;
|
|
18
|
+
|
|
19
|
+
constructor(seqCol: DG.Column<string>) {
|
|
20
|
+
super(ui.divV([]));
|
|
21
|
+
|
|
22
|
+
this.seqCol = seqCol;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
async init(): Promise<void> {
|
|
26
|
+
const uh = UnitsHandler.getOrCreate(this.seqCol);
|
|
27
|
+
const pkgTooltipWebLogo = _package.properties.tooltipWebLogo;
|
|
28
|
+
const colTooltipWebLogo = this.seqCol.getTag(wlTAGS.tooltipWebLogo);
|
|
29
|
+
|
|
30
|
+
if (pkgTooltipWebLogo !== false && !['false', 'off', 'disable', 'disabled'].includes(colTooltipWebLogo)) {
|
|
31
|
+
this.wlViewer = await this.seqCol.dataFrame.plot.fromType('WebLogo', {
|
|
32
|
+
sequenceColumnName: this.seqCol.name,
|
|
33
|
+
backgroundColor: 0x00000000,
|
|
34
|
+
positionHeight: 'Entropy',
|
|
35
|
+
positionWidth: (uh.getAlphabetIsMultichar() ? 24 : 16),
|
|
36
|
+
fixWidth: true,
|
|
37
|
+
fitArea: false,
|
|
38
|
+
// maxHeight: 100,
|
|
39
|
+
// minHeight: 25,
|
|
40
|
+
}) as unknown as WebLogoViewer;
|
|
41
|
+
this.wlViewer.root.style.height = `50px`;
|
|
42
|
+
|
|
43
|
+
this.root.appendChild(this.wlViewer.root);
|
|
44
|
+
this.root.style.width = '100%';
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
package/src/utils/monomer-lib.ts
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
|
-
// import * as ui from 'datagrok-api/ui';
|
|
2
|
-
import * as DG from 'datagrok-api/dg';
|
|
3
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
4
|
|
|
5
5
|
import {Observable, Subject} from 'rxjs';
|
|
6
|
+
|
|
6
7
|
import {IMonomerLib, Monomer} from '@datagrok-libraries/bio/src/types/index';
|
|
7
8
|
import {
|
|
8
9
|
createJsonMonomerLibFromSdf,
|
|
9
10
|
IMonomerLibHelper,
|
|
10
11
|
} from '@datagrok-libraries/bio/src/monomer-works/monomer-utils';
|
|
11
12
|
import {HELM_REQUIRED_FIELDS as REQ, HELM_OPTIONAL_FIELDS as OPT} from '@datagrok-libraries/bio/src/utils/const';
|
|
13
|
+
|
|
12
14
|
import {_package} from '../package';
|
|
13
15
|
|
|
14
16
|
const _HELM_REQUIRED_FIELDS_ARRAY = [
|
|
@@ -51,6 +53,43 @@ export async function setUserLibSetting(value: LibSettings): Promise<void> {
|
|
|
51
53
|
await grok.dapi.userDataStorage.postValue(LIB_STORAGE_NAME, 'Settings', JSON.stringify(value), true);
|
|
52
54
|
}
|
|
53
55
|
|
|
56
|
+
export async function manageFiles() {
|
|
57
|
+
const a = ui.dialog({title: 'Manage files'})
|
|
58
|
+
//@ts-ignore
|
|
59
|
+
.add(ui.fileBrowser({path: 'System:AppData/Bio/libraries'}).root)
|
|
60
|
+
.addButton('OK', () => a.close())
|
|
61
|
+
.show();
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export async function getLibraryPanelUI(): Promise<DG.Widget> {
|
|
65
|
+
//@ts-ignore
|
|
66
|
+
const filesButton: HTMLButtonElement = ui.button('Manage', manageFiles);
|
|
67
|
+
const inputsForm: HTMLDivElement = ui.inputs([]);
|
|
68
|
+
const libFileNameList: string[] = await getLibFileNameList();
|
|
69
|
+
|
|
70
|
+
let userStoragePromise: Promise<void> = Promise.resolve();
|
|
71
|
+
for (const libFileName of libFileNameList) {
|
|
72
|
+
const settings = await getUserLibSettings();
|
|
73
|
+
const libInput: DG.InputBase<boolean | null> = ui.boolInput(libFileName, !settings.exclude.includes(libFileName),
|
|
74
|
+
() => {
|
|
75
|
+
userStoragePromise = userStoragePromise.then(async () => {
|
|
76
|
+
if (libInput.value == true) {
|
|
77
|
+
// Checked library remove from excluded list
|
|
78
|
+
settings.exclude = settings.exclude.filter((l) => l != libFileName);
|
|
79
|
+
} else {
|
|
80
|
+
// Unchecked library add to excluded list
|
|
81
|
+
if (!settings.exclude.includes(libFileName)) settings.exclude.push(libFileName);
|
|
82
|
+
}
|
|
83
|
+
await setUserLibSetting(settings);
|
|
84
|
+
await MonomerLibHelper.instance.loadLibraries(true); // from libraryPanel()
|
|
85
|
+
grok.shell.info('Monomer library user settings saved.');
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
inputsForm.append(libInput.root);
|
|
89
|
+
}
|
|
90
|
+
return new DG.Widget(ui.divV([inputsForm, ui.div(filesButton)]));
|
|
91
|
+
}
|
|
92
|
+
|
|
54
93
|
export class MonomerLib implements IMonomerLib {
|
|
55
94
|
public readonly error: string | undefined;
|
|
56
95
|
|
|
@@ -26,6 +26,7 @@ import {
|
|
|
26
26
|
WebLogoPropsDefault,
|
|
27
27
|
} from '@datagrok-libraries/bio/src/viewers/web-logo';
|
|
28
28
|
import {errorToConsole} from '@datagrok-libraries/utils/src/to-console';
|
|
29
|
+
import {intToHtmlA} from '@datagrok-libraries/utils/src/color';
|
|
29
30
|
|
|
30
31
|
import {_package} from '../package';
|
|
31
32
|
|
|
@@ -155,6 +156,7 @@ export class PositionInfo {
|
|
|
155
156
|
jPos: number, absoluteMaxHeight: number, heightMode: PositionHeight, alphabetSizeLog: number,
|
|
156
157
|
positionWidthWithMargin: number, positionWidth: number, r: number, axisHeight: number
|
|
157
158
|
): void {
|
|
159
|
+
const dpr = window.devicePixelRatio;
|
|
158
160
|
// const rowCount = this.positions[jPos].rowCount;
|
|
159
161
|
// const alphabetSize = this.getAlphabetSize();
|
|
160
162
|
// if ((this.positionHeight == PositionHeight.Entropy) && (alphabetSize == null))
|
|
@@ -207,7 +209,7 @@ export class PositionInfo {
|
|
|
207
209
|
// const m: string = entry[0];
|
|
208
210
|
const h: number = maxHeight * pmInfo.count / this.rowCount;
|
|
209
211
|
|
|
210
|
-
pmInfo.bounds = new DG.Rect(jPos * positionWidthWithMargin, y, positionWidth, h);
|
|
212
|
+
pmInfo.bounds = new DG.Rect(jPos * dpr * positionWidthWithMargin, y, positionWidth * dpr, h);
|
|
211
213
|
y += h;
|
|
212
214
|
}
|
|
213
215
|
}
|
|
@@ -755,9 +757,9 @@ export class WebLogoViewer extends DG.JsViewer implements IWebLogoViewer {
|
|
|
755
757
|
|
|
756
758
|
// -- Routines --
|
|
757
759
|
|
|
758
|
-
getMonomer(p: DG.Point): [number, string | null, PositionMonomerInfo | null] {
|
|
759
|
-
const calculatedX = p.x + this.firstVisibleIndex * this.positionWidthWithMargin;
|
|
760
|
-
const jPos = Math.floor(p.x / this.positionWidthWithMargin + this.firstVisibleIndex);
|
|
760
|
+
getMonomer(p: DG.Point, dpr: number): [number, string | null, PositionMonomerInfo | null] {
|
|
761
|
+
const calculatedX = p.x + this.firstVisibleIndex * this.positionWidthWithMargin * dpr;
|
|
762
|
+
const jPos = Math.floor(p.x / (this.positionWidthWithMargin * dpr) + this.firstVisibleIndex);
|
|
761
763
|
const position: PositionInfo = this.positions[jPos];
|
|
762
764
|
|
|
763
765
|
if (position === undefined)
|
|
@@ -887,7 +889,7 @@ export class WebLogoViewer extends DG.JsViewer implements IWebLogoViewer {
|
|
|
887
889
|
|
|
888
890
|
const length: number = this.Length;
|
|
889
891
|
g.resetTransform();
|
|
890
|
-
g.fillStyle =
|
|
892
|
+
g.fillStyle = intToHtmlA(this.backgroundColor);
|
|
891
893
|
g.fillRect(0, 0, this.canvas.width, this.canvas.height);
|
|
892
894
|
g.textBaseline = this.textBaseline;
|
|
893
895
|
|
|
@@ -902,14 +904,15 @@ export class WebLogoViewer extends DG.JsViewer implements IWebLogoViewer {
|
|
|
902
904
|
g.textAlign = 'center';
|
|
903
905
|
g.font = `${positionFontSize.toFixed(1)}px Roboto, Roboto Local, sans-serif`;
|
|
904
906
|
const posNameMaxWidth = Math.max(...this.positions.map((pos) => g.measureText(pos.name).width));
|
|
905
|
-
const hScale = posNameMaxWidth < (this._positionWidth - 2) ? 1 :
|
|
907
|
+
const hScale = posNameMaxWidth < (this._positionWidth * dpr - 2) ? 1 :
|
|
908
|
+
(this._positionWidth * dpr - 2) / posNameMaxWidth;
|
|
906
909
|
|
|
907
910
|
for (let jPos = this.firstVisibleIndex; jPos < lastVisibleIndex; jPos++) {
|
|
908
911
|
const pos: PositionInfo = this.positions[jPos];
|
|
909
912
|
g.resetTransform();
|
|
910
913
|
g.setTransform(
|
|
911
914
|
hScale, 0, 0, 1,
|
|
912
|
-
jPos * this.positionWidthWithMargin + this._positionWidth / 2 -
|
|
915
|
+
jPos * this.positionWidthWithMargin * dpr + this._positionWidth * dpr / 2 -
|
|
913
916
|
this.positionWidthWithMargin * firstVisibleIndex, 0);
|
|
914
917
|
g.fillText(pos.label, 0, 0);
|
|
915
918
|
}
|
|
@@ -1097,12 +1100,12 @@ export class WebLogoViewer extends DG.JsViewer implements IWebLogoViewer {
|
|
|
1097
1100
|
}
|
|
1098
1101
|
|
|
1099
1102
|
private canvasOnMouseMove(e: MouseEvent) {
|
|
1103
|
+
const dpr = window.devicePixelRatio;
|
|
1100
1104
|
try {
|
|
1101
1105
|
const args = e as MouseEvent;
|
|
1102
1106
|
|
|
1103
|
-
const dpr: number = window.devicePixelRatio;
|
|
1104
1107
|
const cursorP: DG.Point = this.canvas.getCursorPosition(args, dpr);
|
|
1105
|
-
const [jPos, monomer] = this.getMonomer(cursorP);
|
|
1108
|
+
const [jPos, monomer] = this.getMonomer(cursorP, dpr);
|
|
1106
1109
|
// if (jPos != undefined && monomer == undefined) {
|
|
1107
1110
|
// const preEl = ui.element('pre');
|
|
1108
1111
|
// preEl.innerHTML = jPos < this.positions.length ?
|
|
@@ -1133,8 +1136,8 @@ export class WebLogoViewer extends DG.JsViewer implements IWebLogoViewer {
|
|
|
1133
1136
|
private canvasOnMouseDown(e: MouseEvent): void {
|
|
1134
1137
|
try {
|
|
1135
1138
|
const args = e as MouseEvent;
|
|
1136
|
-
const
|
|
1137
|
-
const [jPos, monomer] = this.getMonomer(this.canvas.getCursorPosition(args,
|
|
1139
|
+
const dpr: number = window.devicePixelRatio;
|
|
1140
|
+
const [jPos, monomer] = this.getMonomer(this.canvas.getCursorPosition(args, dpr), dpr);
|
|
1138
1141
|
|
|
1139
1142
|
// prevents deselect all rows if we miss monomer bounds
|
|
1140
1143
|
if (this.dataFrame && this.seqCol && this.unitsHandler && monomer) {
|
|
@@ -5,6 +5,7 @@ import {_package} from '../package';
|
|
|
5
5
|
|
|
6
6
|
export class PackageSettingsEditorWidget extends DG.Widget {
|
|
7
7
|
maxMonomerLengthProp: DG.Property;
|
|
8
|
+
tooltipWebLogo: DG.Property;
|
|
8
9
|
|
|
9
10
|
constructor(propList: DG.Property[]) {
|
|
10
11
|
super(ui.div([], {}));
|
|
@@ -13,6 +14,7 @@ export class PackageSettingsEditorWidget extends DG.Widget {
|
|
|
13
14
|
Object.assign({}, ...propList.map((p) => ({[p.name]: p})));
|
|
14
15
|
|
|
15
16
|
this.maxMonomerLengthProp = props['MaxMonomerLength'];
|
|
17
|
+
this.tooltipWebLogo = props['TooltipWebLogo'];
|
|
16
18
|
}
|
|
17
19
|
|
|
18
20
|
async init(): Promise<void> {
|
|
@@ -23,6 +25,14 @@ export class PackageSettingsEditorWidget extends DG.Widget {
|
|
|
23
25
|
_package.properties.maxMonomerLength = value;
|
|
24
26
|
});
|
|
25
27
|
|
|
26
|
-
|
|
28
|
+
const tooltipWebLogo = ui.boolInput('Tooltip WebLogo',
|
|
29
|
+
_package.properties.tooltipWebLogo,
|
|
30
|
+
(value: boolean) => {
|
|
31
|
+
_package.properties.tooltipWebLogo = value;
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
this.root.appendChild(ui.form([
|
|
35
|
+
maxMonomerLengthInput,
|
|
36
|
+
tooltipWebLogo]));
|
|
27
37
|
}
|
|
28
38
|
}
|