@datagrok/sequence-translator 1.2.3 → 1.2.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1 -1
- 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 +1 -1
- package/src/package.ts +4 -0
- package/src/view/apps/oligo-pattern.ts +69 -109
- package/src/view/apps/oligo-structure.ts +4 -3
- package/src/view/apps/oligo-translator.ts +8 -2
- package/src/view/style/translator-app.css +2 -2
package/package.json
CHANGED
package/src/package.ts
CHANGED
|
@@ -51,6 +51,7 @@ async function buildLayout(appName: string): Promise<void> {
|
|
|
51
51
|
|
|
52
52
|
//name: Oligo Toolkit
|
|
53
53
|
//meta.icon: img/icons/toolkit.png
|
|
54
|
+
//meta.browsePath: Oligo
|
|
54
55
|
//tags: app
|
|
55
56
|
export async function oligoToolkitApp(): Promise<void> {
|
|
56
57
|
await initSequenceTranslatorLibData();
|
|
@@ -63,6 +64,7 @@ export async function oligoToolkitApp(): Promise<void> {
|
|
|
63
64
|
|
|
64
65
|
//name: Oligo Translator
|
|
65
66
|
//meta.icon: img/icons/translator.png
|
|
67
|
+
//meta.browsePath: Oligo
|
|
66
68
|
//tags: app
|
|
67
69
|
export async function oligoTranslatorApp(): Promise<void> {
|
|
68
70
|
await buildLayout(APP.TRANSLATOR);
|
|
@@ -70,6 +72,7 @@ export async function oligoTranslatorApp(): Promise<void> {
|
|
|
70
72
|
|
|
71
73
|
//name: Oligo Pattern
|
|
72
74
|
//meta.icon: img/icons/pattern.png
|
|
75
|
+
//meta.browsePath: Oligo
|
|
73
76
|
//tags: app
|
|
74
77
|
export async function oligoPatternApp(): Promise<void> {
|
|
75
78
|
await buildLayout(APP.PATTERN);
|
|
@@ -77,6 +80,7 @@ export async function oligoPatternApp(): Promise<void> {
|
|
|
77
80
|
|
|
78
81
|
//name: Oligo Structure
|
|
79
82
|
//meta.icon: img/icons/structure.png
|
|
83
|
+
//meta.browsePath: Oligo
|
|
80
84
|
//tags: app
|
|
81
85
|
export async function oligoStructureApp(): Promise<void> {
|
|
82
86
|
await buildLayout(APP.STRUCTRE);
|
|
@@ -5,7 +5,7 @@ import * as DG from 'datagrok-api/dg';
|
|
|
5
5
|
|
|
6
6
|
import {axolabsStyleMap} from '../../model/data-loading-utils/json-loader';
|
|
7
7
|
import {
|
|
8
|
-
DEFAULT_PTO, DEFAULT_SEQUENCE_LENGTH, MAX_SEQUENCE_LENGTH, USER_STORAGE_KEY,
|
|
8
|
+
DEFAULT_PTO, DEFAULT_SEQUENCE_LENGTH, MAX_SEQUENCE_LENGTH, USER_STORAGE_KEY, SS, AS, STRAND_NAME, STRANDS, TERMINAL, TERMINAL_KEYS, THREE_PRIME, FIVE_PRIME, JSON_FIELD as FIELD
|
|
9
9
|
} from '../../model/pattern-app/const';
|
|
10
10
|
import {isOverhang} from '../../model/pattern-app/helpers';
|
|
11
11
|
import {generateExample, translateSequence, getShortName, isCurrentUserCreatedThisPattern, findDuplicates, addColumnWithIds, addColumnWithTranslatedSequences} from '../../model//pattern-app/oligo-pattern';
|
|
@@ -107,7 +107,7 @@ export class PatternLayoutHandler {
|
|
|
107
107
|
|
|
108
108
|
function updateInputExamples() {
|
|
109
109
|
STRANDS.forEach((s) => {
|
|
110
|
-
if (
|
|
110
|
+
if (strandColumnInput[s].value === '')
|
|
111
111
|
inputExample[s].value = generateExample(strandLengthInput[s].value!, sequenceBase.value!);
|
|
112
112
|
});
|
|
113
113
|
}
|
|
@@ -211,7 +211,7 @@ export class PatternLayoutHandler {
|
|
|
211
211
|
}
|
|
212
212
|
|
|
213
213
|
function allColumnValuesOfEqualLength(colName: string): boolean {
|
|
214
|
-
const col =
|
|
214
|
+
const col = tableInput.value!.getCol(colName);
|
|
215
215
|
let allLengthsAreTheSame = true;
|
|
216
216
|
for (let i = 1; i < col.length; i++) {
|
|
217
217
|
if (col.get(i - 1).length !== col.get(i).length && col.get(i).length !== 0) {
|
|
@@ -226,14 +226,14 @@ export class PatternLayoutHandler {
|
|
|
226
226
|
.add(ui.divText('The sequence length should match the number of Raw sequences in the input file'))
|
|
227
227
|
.add(ui.divText('\'ADD COLUMN\' to see sequences lengths'))
|
|
228
228
|
.addButton('ADD COLUMN', () => {
|
|
229
|
-
|
|
230
|
-
grok.shell.info('Column with lengths added to \'' +
|
|
229
|
+
tableInput.value!.columns.addNewInt('Sequences lengths in ' + colName).init((j: number) => col.get(j).length);
|
|
230
|
+
grok.shell.info('Column with lengths added to \'' + tableInput.value!.name + '\'');
|
|
231
231
|
dialog.close();
|
|
232
|
-
grok.shell.v = grok.shell.getTableView(
|
|
232
|
+
grok.shell.v = grok.shell.getTableView(tableInput.value!.name);
|
|
233
233
|
})
|
|
234
234
|
.show();
|
|
235
235
|
}
|
|
236
|
-
if (col.get(0) !== strandLengthInput[SS].value) {
|
|
236
|
+
if (col.get(0).length !== strandLengthInput[SS].value) {
|
|
237
237
|
const d = ui.dialog('Length was updated by value to from imported file');
|
|
238
238
|
d.add(ui.divText('Latest modifications may not take effect during translation'))
|
|
239
239
|
.onOK(() => grok.shell.info('Lengths changed')).show();
|
|
@@ -367,25 +367,26 @@ export class PatternLayoutHandler {
|
|
|
367
367
|
|
|
368
368
|
function validateStrandColumn(colName: string, strand: string): void {
|
|
369
369
|
const allLengthsAreTheSame: boolean = allColumnValuesOfEqualLength(colName);
|
|
370
|
-
const firstSequence =
|
|
370
|
+
const firstSequence = tableInput.value!.getCol(colName).get(0);
|
|
371
371
|
if (allLengthsAreTheSame && firstSequence.length !== strandLengthInput[strand].value)
|
|
372
|
-
strandLengthInput[strand].value =
|
|
372
|
+
strandLengthInput[strand].value = tableInput.value!.getCol(colName).get(0).length;
|
|
373
373
|
inputExample[strand].value = firstSequence;
|
|
374
374
|
}
|
|
375
375
|
|
|
376
376
|
function validateIdsColumn(colName: string) {
|
|
377
|
-
const col =
|
|
377
|
+
const col = tableInput.value!.getCol(colName);
|
|
378
378
|
if (col.type !== DG.TYPE.INT)
|
|
379
379
|
grok.shell.error('Column should contain integers only');
|
|
380
|
+
//@ts-ignore
|
|
380
381
|
else if (col.categories.filter((e) => e !== '').length < col.toList().filter((e) => e !== '').length) {
|
|
381
382
|
const duplicates = findDuplicates(col.getRawData());
|
|
382
383
|
ui.dialog('Non-unique IDs')
|
|
383
384
|
.add(ui.divText('Press \'OK\' to select rows with non-unique values'))
|
|
384
385
|
.onOK(() => {
|
|
385
|
-
const selection =
|
|
386
|
+
const selection = tableInput.value!.selection;
|
|
386
387
|
selection.init((i: number) => duplicates.indexOf(col.get(i)) > -1);
|
|
387
|
-
grok.shell.v = grok.shell.getTableView(
|
|
388
|
-
grok.shell.info('Rows are selected in table \'' +
|
|
388
|
+
grok.shell.v = grok.shell.getTableView(tableInput.value!.name);
|
|
389
|
+
grok.shell.info('Rows are selected in table \'' + tableInput.value!.name + '\'');
|
|
389
390
|
})
|
|
390
391
|
.show();
|
|
391
392
|
}
|
|
@@ -435,23 +436,16 @@ export class PatternLayoutHandler {
|
|
|
435
436
|
return [strand, input];
|
|
436
437
|
}));
|
|
437
438
|
const strandVar = Object.fromEntries(STRANDS.map((strand) => [strand, '']));
|
|
438
|
-
// todo: rename to strandColumnInputDiv
|
|
439
|
-
const inputStrandColumnDiv = Object.fromEntries(STRANDS.map(
|
|
440
|
-
(strand) => [strand, ui.div([])]
|
|
441
|
-
));
|
|
442
439
|
const inputExample = Object.fromEntries(STRANDS.map(
|
|
443
440
|
(strand) => [strand, ui.textInput(
|
|
444
441
|
``, generateExample(strandLengthInput[strand].value!, sequenceBase.value!))
|
|
445
442
|
]));
|
|
446
443
|
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
const input: StringInput = ui.choiceInput(`${STRAND_NAME[strand]} column`, '', [], (colName: string) => {
|
|
444
|
+
const strandColumnInput = Object.fromEntries(STRANDS.map((strand) => {
|
|
445
|
+
const input = ui.choiceInput(`${STRAND_NAME[strand]} column`, '', [], (colName: string) => {
|
|
450
446
|
validateStrandColumn(colName, strand);
|
|
451
447
|
strandVar[strand] = colName;
|
|
452
448
|
});
|
|
453
|
-
inputStrandColumnDiv[strand].append(input.root);
|
|
454
|
-
//input.addPostfix(``);
|
|
455
449
|
return [strand, input];
|
|
456
450
|
}));
|
|
457
451
|
|
|
@@ -464,8 +458,6 @@ export class PatternLayoutHandler {
|
|
|
464
458
|
input.captionLabel.style.maxWidth = '100px';
|
|
465
459
|
input.captionLabel.style.minWidth = '40px';
|
|
466
460
|
input.captionLabel.style.width = 'auto';
|
|
467
|
-
|
|
468
|
-
|
|
469
461
|
|
|
470
462
|
return [strand, input];
|
|
471
463
|
}));
|
|
@@ -508,9 +500,7 @@ export class PatternLayoutHandler {
|
|
|
508
500
|
STRANDS.forEach((s) => {
|
|
509
501
|
|
|
510
502
|
inputExample[s].input.style.resize = 'none';
|
|
511
|
-
//inputExample[s].input.style.minWidth = EXAMPLE_MIN_WIDTH;
|
|
512
503
|
outputExample[s].input.style.resize = 'none';
|
|
513
|
-
//outputExample[s].input.styl
|
|
514
504
|
inputExample[s].input.style.minWidth = 'none';
|
|
515
505
|
inputExample[s].input.style.flexGrow = '1';
|
|
516
506
|
outputExample[s].input.style.minWidth = 'none';
|
|
@@ -527,10 +517,9 @@ export class PatternLayoutHandler {
|
|
|
527
517
|
);
|
|
528
518
|
})
|
|
529
519
|
|
|
530
|
-
const inputIdColumnDiv = ui.div([]);
|
|
520
|
+
// const inputIdColumnDiv = ui.div([]);
|
|
531
521
|
const svgDiv = ui.div([]);
|
|
532
522
|
const asExampleDiv = ui.div([], 'ui-form ui-form-wide');
|
|
533
|
-
const appAxolabsDescription = ui.div([]);
|
|
534
523
|
const loadPatternDiv = ui.div([]);
|
|
535
524
|
const asModificationDiv = ui.form([]);
|
|
536
525
|
const isEnumerateModificationsDiv = ui.divH([
|
|
@@ -550,25 +539,45 @@ export class PatternLayoutHandler {
|
|
|
550
539
|
|
|
551
540
|
const asLengthDiv = ui.div([strandLengthInput[AS].root]);
|
|
552
541
|
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
542
|
+
function getTableInput(tableList: DG.DataFrame[]): DG.InputBase {
|
|
543
|
+
const tableInput = ui.tableInput('Tables', tableList[0], tableList, () => {
|
|
544
|
+
const table = tableInput.value;
|
|
545
|
+
if (table === null) {
|
|
546
|
+
console.warn('Table is null');
|
|
547
|
+
return;
|
|
548
|
+
}
|
|
549
|
+
const tableName = table!.name;
|
|
550
|
+
if (!grok.shell.tableNames.includes(tableName)) {
|
|
551
|
+
const view = grok.shell.v;
|
|
552
|
+
grok.shell.addTableView(table!);
|
|
553
|
+
grok.shell.v = view;
|
|
554
|
+
}
|
|
555
|
+
const columnNames = table.columns.names();
|
|
556
|
+
|
|
557
|
+
STRANDS.forEach((strand) => {
|
|
558
|
+
const defaultColumn = columnNames[0];
|
|
559
|
+
validateStrandColumn(defaultColumn, strand);
|
|
560
|
+
strandVar[strand] = defaultColumn;
|
|
561
|
+
const input = ui.choiceInput(`${STRAND_NAME[strand]} column`, defaultColumn, columnNames, (colName: string) => {
|
|
562
|
+
validateStrandColumn(colName, strand);
|
|
563
|
+
strandVar[strand] = colName;
|
|
564
|
+
console.log(`clicked ${strand} var:`, strandVar[strand]);
|
|
565
|
+
});
|
|
566
|
+
$(strandColumnInput[strand].root).replaceWith(input.root);
|
|
567
|
+
})
|
|
562
568
|
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
569
|
+
idVar = columnNames[0];
|
|
570
|
+
// todo: unify with inputStrandColumn
|
|
571
|
+
const idInput = ui.choiceInput('ID column', columnNames[0], columnNames, (colName: string) => {
|
|
572
|
+
validateIdsColumn(colName);
|
|
573
|
+
idVar = colName;
|
|
574
|
+
});
|
|
575
|
+
$(inputIdColumn.root).replaceWith(idInput.root);
|
|
567
576
|
});
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
});
|
|
577
|
+
return tableInput;
|
|
578
|
+
}
|
|
571
579
|
|
|
580
|
+
const tableInput = getTableInput([]);
|
|
572
581
|
|
|
573
582
|
// todo: unify with strandVar
|
|
574
583
|
let idVar = '';
|
|
@@ -576,13 +585,13 @@ export class PatternLayoutHandler {
|
|
|
576
585
|
validateIdsColumn(colName);
|
|
577
586
|
idVar = colName;
|
|
578
587
|
});
|
|
579
|
-
inputIdColumnDiv.append(inputIdColumn.root);
|
|
588
|
+
// inputIdColumnDiv.append(inputIdColumn.root);
|
|
580
589
|
|
|
581
590
|
updatePatternsList();
|
|
582
591
|
|
|
583
592
|
const createAsStrand = ui.boolInput('Anti sense strand', true, (v: boolean) => {
|
|
584
593
|
modificationSection[AS].hidden = !v;
|
|
585
|
-
|
|
594
|
+
strandColumnInput[AS].root.hidden = !v;
|
|
586
595
|
asLengthDiv.hidden = !v;
|
|
587
596
|
asModificationDiv.hidden = !v;
|
|
588
597
|
asExampleDiv.hidden = !v;
|
|
@@ -619,6 +628,7 @@ export class PatternLayoutHandler {
|
|
|
619
628
|
|
|
620
629
|
const convertSequenceButton = ui.bigButton('Convert', () => {
|
|
621
630
|
const condition = [true, createAsStrand.value];
|
|
631
|
+
console.log(`strand vars:`, Object.values(strandVar));
|
|
622
632
|
if (STRANDS.some((s, i) => condition[i] && strandVar[s] === ''))
|
|
623
633
|
grok.shell.info('Please select table and columns on which to apply pattern');
|
|
624
634
|
else if (STRANDS.some((s) => strandLengthInput[s].value !== inputExample[s].value.length)) {
|
|
@@ -628,24 +638,24 @@ export class PatternLayoutHandler {
|
|
|
628
638
|
.add(ui.divText('Length of sequences in columns doesn\'t match entered length. Update length value?'))
|
|
629
639
|
.addButton('YES', () => {
|
|
630
640
|
STRANDS.forEach((s) => {
|
|
631
|
-
strandLengthInput[s].value =
|
|
641
|
+
strandLengthInput[s].value = tableInput.value!.getCol(strandColumnInput[s].value!).getString(0).length;
|
|
632
642
|
})
|
|
633
643
|
dialog.close();
|
|
634
644
|
})
|
|
635
645
|
.show();
|
|
636
646
|
} else {
|
|
637
647
|
if (idVar !== '')
|
|
638
|
-
addColumnWithIds(
|
|
648
|
+
addColumnWithIds(tableInput.value!.name, idVar, getShortName(saveAs.value));
|
|
639
649
|
const condition = [true, createAsStrand.value];
|
|
640
650
|
STRANDS.forEach((strand, i) => {
|
|
641
651
|
if (condition[i])
|
|
642
652
|
addColumnWithTranslatedSequences(
|
|
643
|
-
|
|
653
|
+
tableInput.value!.name, strandVar[strand], baseInputsObject[strand], ptoLinkages[strand],
|
|
644
654
|
terminalModification[strand][FIVE_PRIME], terminalModification[strand][THREE_PRIME], firstPto[strand].value!);
|
|
645
655
|
})
|
|
646
|
-
grok.shell.v = grok.shell.getTableView(
|
|
656
|
+
grok.shell.v = grok.shell.getTableView(tableInput.value!.name);
|
|
647
657
|
grok.shell.info(((createAsStrand.value) ? 'Columns were' : 'Column was') +
|
|
648
|
-
' added to table \'' +
|
|
658
|
+
' added to table \'' + tableInput.value!.name + '\'');
|
|
649
659
|
updateOutputExamples();
|
|
650
660
|
}
|
|
651
661
|
});
|
|
@@ -664,10 +674,10 @@ export class PatternLayoutHandler {
|
|
|
664
674
|
|
|
665
675
|
const inputsSection = ui.block50([
|
|
666
676
|
ui.h1('Convert options'),
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
677
|
+
tableInput.root,
|
|
678
|
+
strandColumnInput[SS].root,
|
|
679
|
+
strandColumnInput[AS].root,
|
|
680
|
+
inputIdColumn.root,
|
|
671
681
|
ui.buttonsInput([
|
|
672
682
|
convertSequenceButton,
|
|
673
683
|
]),
|
|
@@ -678,7 +688,7 @@ export class PatternLayoutHandler {
|
|
|
678
688
|
{backgroundColor: 'white'}), 'Download pattern as PNG image', '');
|
|
679
689
|
|
|
680
690
|
const editPattern = ui.link('Edit pattern', ()=>{
|
|
681
|
-
ui.dialog('Edit
|
|
691
|
+
ui.dialog('Edit pattern')
|
|
682
692
|
.add(ui.divV([
|
|
683
693
|
ui.h1('PTO'),
|
|
684
694
|
ui.divH([
|
|
@@ -695,56 +705,6 @@ export class PatternLayoutHandler {
|
|
|
695
705
|
.show()
|
|
696
706
|
}, 'Edit pattern', '');
|
|
697
707
|
|
|
698
|
-
const mainSection = ui.panel([
|
|
699
|
-
ui.block([
|
|
700
|
-
svgDiv,
|
|
701
|
-
], {style: {overflowX: 'scroll'}}),
|
|
702
|
-
downloadButton,
|
|
703
|
-
isEnumerateModificationsDiv,
|
|
704
|
-
ui.div([
|
|
705
|
-
ui.div([
|
|
706
|
-
ui.divH([
|
|
707
|
-
ui.h1('Pattern options'),
|
|
708
|
-
]),
|
|
709
|
-
ui.divH([
|
|
710
|
-
ui.block([
|
|
711
|
-
strandLengthInput[SS].root,
|
|
712
|
-
asLengthDiv,
|
|
713
|
-
sequenceBase.root,
|
|
714
|
-
comment.root,
|
|
715
|
-
loadPatternDiv,
|
|
716
|
-
saveAs.root,
|
|
717
|
-
ui.buttonsInput([
|
|
718
|
-
//savePatternButton,
|
|
719
|
-
]),
|
|
720
|
-
], 'ui-form'),
|
|
721
|
-
ui.block([
|
|
722
|
-
createAsStrand.root,
|
|
723
|
-
fullyPto.root,
|
|
724
|
-
firstPto[SS].root,
|
|
725
|
-
firstPto[AS].root,
|
|
726
|
-
terminalModification[SS][FIVE_PRIME].root,
|
|
727
|
-
terminalModification[SS][THREE_PRIME].root,
|
|
728
|
-
asModificationDiv,
|
|
729
|
-
], 'ui-form'),
|
|
730
|
-
]),
|
|
731
|
-
], 'ui-form'),
|
|
732
|
-
inputsSection,
|
|
733
|
-
exampleSection,
|
|
734
|
-
], {style: {flexWrap: 'wrap'}}),
|
|
735
|
-
]);
|
|
736
|
-
|
|
737
|
-
const info = ui.info(
|
|
738
|
-
[
|
|
739
|
-
ui.divText('\n How to define new pattern:', {style: {'font-weight': 'bolder'}}),
|
|
740
|
-
ui.divText('1. Choose table and columns with sense and antisense strands'),
|
|
741
|
-
ui.divText('2. Choose lengths of both strands by editing checkboxes below'),
|
|
742
|
-
ui.divText('3. Choose basis and PTO status for each nucleotide'),
|
|
743
|
-
ui.divText('4. Set additional modifications for sequence edges'),
|
|
744
|
-
ui.divText('5. Press \'Convert Sequences\' button'),
|
|
745
|
-
ui.divText('This will add the result column(s) to the right of the table'),
|
|
746
|
-
], 'Create and apply Axolabs translation patterns.',
|
|
747
|
-
);
|
|
748
708
|
strandLengthInput[SS].addCaption('Length');
|
|
749
709
|
|
|
750
710
|
return ui.splitH([
|
|
@@ -759,9 +719,9 @@ export class PatternLayoutHandler {
|
|
|
759
719
|
loadPatternDiv,
|
|
760
720
|
saveAs.root,
|
|
761
721
|
ui.h1('Convert'),
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
722
|
+
tableInput.root,
|
|
723
|
+
strandColumnInput[SS],
|
|
724
|
+
strandColumnInput[AS],
|
|
765
725
|
inputIdColumn.root,
|
|
766
726
|
ui.buttonsInput([
|
|
767
727
|
convertSequenceButton,
|
|
@@ -126,9 +126,10 @@ export class StructureLayoutHandler {
|
|
|
126
126
|
const clearBlock = Object.fromEntries(
|
|
127
127
|
STRANDS.map(
|
|
128
128
|
(key) => {
|
|
129
|
-
const
|
|
130
|
-
ui.
|
|
131
|
-
|
|
129
|
+
const clearIcon = ui.icons.delete(() => { coloredInput[key].inputBase.value = '' });
|
|
130
|
+
const clearButton = ui.button(clearIcon, () => {});
|
|
131
|
+
ui.tooltip.bind(clearButton, `Clear ${key.toUpperCase()}`);
|
|
132
|
+
return [key, clearIcon];
|
|
132
133
|
}
|
|
133
134
|
));
|
|
134
135
|
|
|
@@ -5,7 +5,6 @@ import * as DG from 'datagrok-api/dg';
|
|
|
5
5
|
|
|
6
6
|
import * as rxjs from 'rxjs';
|
|
7
7
|
import '../style/translator-app.css';
|
|
8
|
-
import $ from 'cash-dom';
|
|
9
8
|
|
|
10
9
|
import {highlightInvalidSubsequence} from '../utils/colored-input/input-painters';
|
|
11
10
|
import {ColoredTextInput} from '../utils/colored-input/colored-text-input';
|
|
@@ -74,12 +73,19 @@ export class TranslatorLayoutHandler {
|
|
|
74
73
|
|
|
75
74
|
const formatChoiceInput = ui.div([this.formatChoiceInput]);
|
|
76
75
|
|
|
76
|
+
const clearButton = ui.button(
|
|
77
|
+
ui.icons.delete(() => { sequenceColoredInput.inputBase.value = '' }),
|
|
78
|
+
() => {}
|
|
79
|
+
);
|
|
80
|
+
ui.tooltip.bind(clearButton, 'Clear input');
|
|
81
|
+
|
|
77
82
|
const inputTableRow = {
|
|
78
83
|
format: formatChoiceInput,
|
|
79
84
|
textInput: sequenceColoredInput.root,
|
|
85
|
+
clearBtn: clearButton
|
|
80
86
|
};
|
|
81
87
|
const upperBlock = ui.table(
|
|
82
|
-
[inputTableRow], (item) => [item.format, item.textInput]
|
|
88
|
+
[inputTableRow], (item) => [item.format, item.textInput, item.clearBtn]
|
|
83
89
|
);
|
|
84
90
|
upperBlock.classList.add('st-translator-input-table');
|
|
85
91
|
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/* Naming convention: class names should begin with st and app name to avoid naming collitions */
|
|
2
2
|
.st-translator-input-table {
|
|
3
|
-
width: 100%;
|
|
3
|
+
/* width: 100%; */
|
|
4
|
+
margin-right: 20px;
|
|
4
5
|
}
|
|
5
6
|
|
|
6
7
|
.st-translator-input-table td:has(textarea) {
|
|
7
8
|
width: 100%;
|
|
8
|
-
padding-right: 20px;
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
.st-translator-input-table td:has(select) {
|