Skip to content

Commit

Permalink
Implement a manual residue selection box
Browse files Browse the repository at this point in the history
Refs #2266
  • Loading branch information
kimrutherford committed Oct 31, 2024
1 parent 9770a62 commit 72e422a
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
.selected-range {
font-size: 120%;
padding: 0 0.5em;
display: flex;
}

.seq-title {
Expand Down Expand Up @@ -183,3 +184,16 @@
.dropdown-item a {
text-decoration: none;
}

.manual-selection {
margin-left: auto;
font-size: 90%
}

.manual-selection input {
width: 16em;
}

.manual-selection-error {
color: red;
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
</select>
</div>

<div (mousemove)="mousemove()">
<div (mousemove)="checkSelection()" (mouseup)="checkSelection()">
<div *ngIf="hasTranscripts">
<div class="controls">
<div *ngIf="featureHasProtein()">
Expand Down Expand Up @@ -192,7 +192,17 @@
{{selectedResidueMessage()}}
</div>
<div *ngIf="!selectedResidueRange">&nbsp;</div>

<div *ngIf="!deployConfigService.productionMode()" class="manual-selection">
<a *ngIf="!selectedResidueRange && !manualSelectionVisible" (click)="manualSelectionVisible=true;">Manually select residues</a>
<div *ngIf="manualSelectionVisible && !selectedResidueRange && !showNucSequence">
Select range: <input [(ngModel)]="manualSelection" (change)="manualSelectionChanged()"
placeholder="Examples: 10..25 or 15-30 or 40">
<span class="manual-selection-error" *ngIf="manualSelectionErrorMessage">error: {{manualSelectionErrorMessage}}</span>
</div>
</div>
</div>

<div class="sequence-display">
<div *ngIf="wrappedSequence || wrappedProteinSequence">
<div class="header">
Expand All @@ -202,6 +212,7 @@
title="{{partTitle(part)}}" class="{{partClass(part)}}"
#partSpan
(mouseenter)="mouseenter(part)" (mouseleave)="mouseleave()"
(mousedown)="clearManualSelection()"
[attr.data-part-id]="part.partId">{{part.residues}}</span></div>
</div>
<div *ngIf="!wrappedSequence && showNucSequence">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { Component, OnChanges, Input, Inject } from '@angular/core';
import { Component, OnChanges, Input, Inject, ElementRef, ViewChild } from '@angular/core';

import { saveAs } from 'file-saver';

import { GeneDetails, ProteinDetails, PombaseAPIService, Strand } from '../pombase-api.service';
import { Util } from '../shared/util';
import { DisplaySequence, DisplaySequencePart, ResidueRange } from '../display-sequence';
import { getAppConfig, replaceFieldsInUrl } from '../config';
import { DeployConfigService } from '../deploy-config.service';

@Component({
selector: 'app-transcript-sequence-select',
Expand Down Expand Up @@ -43,6 +44,12 @@ export class TranscriptSequenceSelectComponent implements OnChanges {
upstreamBases = 0;
downstreamBases = 0;

manualSelection?: string;
manualSelectionErrorMessage?: string;
manualSelectionVisible = false;

@ViewChild('partSpan') partSpanElement: ElementRef;

linksInNewWindow = true;

hoverPart?: DisplaySequencePart;
Expand All @@ -57,6 +64,7 @@ export class TranscriptSequenceSelectComponent implements OnChanges {
downloadWithFeaturesURL = getAppConfig().seq_and_features_download_url;

constructor(private apiService: PombaseAPIService,
public deployConfigService: DeployConfigService,
@Inject('Window') private window: Window) { }

updateHeader(sequenceLength: number) {
Expand Down Expand Up @@ -132,6 +140,11 @@ export class TranscriptSequenceSelectComponent implements OnChanges {
return retVal;
}

clearManualSelection(): void {
this.manualSelection = undefined;
this.manualSelectionErrorMessage = undefined;
}

mouseenter(part: DisplaySequencePart): void {
if (this.showNucSequence) {
this.hoverPart = part;
Expand All @@ -142,7 +155,7 @@ export class TranscriptSequenceSelectComponent implements OnChanges {
this.hoverPart = undefined;
}

mousemove(): void {
checkSelection(): void {
this.selectedResidueRange = undefined;

const selection = this.window.getSelection();
Expand All @@ -169,6 +182,10 @@ export class TranscriptSequenceSelectComponent implements OnChanges {
this.selectedResidueRange =
displaySequence.rangeFromParts(+startPartId, startOffset,
+endPartId, endOffset - 1);
if (this.selectedResidueRange) {
this.manualSelectionVisible = false;
this.manualSelection = undefined;
}
}
}
}
Expand Down Expand Up @@ -426,6 +443,55 @@ export class TranscriptSequenceSelectComponent implements OnChanges {
this.updateSequence();
}

manualSelectionChanged(): void {
this.manualSelectionErrorMessage = undefined;
const selection = this.window.getSelection();
if (selection) {
selection.removeAllRanges();
}

if (this.manualSelection && this.manualSelection.trim().length >= 0) {
const parts = /^(\d+)(?:(?:\.\.|--?)(\d+))?$/.exec(this.manualSelection.trim());

if (parts) {
let start = parseInt(parts[1], 10);
let end = undefined;

const endMatch = parts[2];

if (endMatch) {
end = parseInt(endMatch, 10);
if (end < start) {
this.manualSelectionErrorMessage = 'end position < start';
return;
}
} else {
end = start;
}

if (start <= end && selection) {
const range = document.createRange();
const residuesText = this.partSpanElement.nativeElement.firstChild;
if (end >= residuesText.length) {
this.manualSelectionErrorMessage = 'end > sequence length';
return;
}
try {
range.setStart(residuesText, start-1);
range.setEnd(residuesText, end);
selection.addRange(range);
this.checkSelection();
}
catch (e) {
console.log(e);
}
}
} else {
this.manualSelectionErrorMessage = 'invalid range - example "10..20"';
}
}
}

selectedResidueMessage(): string {
if (!this.selectedResidueRange) {
return '';
Expand Down

0 comments on commit 72e422a

Please sign in to comment.