@datagrok/sequence-translator 1.2.6 → 1.2.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. package/.eslintrc.json +5 -5
  2. package/CHANGELOG.md +12 -0
  3. package/dist/package-test.js +2 -1
  4. package/dist/package-test.js.LICENSE.txt +8 -0
  5. package/dist/package-test.js.map +1 -1
  6. package/dist/package.js +2 -1
  7. package/dist/package.js.LICENSE.txt +8 -0
  8. package/dist/package.js.map +1 -1
  9. package/files/pattern-app-data.json +80 -0
  10. package/package.json +21 -14
  11. package/src/{model → apps/common/model}/const.ts +1 -1
  12. package/src/{model/data-loading-utils → apps/common/model/data-loader}/const.ts +7 -2
  13. package/src/apps/common/model/data-loader/json-loader.ts +48 -0
  14. package/src/{model/data-loading-utils → apps/common/model/data-loader}/types.ts +13 -6
  15. package/src/{model → apps/common/model}/monomer-lib/lib-wrapper.ts +9 -12
  16. package/src/apps/common/model/oligo-toolkit-package.ts +30 -0
  17. package/src/{model → apps/common/model}/parsing-validation/format-detector.ts +5 -5
  18. package/src/{model → apps/common/model}/parsing-validation/format-handler.ts +18 -19
  19. package/src/{model → apps/common/model}/parsing-validation/sequence-validator.ts +1 -1
  20. package/src/apps/common/view/app-ui-base.ts +28 -0
  21. package/src/apps/common/view/combined-app-ui.ts +66 -0
  22. package/src/{view/utils → apps/common/view/components}/colored-input/colored-text-input.ts +1 -1
  23. package/src/{view/utils → apps/common/view/components}/draw-molecule.ts +1 -1
  24. package/src/{view/utils → apps/common/view/components}/molecule-img.ts +3 -3
  25. package/src/{view/const/ui.ts → apps/common/view/const.ts} +4 -4
  26. package/src/apps/common/view/isolated-app-ui.ts +43 -0
  27. package/src/{view/monomer-lib-viewer/viewer.ts → apps/common/view/monomer-lib-viewer.ts} +2 -2
  28. package/src/apps/common/view/utils.ts +29 -0
  29. package/src/apps/pattern/model/const.ts +121 -0
  30. package/src/apps/pattern/model/data-manager.ts +297 -0
  31. package/src/apps/pattern/model/event-bus.ts +470 -0
  32. package/src/apps/pattern/model/router.ts +46 -0
  33. package/src/apps/pattern/model/subscription-manager.ts +21 -0
  34. package/src/apps/pattern/model/translator.ts +68 -0
  35. package/src/apps/pattern/model/types.ts +52 -0
  36. package/src/apps/pattern/model/utils.ts +110 -0
  37. package/src/apps/pattern/view/components/bulk-convert/column-input.ts +69 -0
  38. package/src/apps/pattern/view/components/bulk-convert/table-controls.ts +37 -0
  39. package/src/apps/pattern/view/components/bulk-convert/table-input.ts +95 -0
  40. package/src/apps/pattern/view/components/edit-block-controls.ts +196 -0
  41. package/src/apps/pattern/view/components/left-section.ts +44 -0
  42. package/src/apps/pattern/view/components/load-block-controls.ts +198 -0
  43. package/src/apps/pattern/view/components/numeric-label-visibility-controls.ts +69 -0
  44. package/src/apps/pattern/view/components/right-section.ts +148 -0
  45. package/src/apps/pattern/view/components/strand-editor/dialog.ts +79 -0
  46. package/src/apps/pattern/view/components/strand-editor/header-controls.ts +105 -0
  47. package/src/apps/pattern/view/components/strand-editor/strand-controls.ts +159 -0
  48. package/src/apps/pattern/view/components/terminal-modification-editor.ts +127 -0
  49. package/src/apps/pattern/view/components/translation-examples-block.ts +139 -0
  50. package/src/{view/style/pattern-app.css → apps/pattern/view/style.css} +4 -0
  51. package/src/apps/pattern/view/svg-utils/const.ts +63 -0
  52. package/src/apps/pattern/view/svg-utils/dimensions-calculator.ts +498 -0
  53. package/src/apps/pattern/view/svg-utils/svg-display-manager.ts +45 -0
  54. package/src/apps/pattern/view/svg-utils/svg-element-factory.ts +82 -0
  55. package/src/apps/pattern/view/svg-utils/svg-renderer.ts +396 -0
  56. package/src/apps/pattern/view/svg-utils/utils.ts +37 -0
  57. package/src/apps/pattern/view/types.ts +14 -0
  58. package/src/apps/pattern/view/ui.ts +61 -0
  59. package/src/{model/structure-app → apps/structure/model}/mol-transformations.ts +3 -3
  60. package/src/{model/structure-app → apps/structure/model}/monomer-code-parser.ts +9 -10
  61. package/src/{model/structure-app → apps/structure/model}/oligo-structure.ts +4 -4
  62. package/src/{model/structure-app → apps/structure/model}/sequence-to-molfile.ts +2 -2
  63. package/src/{view/apps/oligo-structure.ts → apps/structure/view/ui.ts} +31 -17
  64. package/src/{model/translator-app → apps/translator/model}/conversion-utils.ts +25 -7
  65. package/src/{model/translator-app → apps/translator/model}/format-converter.ts +7 -12
  66. package/src/{view/const/oligo-translator.ts → apps/translator/view/const.ts} +2 -0
  67. package/src/apps/translator/view/ui.ts +547 -0
  68. package/src/demo/demo-st-ui.ts +12 -32
  69. package/src/package.ts +76 -56
  70. package/src/plugins/mermade.ts +9 -9
  71. package/src/polytool/const.ts +40 -0
  72. package/src/polytool/csv-to-json-monomer-lib-converter.ts +40 -0
  73. package/src/polytool/cyclized.ts +56 -0
  74. package/src/polytool/monomer-lib-handler.ts +115 -0
  75. package/src/polytool/transformation.ts +326 -0
  76. package/src/polytool/ui.ts +59 -0
  77. package/src/polytool/utils.ts +20 -0
  78. package/src/tests/const.ts +5 -5
  79. package/src/tests/formats-support.ts +6 -6
  80. package/src/tests/formats-to-helm.ts +5 -5
  81. package/src/tests/helm-to-nucleotides.ts +5 -5
  82. package/tsconfig.json +4 -10
  83. package/webpack.config.js +3 -0
  84. package/files/axolabs-style.json +0 -97
  85. package/src/model/data-loading-utils/json-loader.ts +0 -38
  86. package/src/model/pattern-app/const.ts +0 -33
  87. package/src/model/pattern-app/draw-svg.ts +0 -193
  88. package/src/model/pattern-app/helpers.ts +0 -96
  89. package/src/model/pattern-app/oligo-pattern.ts +0 -111
  90. package/src/view/app-ui.ts +0 -193
  91. package/src/view/apps/oligo-pattern.ts +0 -759
  92. package/src/view/apps/oligo-translator.ts +0 -184
  93. /package/src/{model → apps/common/model}/helpers.ts +0 -0
  94. /package/src/{model → apps/common/model}/monomer-lib/const.ts +0 -0
  95. /package/src/{view/utils → apps/common/view/components}/app-info-dialog.ts +0 -0
  96. /package/src/{view/utils → apps/common/view/components}/colored-input/input-painters.ts +0 -0
  97. /package/src/{view/style/colored-text-input.css → apps/common/view/components/colored-input/style.css} +0 -0
  98. /package/src/{view/utils → apps/common/view/components}/router.ts +0 -0
  99. /package/src/{model/structure-app → apps/structure/model}/const.ts +0 -0
  100. /package/src/{view/style/structure-app.css → apps/structure/view/style.css} +0 -0
  101. /package/src/{model/translator-app → apps/translator/model}/const.ts +0 -0
  102. /package/src/{view/style/translator-app.css → apps/translator/view/style.css} +0 -0
@@ -0,0 +1,80 @@
1
+ {
2
+ "Axolabs": {
3
+ "RNA": {
4
+ "color": "rgb(255,230,153)",
5
+ "substitution": "$1"
6
+ },
7
+ "DNA": {
8
+ "color": "rgb(66, 120, 245)",
9
+ "substitution": "d$1"
10
+ },
11
+ "2'-Fluoro": {
12
+ "color": "rgb(95, 212, 245)",
13
+ "substitution": "$1f"
14
+ },
15
+ "2'-O-Methyl": {
16
+ "color": "rgb(150, 95, 245)",
17
+ "substitution": "$1f"
18
+ },
19
+ "2'-O-MOE": {
20
+ "color": "rgb(129, 199, 130)",
21
+ "substitution": "$1m"
22
+ },
23
+ "GNA": {
24
+ "color": "rgb(199, 169, 129)",
25
+ "substitution": "(GNA-$1)"
26
+ },
27
+ "LNA": {
28
+ "color": "rgb(250, 185, 182)",
29
+ "substitution": "$1b"
30
+ },
31
+ "UNA": {
32
+ "color": "rgb(237, 104, 184)",
33
+ "substitution": "$1o"
34
+ },
35
+ "A": {
36
+ "color": "rgb(255,230,153)",
37
+ "substitution": "A"
38
+ },
39
+ "C": {
40
+ "color": "rgb(255,230,153)",
41
+ "substitution": "C"
42
+ },
43
+ "G": {
44
+ "color": "rgb(255,230,153)",
45
+ "substitution": "G"
46
+ },
47
+ "U": {
48
+ "color": "rgb(255,230,153)",
49
+ "substitution": "U"
50
+ },
51
+ "X-New": {
52
+ "color": "rgb(196, 91, 252)",
53
+ "substitution": "X"
54
+ },
55
+ "Y-New": {
56
+ "color": "rgb(150, 177, 255)",
57
+ "substitution": "Y"
58
+ },
59
+ "Z-New": {
60
+ "color": "rgb(11, 222, 71)",
61
+ "substitution": "Z"
62
+ },
63
+ "invAb": {
64
+ "color": "rgb(243, 153, 247)",
65
+ "substitution": "(invAb)"
66
+ },
67
+ "5'-vinylps": {
68
+ "color": "rgb(99, 3, 40)",
69
+ "substitution": "(vinu)"
70
+ },
71
+ "invAb(o)": {
72
+ "color": "rgb(240, 224, 108)",
73
+ "substitution": "(invAb)"
74
+ },
75
+ "2'-OMe-U(o)": {
76
+ "color": "rgb(190, 237, 123)",
77
+ "substitution": "mU"
78
+ }
79
+ }
80
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@datagrok/sequence-translator",
3
3
  "friendlyName": "Sequence Translator",
4
- "version": "1.2.6",
4
+ "version": "1.2.9",
5
5
  "author": {
6
6
  "name": "Alexey Choposky",
7
7
  "email": "achopovsky@datagrok.ai"
@@ -13,39 +13,45 @@
13
13
  "directory": "packages/SequenceTranslator"
14
14
  },
15
15
  "dependencies": {
16
- "@datagrok-libraries/bio": "^5.32.1",
17
- "@datagrok-libraries/chem-meta": "^1.0.9",
18
- "@datagrok-libraries/tutorials": "^1.3.2",
19
- "@datagrok-libraries/utils": "^1.17.2",
16
+ "@datagrok-libraries/bio": "^5.40.3",
17
+ "@datagrok-libraries/chem-meta": "^1.2.3",
18
+ "@datagrok-libraries/tutorials": "^1.3.12",
19
+ "@datagrok-libraries/utils": "^4.1.45",
20
20
  "@types/react": "^18.0.15",
21
21
  "cash-dom": "^8.1.0",
22
- "datagrok-api": "^1.15.2",
22
+ "datagrok-api": "^1.18.2",
23
+ "lodash": "^4.17.21",
24
+ "object-hash": "^3.0.0",
23
25
  "openchemlib": "6.0.1",
24
26
  "save-svg-as-png": "^1.4.17",
25
27
  "ts-loader": "^9.3.1",
26
- "typescript": "^4.7.4"
28
+ "typescript": "^5.4.2",
29
+ "typeahead-standalone": "4.14.1"
27
30
  },
28
31
  "devDependencies": {
29
- "@datagrok/bio": "^2.10.0",
30
- "@datagrok/chem": "1.7.2",
32
+ "@datagrok/bio": "^2.12.0",
33
+ "@datagrok/chem": "1.9.0",
31
34
  "@types/jquery": "^3.5.14",
32
35
  "@types/js-yaml": "^4.0.5",
36
+ "@types/lodash": "^4.14.202",
33
37
  "@types/node-fetch": "^2.6.2",
38
+ "@types/object-hash": "^3.0.6",
34
39
  "@types/react": "^18.0.15",
35
- "@typescript-eslint/eslint-plugin": "latest",
36
- "@typescript-eslint/parser": "parser",
40
+ "@typescript-eslint/eslint-plugin": "^7.2.0",
41
+ "@typescript-eslint/parser": "^7.2.0",
37
42
  "css-loader": "^6.7.3",
38
- "eslint": "^7.32.0",
43
+ "eslint": "^8.57.0",
39
44
  "eslint-config-google": "latest",
40
45
  "style-loader": "^3.3.1",
41
46
  "ts-loader": "^9.3.1",
42
47
  "typescript": "^4.7.4",
48
+ "typescript-eslint": "^7.2.0",
43
49
  "webpack": "^5.75.0",
44
50
  "webpack-cli": "latest"
45
51
  },
46
52
  "scripts": {
47
53
  "link-api": "npm link datagrok-api",
48
- "link-all": "npm link datagrok-api @datagrok-libraries/utils @datagrok-libraries/bio",
54
+ "link-all": "npm link @datagrok-libraries/chem-meta datagrok-api @datagrok-libraries/utils @datagrok-libraries/bio @datagrok-libraries/tutorials",
49
55
  "debug-sequencetranslator": "grok publish",
50
56
  "release-sequencetranslator": "grok publish localhost --release",
51
57
  "build-sequencetranslator": "webpack",
@@ -58,7 +64,8 @@
58
64
  "lint-fix": "eslint \"./src/**/*.ts\" --fix",
59
65
  "test": "grok test",
60
66
  "test-dev": "grok test --host dev",
61
- "test-local": "grok test --host localhost"
67
+ "test-local": "grok test --host localhost",
68
+ "build-all": "npm --prefix ./../../libraries/chem-meta run build && npm --prefix ./../../js-api run build && npm --prefix ./../../libraries/utils run build && npm --prefix ./../../libraries/bio run build && npm --prefix ./../../libraries/tutorials run build && npm run build"
62
69
  },
63
70
  "canEdit": [
64
71
  "Developers"
@@ -3,7 +3,7 @@ import * as grok from 'datagrok-api/grok';
3
3
  import * as ui from 'datagrok-api/ui';
4
4
  import * as DG from 'datagrok-api/dg';
5
5
 
6
- export const NUCLEOTIDES = ['A', 'G', 'C', 'U', 'T'];
6
+ export const NUCLEOTIDES = ['A', 'G', 'C', 'U'];
7
7
 
8
8
  export const TECHNOLOGIES = {
9
9
  DNA: 'DNA',
@@ -2,7 +2,12 @@ export const LIB_PATH = 'System:AppData/SequenceTranslator';
2
2
  export const DEFAULT_LIB_FILENAME = 'monomer-lib.json';
3
3
 
4
4
  export const APP_PATH = 'System:AppData/SequenceTranslator';
5
- export const AXOLABS_STYLE_FILENAME = 'axolabs-style.json';
5
+ export const PATTERN_APP_DATA_FILENAME = 'pattern-app-data.json';
6
6
  export const CODES_TO_HELM_DICT_FILENAME = 'formats-to-helm.json';
7
7
  export const CODES_TO_SYMBOLS_FILENAME = 'codes-to-symbols.json';
8
- export const MONOMERS_WITH_PHOSPHATE_LINKERS = 'linkers.json';
8
+ export const MONOMERS_WITH_PHOSPHATE_FILENAME = 'linkers.json';
9
+
10
+ export const enum MODIFICATION_DATA_FIELDS {
11
+ COLOR = 'color',
12
+ SUBSTITUTION = 'substitution',
13
+ }
@@ -0,0 +1,48 @@
1
+ /* Do not change these import lines to match external modules in webpack configuration */
2
+ import * as DG from 'datagrok-api/dg';
3
+
4
+ import {
5
+ APP_PATH, PATTERN_APP_DATA_FILENAME, CODES_TO_HELM_DICT_FILENAME,
6
+ CODES_TO_SYMBOLS_FILENAME, MONOMERS_WITH_PHOSPHATE_FILENAME
7
+ } from './const';
8
+ import {PatternAppData, CodeToSymbol, FormatToHELMDict} from './types';
9
+
10
+ const fileSource = new DG.FileSource(APP_PATH);
11
+
12
+ export let PATTERN_APP_DATA: PatternAppData;
13
+ export let CODES_TO_HELM_DICT: FormatToHELMDict;
14
+ export let CODES_TO_SYMBOLS_DICT: CodeToSymbol;
15
+ export let MONOMERS_WITH_PHOSPHATE: {[key: string]: string[]};
16
+
17
+ export async function loadJsonData(): Promise<void> {
18
+ if (isAllJsonDataLoaded())
19
+ return;
20
+
21
+ const jsonFileNames = [
22
+ PATTERN_APP_DATA_FILENAME, CODES_TO_HELM_DICT_FILENAME, CODES_TO_SYMBOLS_FILENAME, MONOMERS_WITH_PHOSPHATE_FILENAME
23
+ ];
24
+
25
+ [
26
+ PATTERN_APP_DATA,
27
+ CODES_TO_HELM_DICT,
28
+ CODES_TO_SYMBOLS_DICT,
29
+ MONOMERS_WITH_PHOSPHATE
30
+ ] = await Promise.all(
31
+ jsonFileNames.map((fileName) => loadAndParseJson(fileName))
32
+ );
33
+ }
34
+
35
+ async function loadAndParseJson(filePath: string): Promise<any> {
36
+ try {
37
+ const content = await fileSource.readAsText(filePath);
38
+ return JSON.parse(content);
39
+ } catch (err) {
40
+ console.error(`Error loading json from ${filePath}:`, err);
41
+ }
42
+ }
43
+
44
+ function isAllJsonDataLoaded(): boolean {
45
+ const data = [PATTERN_APP_DATA, CODES_TO_HELM_DICT, CODES_TO_SYMBOLS_DICT, MONOMERS_WITH_PHOSPHATE];
46
+
47
+ return data.every((item) => item !== undefined);
48
+ }
@@ -1,15 +1,22 @@
1
+ import {MODIFICATION_DATA_FIELDS as F} from './const';
2
+
1
3
  type KeyToValue = {[key: string]: string};
2
4
 
3
5
  export type Edges = {
4
6
  [key: string]: KeyToValue
5
7
  }
6
8
 
7
- export type AxolabsStyle = {
8
- [index: string]: {
9
- fullName: string,
10
- symbols: string[],
11
- color: string,
12
- }
9
+ export type ModificationData = {
10
+ [F.COLOR]: string,
11
+ [F.SUBSTITUTION]: string,
12
+ }
13
+
14
+ export type ModificationEntry = {
15
+ [modification: string]: ModificationData
16
+ }
17
+
18
+ export type PatternAppData = {
19
+ [format: string]: ModificationEntry
13
20
  };
14
21
 
15
22
  export type CodesInfo = {
@@ -1,16 +1,13 @@
1
- /* Do not change these import lines to match external modules in webpack configuration */
2
- import * as grok from 'datagrok-api/grok';
3
- import * as ui from 'datagrok-api/ui';
4
1
  import * as DG from 'datagrok-api/dg';
5
2
 
6
- import {_package} from '../../package';
3
+ import {_package} from '../../../../package';
7
4
  import {DEFAULT_FORMATS} from '../const';
8
5
 
9
6
  import {IMonomerLib, Monomer} from '@datagrok-libraries/bio/src/types';
7
+ import {HELM_REQUIRED_FIELD as REQ, HELM_OPTIONAL_FIELDS as OPT} from '@datagrok-libraries/bio/src/utils/const';
10
8
 
11
- import {HELM_REQUIRED_FIELDS as REQ, HELM_OPTIONAL_FIELDS as OPT} from '@datagrok-libraries/bio/src/utils/const';
12
9
  import {META_FIELDS as MET} from './const';
13
- import {codesToSymbolsDictionary} from '../../model/data-loading-utils/json-loader';
10
+ import {CODES_TO_SYMBOLS_DICT} from '../data-loader/json-loader';
14
11
 
15
12
  export class MonomerLibWrapper {
16
13
  private constructor() {
@@ -34,10 +31,10 @@ export class MonomerLibWrapper {
34
31
  formats.forEach((format) => {
35
32
  if (format === DEFAULT_FORMATS.HELM)
36
33
  return;
37
- const map = codesToSymbolsDictionary[format];
34
+ const map = CODES_TO_SYMBOLS_DICT[format];
38
35
  const codes = Object.keys(map).filter((code) => map[code] === sourceObj.symbol);
39
36
  formattedObject[format] = codes.join(', ');
40
- })
37
+ });
41
38
 
42
39
  return formattedObject;
43
40
  }
@@ -88,15 +85,15 @@ export class MonomerLibWrapper {
88
85
  }
89
86
 
90
87
  getCodeToSymbolMap(format: string): Map<string, string> {
91
- return new Map<string, string>(Object.entries(codesToSymbolsDictionary[format]));
88
+ return new Map<string, string>(Object.entries(CODES_TO_SYMBOLS_DICT[format]));
92
89
  }
93
90
 
94
91
  getCodesByFormat(format: string): string[] {
95
- return Object.keys(codesToSymbolsDictionary[format]);
92
+ return Object.keys(CODES_TO_SYMBOLS_DICT[format]);
96
93
  }
97
94
 
98
95
  getAllFormats(): string[] {
99
- return Object.keys(codesToSymbolsDictionary);
96
+ return Object.keys(CODES_TO_SYMBOLS_DICT);
100
97
  }
101
98
 
102
99
  getTableForViewer(): DG.DataFrame {
@@ -107,7 +104,7 @@ export class MonomerLibWrapper {
107
104
 
108
105
  getCodesToWeightsMap(): Map<string, number> {
109
106
  const codesToWeightsMap = new Map<string, number>();
110
- Object.entries(codesToSymbolsDictionary).forEach(([_, dict]) => {
107
+ Object.entries(CODES_TO_SYMBOLS_DICT).forEach(([_, dict]) => {
111
108
  Object.entries(dict).forEach(([code, monomerSymbol]) => {
112
109
  const monomer = this.getMonomer(monomerSymbol);
113
110
  const weight = monomer[OPT.META]?.[MET.MOLWEIGHT];
@@ -0,0 +1,30 @@
1
+ import * as DG from 'datagrok-api/dg';
2
+
3
+ import {getMonomerLibHelper, IMonomerLibHelper} from '@datagrok-libraries/bio/src/monomer-works/monomer-utils';
4
+ import {IMonomerLib} from '@datagrok-libraries/bio/src/types';
5
+
6
+ import {APP_NAME} from '../view/const';
7
+ import {DEFAULT_LIB_FILENAME, LIB_PATH} from './data-loader/const';
8
+ import {tryCatch} from './helpers';
9
+
10
+ export class OligoToolkitPackage extends DG.Package {
11
+ private _monomerLib?: IMonomerLib;
12
+
13
+ get monomerLib(): IMonomerLib {
14
+ if (!this._monomerLib)
15
+ throw new Error('Monomer lib not loaded');
16
+ return this._monomerLib!;
17
+ }
18
+
19
+ async initMonomerLib(): Promise<void> {
20
+ if (this._monomerLib !== undefined)
21
+ return;
22
+
23
+ const pi: DG.TaskBarProgressIndicator = DG.TaskBarProgressIndicator.create(
24
+ `Initializing ${APP_NAME.COMBINED} monomer library ...`);
25
+ await tryCatch(async () => {
26
+ const libHelper: IMonomerLibHelper = await getMonomerLibHelper();
27
+ this._monomerLib = await libHelper.readLibrary(LIB_PATH, DEFAULT_LIB_FILENAME);
28
+ }, () => pi.close());
29
+ }
30
+ }
@@ -6,13 +6,13 @@ import * as DG from 'datagrok-api/dg';
6
6
  import {sortByReverseLength} from '../helpers';
7
7
  import {DEFAULT_FORMATS} from '../const';
8
8
  import {MonomerLibWrapper} from '../monomer-lib/lib-wrapper';
9
- import {codesToHelmDictionary} from '../data-loading-utils/json-loader';
9
+ import {CODES_TO_HELM_DICT} from '../data-loader/json-loader';
10
10
  import {SequenceValidator} from './sequence-validator';
11
11
 
12
12
  export class FormatDetector {
13
- constructor (private sequence: string) {
13
+ constructor(private sequence: string) {
14
14
  this.libWrapper = MonomerLibWrapper.getInstance();
15
- this.formats = Object.keys(codesToHelmDictionary);
15
+ this.formats = Object.keys(CODES_TO_HELM_DICT);
16
16
  };
17
17
 
18
18
  private libWrapper: MonomerLibWrapper;
@@ -39,9 +39,9 @@ export class FormatDetector {
39
39
  // todo: rename
40
40
  private getListOfPossibleSynthesizersByFirstMatchedCode(): string[] {
41
41
  const sequence = this.sequence;
42
- let synthesizers: string[] = [];
42
+ const synthesizers: string[] = [];
43
43
  for (const format of this.formats) {
44
- let codes = sortByReverseLength(this.libWrapper.getCodesByFormat(format));
44
+ const codes = sortByReverseLength(this.libWrapper.getCodesByFormat(format));
45
45
  let start = 0;
46
46
  for (let i = 0; i < sequence.length; i++) {
47
47
  if (sequence[i] === ')' && i !== sequence.length - 1) {
@@ -3,10 +3,10 @@ import * as grok from 'datagrok-api/grok';
3
3
  import * as ui from 'datagrok-api/ui';
4
4
  import * as DG from 'datagrok-api/dg';
5
5
 
6
- import {codesToHelmDictionary} from '../data-loading-utils/json-loader';
7
- import {CodesInfo} from '../data-loading-utils/types';
6
+ import {CODES_TO_HELM_DICT} from '../data-loader/json-loader';
7
+ import {CodesInfo} from '../data-loader/types';
8
8
  import {DEFAULT_FORMATS} from '../const';
9
- import {GROUP_TYPE, PHOSPHATE_SYMBOL} from '../translator-app/const';
9
+ import {GROUP_TYPE, PHOSPHATE_SYMBOL} from '../../../translator/model/const';
10
10
 
11
11
  const inverseLengthComparator = (a: string, b: string) => b.length - a.length;
12
12
 
@@ -34,7 +34,7 @@ export class FormatHandler {
34
34
  getHelmToFormatDict(format: string): {[key: string]: string} {
35
35
  this.validateFormat(format);
36
36
 
37
- const codesInfoObject = codesToHelmDictionary[format] as CodesInfo;
37
+ const codesInfoObject = CODES_TO_HELM_DICT[format] as CodesInfo;
38
38
  const dict = getHelmToCodeDict(codesInfoObject);
39
39
  return dict;
40
40
  }
@@ -42,7 +42,7 @@ export class FormatHandler {
42
42
  getFormatToHelmDict(format: string): {[key: string]: string} {
43
43
  this.validateFormat(format);
44
44
 
45
- const codesInfoObject = codesToHelmDictionary[format] as CodesInfo;
45
+ const codesInfoObject = CODES_TO_HELM_DICT[format] as CodesInfo;
46
46
  const dict = Object.assign({}, ...Object.values(codesInfoObject)) as {[code: string]: string};
47
47
  return dict;
48
48
  }
@@ -75,7 +75,7 @@ export class FormatHandler {
75
75
  getPhosphateHelmCodesRegExp(format: string): RegExp {
76
76
  this.validateFormat(format);
77
77
 
78
- const codesInfoObject = codesToHelmDictionary[format] as CodesInfo;
78
+ const codesInfoObject = CODES_TO_HELM_DICT[format] as CodesInfo;
79
79
  const phosphateHELMCodes = Array.from(
80
80
  new Set(Object.values(codesInfoObject[GROUP_TYPE.LINKAGE]))
81
81
  ).sort(inverseLengthComparator);
@@ -89,7 +89,7 @@ export class FormatHandler {
89
89
  }
90
90
 
91
91
  private getFormats(): string[] {
92
- return Object.keys(codesToHelmDictionary);
92
+ return Object.keys(CODES_TO_HELM_DICT);
93
93
  }
94
94
 
95
95
  private validateFormat(format: string) {
@@ -106,7 +106,7 @@ export class FormatHandler {
106
106
  const formatCodes = Object.keys(dict).sort(inverseLengthComparator);
107
107
  return formatCodes;
108
108
  }
109
-
109
+
110
110
  private getNonHelmFormatRegExp(format: string): RegExp {
111
111
  const formatCodes = this.getCodesByFormat(format);
112
112
  const formatRegExp = new RegExp(getRegExpPattern(formatCodes) + '|\\([^()]*\\)|.', 'g'); // the added group before '|.' is to avoid mismatch inside parenths
@@ -116,14 +116,14 @@ export class FormatHandler {
116
116
 
117
117
  export function getRegExpPattern(arr: string[]): string {
118
118
  const negativeLookBehind = '(?<!\\([^()]*)'; // not '(' followed by non-parenths
119
- const negativeLookAhead = '(?![^()]*\\))'; // not ')' preceded by non-parenths
119
+ const negativeLookAhead = '(?![^()]*\\))'; // not ')' preceded by non-parenths
120
120
  const escaped = arr.map((key) => key.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'))
121
121
  .map((key) => {
122
- if (!key.includes('(') && !key.includes(')'))
123
- return `${negativeLookBehind}${key}${negativeLookAhead}`;
124
- return key;
125
- });
126
- const result = escaped.join('|');
122
+ if (!key.includes('(') && !key.includes(')'))
123
+ return `${negativeLookBehind}${key}${negativeLookAhead}`;
124
+ return key;
125
+ });
126
+ const result = escaped.join('|');
127
127
  return result;
128
128
  }
129
129
 
@@ -132,16 +132,15 @@ function getHelmToCodeDict(infoObj: CodesInfo) {
132
132
  Object.values(infoObj).forEach((obj: {[code: string]: string}) => {
133
133
  Object.entries(obj).forEach(([code, helm]) => {
134
134
  const key = helm.replace(/\)p/g, ')').replace(/\]p/g, ']');
135
- if (result[key] === undefined) {
135
+ if (result[key] === undefined)
136
136
  result[key] = [code];
137
- } else {
137
+ else
138
138
  (result[key] as string[]).push(code);
139
- }
140
- })
139
+ });
141
140
  });
142
141
  Object.entries(result).forEach(([key, value]) => {
143
142
  const sorted = (value as string[]).sort(inverseLengthComparator);
144
143
  result[key] = sorted[0] as string;
145
- })
144
+ });
146
145
  return result as {[key: string]: string};
147
146
  }
@@ -42,7 +42,7 @@ export class SequenceValidator {
42
42
  indexOfFirstInvalidChar += matchedCode.length;
43
43
  }
44
44
  if (indexOfFirstInvalidChar === this.sequence.length)
45
- indexOfFirstInvalidChar = -1
45
+ indexOfFirstInvalidChar = -1;
46
46
  return indexOfFirstInvalidChar;
47
47
  }
48
48
 
@@ -0,0 +1,28 @@
1
+ /* Do not change these import lines to match external modules in webpack configuration */
2
+ import * as DG from 'datagrok-api/dg';
3
+ import * as grok from 'datagrok-api/grok';
4
+ import * as ui from 'datagrok-api/ui';
5
+
6
+ export abstract class AppUIBase {
7
+ constructor(protected appName: string, protected parentAppName?: string) { }
8
+ protected abstract constructView(): Promise<DG.ViewBase>;
9
+
10
+ async getAppView(): Promise<DG.ViewBase> {
11
+ const progressIndicator: DG.TaskBarProgressIndicator =
12
+ DG.TaskBarProgressIndicator.create(`Loading ${this.appName}...`);
13
+
14
+ const currentView = grok.shell.v?.root;
15
+ if (currentView)
16
+ ui.setUpdateIndicator(currentView, true);
17
+
18
+ try {
19
+ const view = await this.constructView();
20
+ return view;
21
+ } finally {
22
+ progressIndicator.close();
23
+ if (currentView)
24
+ ui.setUpdateIndicator(currentView, false);
25
+ }
26
+ }
27
+ }
28
+
@@ -0,0 +1,66 @@
1
+ /* Do not change these import lines to match external modules in webpack configuration */
2
+ import * as DG from 'datagrok-api/dg';
3
+ import * as grok from 'datagrok-api/grok';
4
+
5
+ import {_package} from '../../../package';
6
+ import {OligoPatternUI} from '../../pattern/view/ui';
7
+ import {OligoStructureUI} from '../../structure/view/ui';
8
+ import {OligoTranslatorUI} from '../../translator/view/ui';
9
+ import {AppUIBase} from './app-ui-base';
10
+ import {IsolatedAppUIBase} from './isolated-app-ui';
11
+ import {APP_NAME, TAB_NAME} from './const';
12
+
13
+ type ViewFactories = {[name: string]: () => DG.View};
14
+
15
+ export class CombinedAppUI extends AppUIBase {
16
+ constructor(externalViewFactories: ViewFactories) {
17
+ super(APP_NAME.COMBINED);
18
+ this.externalViewFactories = externalViewFactories;
19
+ const factories = this.getViewFactories();
20
+ this.multiView = new DG.MultiView({viewFactories: factories});
21
+ }
22
+
23
+ private multiView: DG.MultiView;
24
+ private externalViewFactories?: ViewFactories;
25
+
26
+
27
+ private getViewFactories(): ViewFactories {
28
+ function viewFactory(UiConstructor: new (view: DG.View) => IsolatedAppUIBase): () => DG.View {
29
+ const view = DG.View.create();
30
+ const translateUI = new UiConstructor(view);
31
+ translateUI.initView().catch(
32
+ (e) => console.error(`Failed to initialize ${UiConstructor.name}: ${e}`)
33
+ );
34
+ return () => translateUI.getView();
35
+ }
36
+
37
+ let result: {[key: string]: () => DG.View } = {
38
+ [TAB_NAME.TRANSLATOR]: viewFactory(OligoTranslatorUI),
39
+ [TAB_NAME.PATTERN]: viewFactory(OligoPatternUI),
40
+ [TAB_NAME.STRUCTURE]: viewFactory(OligoStructureUI),
41
+ };
42
+
43
+ if (this.externalViewFactories)
44
+ result = Object.assign({}, result, this.externalViewFactories);
45
+
46
+ return result;
47
+ }
48
+
49
+ private getCurrentPanePath(): string {
50
+ let name = this.multiView.tabs.currentPane.name;
51
+ name = name.charAt(0).toUpperCase() + name.substring(1).toLowerCase();
52
+ const path = `/apps/${_package.name}/OligoToolkit/${name}`;
53
+ return path;
54
+ }
55
+
56
+ private setUrl(): void {
57
+ this.multiView.path = this.getCurrentPanePath();
58
+ }
59
+
60
+ protected async constructView(): Promise<DG.ViewBase> {
61
+ this.multiView.tabs.onTabChanged.subscribe(() => this.setUrl());
62
+ this.setUrl();
63
+ return this.multiView;
64
+ }
65
+ }
66
+
@@ -7,7 +7,7 @@ import * as DG from 'datagrok-api/dg';
7
7
  import $ from 'cash-dom';
8
8
 
9
9
  // inner dependencies
10
- import '../../style/colored-text-input.css';
10
+ import './style.css';
11
11
 
12
12
 
13
13
  /** Class for colorizing input in the textarea of DG.InputBase. */
@@ -6,7 +6,7 @@ import {errorToConsole} from '@datagrok-libraries/utils/src/to-console';
6
6
 
7
7
  import $ from 'cash-dom';
8
8
 
9
- import {extractAtomDataV3000} from '../../model/structure-app/mol-transformations';
9
+ import {extractAtomDataV3000} from '../../../structure/model/mol-transformations';
10
10
 
11
11
  /** Draw molecule on the canvas and append it to the specified div, with the
12
12
  * option of zoom-in */
@@ -64,7 +64,7 @@ export class MoleculeImage {
64
64
  }
65
65
 
66
66
  private async zoomIn(): Promise<void> {
67
- const dialog = ui.dialog({title: 'Molecule', showFooter:false});
67
+ const dialog = ui.dialog({title: 'Molecule', showFooter: false});
68
68
  const dialogDivStyle = {
69
69
  overflowX: 'scroll',
70
70
  };
@@ -79,7 +79,7 @@ export class MoleculeImage {
79
79
 
80
80
  const dialogCanvas = ui.canvas(dialogCanvasWidth, dialogCanvasHeight);
81
81
  await this.drawMolBlockOnCanvas(dialogCanvas);
82
-
82
+
83
83
  const dialogDiv = ui.block([dialogCanvas], {style: dialogDivStyle});
84
84
  dialog.add(dialogDiv).showModal(true);
85
85
 
@@ -117,6 +117,6 @@ export class MoleculeImage {
117
117
  //$(canvas).on('mouseover', () => $(canvas).css('cursor', 'grab')); // for some reason 'zoom-in' value wouldn't work
118
118
  //$(canvas).on('mouseout', () => $(canvas).css('cursor', 'default'));
119
119
 
120
- moleculeImgDiv.append(ui.tooltip.bind(canvas,'Click to zoom'));
120
+ moleculeImgDiv.append(ui.tooltip.bind(canvas, 'Click to zoom'));
121
121
  }
122
122
  }
@@ -1,14 +1,14 @@
1
- export const enum TAB {
1
+ export const enum TAB_NAME {
2
2
  TRANSLATOR = 'TRANSLATOR',
3
3
  PATTERN = 'PATTERN',
4
- STRUCTRE = 'STRUCTURE'
4
+ STRUCTURE = 'STRUCTURE'
5
5
  }
6
6
 
7
- export const enum APP {
7
+ export const enum APP_NAME {
8
8
  COMBINED = 'Oligo Toolkit',
9
9
  TRANSLATOR = 'Oligo Translator',
10
10
  PATTERN = 'Oligo Pattern',
11
- STRUCTRE = 'Oligo Structure',
11
+ STRUCTURE = 'Oligo Structure',
12
12
  }
13
13
 
14
14
  export const DEFAULT_AXOLABS_INPUT = 'Afcgacsu';