diff --git a/angular.json b/angular.json index a44d445a77016e8c6864c6a8e5d81841be626952..5b7311565a31611fb440b30a08df6da80802ace8 100644 --- a/angular.json +++ b/angular.json @@ -24,6 +24,7 @@ "src/assets" ], "styles": [ + { "input":"src/tabulator.css"}, { "input":"./node_modules/tabulator-tables/dist/css/tabulator_bootstrap4.min.css"}, { "input":"./node_modules/bootstrap/dist/css/bootstrap.min.css"}, { "input":"./node_modules/@angular/material/prebuilt-themes/indigo-pink.css"}, diff --git a/src/app/document-detail/document-detail.component.css b/src/app/document-detail/document-detail.component.css index d5508905eecd5b2300564de63913719f511d1a23..48228edf578c63d3eea562f761b04a5a005dfde3 100644 --- a/src/app/document-detail/document-detail.component.css +++ b/src/app/document-detail/document-detail.component.css @@ -1,25 +1,109 @@ -.loader{ - position: absolute; - top:0px; - right:0px; - width:100%; - height:100%; - background-color:#eceaea; - background-image:url('loader.gif'); - background-size: 100px; - background-repeat:no-repeat; - background-position:center; - z-index:10000000; - opacity: 0.4; - filter: alpha(opacity=40); -} - -.FixedHeightContainer -{ - -} -.brat_div -{ - - overflow:auto; +.loader { + position: absolute; + top: 0px; + right: 0px; + width: 100%; + height: 100%; + background-color: #eceaea; + background-image: url('loader.gif'); + background-size: 100px; + background-repeat: no-repeat; + background-position: center; + z-index: 10000000; + opacity: 0.4; + filter: alpha(opacity=40); +} + +.FixedHeightContainer {} + +.brat_div { + + overflow: auto; +} + +.add-fiding-button { + background-color: transparent; + border: none; + margin-left: auto; + margin-block: auto; +} + +.add-fiding-button .fa-solid.fa-plus { + color: grey; +} + +.export-document-button { + text-decoration: none; + cursor: pointer; +} + +.export-document-button .fa.fa-download { + color: black; + padding: 10px 30px; + font-size: 2rem; +} + +.get-evidence-button { + text-decoration: none; + cursor: pointer; +} + +.get-evidence-button .fa.fa-eye { + color: black; + padding: 10px 30px; + font-size: 2rem; +} + +.find-doc-button { + text-decoration: none; + cursor: pointer; +} + +.find-doc-button .fa.fa-file-text { + color: black; + padding: 10px 30px; + font-size: 2rem; +} + +.get-history-button { + text-decoration: none; + cursor: pointer; +} + +.get-history-button .fa.fa-history { + color: black; + padding: 10px 30px; + font-size: 2rem; +} + +.collapse-button { + text-decoration: none; + cursor: pointer; +} + +.collapse-button .fa.fa-angle-down { + color: black; + padding: 10px 30px; + font-size: 3rem; +} + +.card-header .document-name { + float: left; + width: 75%; +} + +.card-header .send-to-srdomain-button { + float: left; + width: 15%; +} + +.card-header .btn-group { + float: left; + width: 10%; +} + +.card-header .btn-group .status-button { + position: absolute; + bottom: 100; + left: 0; } \ No newline at end of file diff --git a/src/app/document-detail/document-detail.component.html b/src/app/document-detail/document-detail.component.html index 36cd4c96aa1c796f7f234f999434e9fae9b64267..6387446d22243ac617d8b18355d443927a9c40e5 100644 --- a/src/app/document-detail/document-detail.component.html +++ b/src/app/document-detail/document-detail.component.html @@ -1,86 +1,77 @@

- +

-
+
- - - -
- -
-
-

{{document.name}}

- -
- -
-
- +
+
+ - - + }" aria-haspopup="true" aria-expanded="true" (click)="moveDocument(status)">{{status}} +
-
- +
- - - - - - - - - - - - - - - - - + + + + + + + + + + + + + +
+
+
+
+
+
- -
+ + + + + \ No newline at end of file diff --git a/src/app/document-detail/document-detail.component.ts b/src/app/document-detail/document-detail.component.ts index 73e850c345bd64451e6ee619b6235329d7201815..aadab3bc2af0e6d13c2a5dc6c19df550649c7382 100644 --- a/src/app/document-detail/document-detail.component.ts +++ b/src/app/document-detail/document-detail.component.ts @@ -1,22 +1,21 @@ -import { Component, OnInit, Input, ViewChild, ElementRef, ViewEncapsulation, AfterViewInit, AfterContentInit } from '@angular/core'; +import { Component, OnInit, Input, ViewChild, ElementRef, ViewEncapsulation } from '@angular/core'; import { Document } from '../model/document'; import { ActivatedRoute } from '@angular/router'; import { Location } from '@angular/common'; import { DocumentService } from '../services/document.service'; +import { EventService } from '../services/event.service'; import { DomSanitizer, SafeHtml } from '@angular/platform-browser'; import { Finding } from '../model/finding'; import { Annotation } from '../model/annotation'; import { environment } from './../../environments/environment'; - -import { MatToolbarModule } from '@angular/material/toolbar'; import { Router } from '@angular/router'; import { CdisSendCtService } from '../services/cdis-send-ct.service'; +import { Status } from '../model/srdomainfindingstatus'; //brat declare var head: any; declare var Util: any; -declare var Visualizer: any; var displaySpanComment = function (evt, target, spanId, spanType, mods, spanText, commentText, commentType, normalizations) { var left = evt.clientX + "px"; @@ -30,12 +29,7 @@ var displaySpanComment = function (evt, target, spanId, spanType, mods, spanText var hideComment = function (evt, target, spanId, spanType, mods, spanText, commentText, commentType, normalizations) { var div = document.getElementById('commentpopup'); - if (div == null || div == undefined) { - console.log("Saved bug") - } else { - div.style.display = 'none'; - } - + div.style.display = 'none'; } declare var jQuery: any; @@ -62,6 +56,8 @@ export class DocumentDetailComponent implements OnInit { @Input() document: Document; + addFindingEnabled: boolean; + data: SafeHtml; docData: string; @@ -81,26 +77,9 @@ export class DocumentDetailComponent implements OnInit { static FINISHED = 'FINISHED'; // tslint:disable-next-line: max-line-length - constructor(private router: Router, private route: ActivatedRoute, private documentService: DocumentService, private cdiscSendCTService: CdisSendCtService, private location: Location, private sanitizer: DomSanitizer) { + constructor(private router: Router, private route: ActivatedRoute, private documentService: DocumentService, private cdiscSendCTService: CdisSendCtService, private location: Location, private sanitizer: DomSanitizer, private eventService: EventService) { const bratLocation = environment.bratUrl; - - head.js( - // External libraries - bratLocation + '/client/lib/jquery.min.js', - bratLocation + '/client/lib/jquery.svg.min.js', - bratLocation + '/client/lib/jquery.svgdom.min.js', - - // brat helper modules - bratLocation + '/client/src/configuration.js', - bratLocation + '/client/src/util.js', - bratLocation + '/client/src/annotation_log.js', - bratLocation + '/client/lib/webfont.js', - - // brat modules - bratLocation + '/client/src/dispatcher.js', - bratLocation + '/client/src/url_monitor.js', - bratLocation + '/client/src/visualizer.js' - ); + this.loadBratVisualizer(); DocumentDetailComponent.webFontURLs = [ bratLocation + '/static/fonts/Astloch-Bold.ttf', @@ -140,7 +119,6 @@ export class DocumentDetailComponent implements OnInit { ] }; - DocumentDetailComponent.collData['entity_attribute_types'] = [{ type: 'Notorious', /* brat supports multi-valued attributes, but in our case we will only @@ -149,7 +127,6 @@ export class DocumentDetailComponent implements OnInit { values: { Notorious: { glyph: '★' } } }]; - DocumentDetailComponent.collData['relation_types'] = [{ type: 'Relation', labels: ['R', 'R'], @@ -171,7 +148,8 @@ export class DocumentDetailComponent implements OnInit { label: 'Relevant Sentences', link: './sentences', index: 0 - }, { + }, + { label: 'Findings', link: './findings', index: 1 @@ -183,7 +161,6 @@ export class DocumentDetailComponent implements OnInit { loadBratVisualizer(): void { const bratLocation = environment.bratUrl; - //const bratLocation = 'http://10.32.6.2:8001'; head.js( // External libraries bratLocation + '/client/lib/jquery.min.js', @@ -201,8 +178,6 @@ export class DocumentDetailComponent implements OnInit { bratLocation + '/client/src/url_monitor.js', bratLocation + '/client/src/visualizer.js' ); - - } loaded(): void { @@ -228,7 +203,6 @@ export class DocumentDetailComponent implements OnInit { } getEvidence() { - //alert('getAllEvidence'); const id = +this.route.snapshot.paramMap.get('id'); this.documentService.getEvidence(id) .subscribe(text => { @@ -255,44 +229,13 @@ export class DocumentDetailComponent implements OnInit { this.document = document; this.setNextStatus(this.document.status); var data_relevant_sentences = []; - // document.findings.forEach(find => { - // data.push({ - // id : find.findingId, - // finding: find.finding != null ? find.finding.value : '', - // study_testcd: find.study_testcd != null ? find.study_testcd.value : '', - // manifestation_finding: find.manifestation_finding != null ? find.manifestation_finding.value : '', - // study_domain: find.study_domain != null ? find.study_domain.value : '', - // specimen: find.specimen != null ? find.specimen.value : '', - // sex: find.sex != null ? find.sex.value : '', - // dose: find.dose != null ? find.dose.value : '', - // group: find.group != null ? find.group.value : '', - // is_trf: find.is_treatment_related != null ? find.is_treatment_related.value : '' - // }); - // }); - //alert(data); - //alert(JSON.stringify(data)); - - //this.tableData = data; - //this.clear(); - //alert(JSON.stringify(document.findings)); - //var j = JSON.parse('{ text:' + document.text + '}'); - // var j = { text: document.text }; - // head.ready( function() { - // const dispatcher = Util.embed('data1' , DocumentDetailComponent.collData, j, DocumentDetailComponent.webFontURLs); - // dispatcher.on('displaySpanComment', displaySpanComment); - // dispatcher.on('hideComment', hideComment); - // }); - - var srDomainFindingsGlobal = []; - - //relevant sentence table document.relevantSentences.forEach(annotation => { var findings = []; annotation.findings.forEach(find => { var srDomainFindings = []; find.srDomainFindings.forEach(srDomainFinding => { - srDomainFindings.push({ + const currentFinding = ({ studyid: srDomainFinding.studyid, domain: srDomainFinding.domain, srseq: srDomainFinding.srseq, @@ -308,7 +251,6 @@ export class DocumentDetailComponent implements OnInit { srobstdy: srDomainFinding.srobstdy, srendy: srDomainFinding.srendy, - srenphse: srDomainFinding.srenphse, srobendy: srDomainFinding.srobendy, srdomain: srDomainFinding.srdomain, @@ -330,27 +272,13 @@ export class DocumentDetailComponent implements OnInit { export: srDomainFinding.export, srDomainId: srDomainFinding.srDomainId, findingId: srDomainFinding.findingId, + status: srDomainFinding.status + }); - }) - }); - - findings.push({ - id: find.findingId, - finding: find.finding != null ? find.finding.value : '', - study_testcd: find.study_testcd != null ? find.study_testcd.value : '', - manifestation_finding: find.manifestation_finding != null ? find.manifestation_finding.value : '', - study_domain: find.study_domain != null ? find.study_domain.value : '', - specimen: find.specimen != null ? find.specimen.value : '', - sex: find.sex != null ? find.sex.value : '', - dose: find.dose != null ? find.dose.value : '', - group: find.group != null ? find.group.value : '', - is_trf: find.is_treatment_related != null ? find.is_treatment_related.value : '', - export: find.export, - status: find.status, - selected: false, - srDomainFindings: srDomainFindings + findings.push(currentFinding); + srDomainFindings.push(currentFinding); }); - + srDomainFindingsGlobal = srDomainFindingsGlobal.concat(srDomainFindings); }); @@ -361,14 +289,16 @@ export class DocumentDetailComponent implements OnInit { }); }); + this.document.srdomainfindings.forEach(newFinding => { + srDomainFindingsGlobal.push(newFinding); + }); + this.tableDataPretoxSentences = data_relevant_sentences; this.tableDataSRDomainTemplate = srDomainFindingsGlobal; }); } rowClickFindingEvidence(dataRow: any): void { - //alert(dataRow.id); - //alert(dataRow); const finding = new Finding(); finding.findingId = dataRow.id; this.findingSelected(finding); @@ -383,7 +313,6 @@ export class DocumentDetailComponent implements OnInit { rowClickSRDomainTemplateEvidence(dataRow: any): void { const finding = new Finding(); finding.findingId = dataRow.findingId; - //finding.findingId=1; this.findingSelected(finding); } @@ -391,17 +320,12 @@ export class DocumentDetailComponent implements OnInit { this.documentService.findingSelected(this.document.documentId, finding) .subscribe(text => { var loading = document.getElementById('loadingDiv'); - //loading.style.display='block'; loading.addEventListener("load", this.loaded); this.docData = text; - //console.log(this.docData); - // console.log(JSON.parse(this.docData)); document.getElementById('data2').className = 'collapse show'; document.getElementById('data1').innerHTML = ''; document.getElementById('data1').className = ''; - //document.getElementById('loadingDiv').className = 'loader'; var j = JSON.parse(this.docData); - //this.loadBratVisualizer(); head.ready(function () { const dispatcher = Util.embed('data1', DocumentDetailComponent.collData, j, DocumentDetailComponent.webFontURLs); //dispatcher.on('displaySpanComment', displaySpanComment); @@ -410,23 +334,17 @@ export class DocumentDetailComponent implements OnInit { // document.getElementById('loadingDiv').className = ''; // }, 4000); }); - }); - } pretoxSentenceSelected(pretoxSentence): void { this.documentService.pretoxSentenceSelected(this.document.documentId, pretoxSentence) .subscribe(text => { this.docData = text; - //console.log(this.docData); - // console.log(JSON.parse(this.docData)); document.getElementById('data2').className = 'collapse show'; document.getElementById('data1').innerHTML = ''; document.getElementById('data1').className = ''; - //document.getElementById('loadingDiv').className = 'loader'; var j = JSON.parse(this.docData); - //this.loadBratVisualizer(); head.ready(function () { const dispatcher = Util.embed('data1', DocumentDetailComponent.collData, j, DocumentDetailComponent.webFontURLs); @@ -446,13 +364,10 @@ export class DocumentDetailComponent implements OnInit { this.documentService.findDocumentText(this.document.documentId) .subscribe(text => { this.docData = text; - //console.log(this.docData); document.getElementById('data2').className = 'collapse show'; document.getElementById('data1').innerHTML = ''; document.getElementById('data1').className = ''; - //document.getElementById('loadingDiv').className = 'loader'; var j = JSON.parse(this.docData); - //this.loadBratVisualizer(); head.ready(function () { const dispatcher = Util.embed('data1', DocumentDetailComponent.collData, j, DocumentDetailComponent.webFontURLs); @@ -466,20 +381,14 @@ export class DocumentDetailComponent implements OnInit { } getAllEvidence() { - //alert('getAllEvidence'); const id = +this.route.snapshot.paramMap.get('id'); - //this.documentService.getAllEvidence(this.document.documentId) this.documentService.getAllEvidence(id) .subscribe(text => { this.docData = text; - //console.log(this.docData); - // console.log(JSON.parse(this.docData)); document.getElementById('data2').className = 'collapse show'; document.getElementById('data1').innerHTML = ''; document.getElementById('data1').className = ''; - //document.getElementById('loadingDiv').className = 'loader'; var j = JSON.parse(this.docData); - //this.loadBratVisualizer(); head.ready(function () { const dispatcher = Util.embed('data1', DocumentDetailComponent.collData, j, DocumentDetailComponent.webFontURLs); //dispatcher.on('displaySpanComment', displaySpanComment); @@ -492,9 +401,7 @@ export class DocumentDetailComponent implements OnInit { } getSentencesEvidence() { - //alert('getSentencesEvidence'); const id = +this.route.snapshot.paramMap.get('id'); - //this.documentService.getAllEvidence(this.document.documentId) this.documentService.getSentencesEvidence(id) .subscribe(text => { this.docData = text; @@ -519,38 +426,33 @@ export class DocumentDetailComponent implements OnInit { setExportSRDomain(data) { const id = +this.route.snapshot.paramMap.get('id'); - //alert(data); - //alert(data.export); this.documentService.setExportSRDomain(id, data.srDomainId, data.export) .subscribe(text => { - //alert(text); }); } updateFinding(data) { const id = +this.route.snapshot.paramMap.get('id'); - this.documentService.updateFinding(id, data) - .subscribe(text => { - //alert(2); - //alert(text); - }); + if (data.status == Status.ADDED) { + this.documentService.addFinding(id, data).subscribe(_ => {}); + } else { + this.documentService.updateFinding(id, data) + .subscribe(text => { + }); + } } setFindingValidation(data) { const id = +this.route.snapshot.paramMap.get('id'); - //alert(data.status); this.documentService.setFindingValidation(id, data.id, data.status) .subscribe(text => { - //alert(text); }); } setSRFindingValidation(data) { const id = +this.route.snapshot.paramMap.get('id'); - //alert(data.status); this.documentService.setSRFindingValidation(id, data.srDomainId, data.status) .subscribe(text => { - //alert(text); }); } @@ -566,7 +468,6 @@ export class DocumentDetailComponent implements OnInit { moveDocument(status) { const id = +this.route.snapshot.paramMap.get('id'); - //alert(data.status); this.documentService.moveDocument(id, status) .subscribe(text => { this.document.status = status; @@ -575,17 +476,14 @@ export class DocumentDetailComponent implements OnInit { } sendToSRDomain() { - //alert(1); const id = +this.route.snapshot.paramMap.get('id'); this.documentService.sendToSRDomain(id); } showHistory() { const id = +this.route.snapshot.paramMap.get('id'); - //alert(data.status); this.documentService.getHistory(id) .subscribe(text => { - //alert(text); }); } @@ -594,48 +492,34 @@ export class DocumentDetailComponent implements OnInit { this.documentService.exportDocument(id, this.document.name); } - onActivate(componentReference) { + addFinding() { + this.eventService.addFindingEvent.emit(); + } - componentReference.activation(this.document); + onActivate(componentReference) { + componentReference.activation(this); - // if(componentReference.constructor.name=='PretoxsentencesTabulatorComponent'){ - // this.getSentencesEvidence(); - // }else if(componentReference.constructor.name=='SrdomaintemplateTabulatorComponent'){ - // this.getAllEvidence(); - // }else if(componentReference.constructor.name=='FindingTabulatorComponent'){ - // this.getAllEvidence(); - // } - //Below will subscribe to the searchItem emitter if (componentReference.rowClickEventFinding != undefined) { componentReference.rowClickEventFinding.subscribe((data) => { - //alert('rowClickEventFinding'); this.rowClickFindingEvidence(data); }) } - //Below will subscribe to the searchItem emitter if (componentReference.rowClickEvent != undefined) { - //alert('sentence activation'); this.getSentencesEvidence(); componentReference.rowClickEvent.subscribe((data) => { - //alert('rowClickEvent'); this.rowClickSentenceEvidence(data); }) } - //Below will subscribe to the searchItem emitter if (componentReference.rowClickSRFindingValidationEvent != undefined) { componentReference.rowClickSRFindingValidationEvent.subscribe((data) => { - //alert('rowClickFindingValidationEvent'); this.setSRFindingValidation(data); }) } - - //Below will subscribe to the searchItem emitter if (componentReference.rowClickFindingValidationEvent != undefined) { componentReference.rowClickFindingValidationEvent.subscribe((data) => { - //alert('rowClickFindingValidationEvent'); this.setFindingValidation(data); }) } @@ -644,34 +528,31 @@ export class DocumentDetailComponent implements OnInit { this.getAllEvidence(); } - //Below will subscribe to the searchItem emitter if (componentReference.rowClickEventSRDomainTemplateEvidence != undefined) { - //alert('sr-domain activation'); - //this.getAllEvidence(); componentReference.rowClickEventSRDomainTemplateEvidence.subscribe((data) => { - //alert('rowClickSRDomainTemplateEvidence'); this.rowClickSRDomainTemplateEvidence(data); }) } - //Below will subscribe to the searchItem emitter if (componentReference.rowClickExportSRDomainEvent != undefined) { componentReference.rowClickExportSRDomainEvent.subscribe((data) => { - //alert('rowClickExportSRDomainEvent'); this.setExportSRDomain(data); }) } - //Below will subscribe to the searchItem emitter if (componentReference.rowClickUpdateFindingEvent != undefined) { componentReference.rowClickUpdateFindingEvent.subscribe((data) => { - //alert('rowClickFindingValidationEvent'); this.updateFinding(data); }) } - + if (componentReference.enableAddFindingEvent != undefined) { + componentReference.enableAddFindingEvent.subscribe(isEnabled => { + this.addFindingEnabled = isEnabled; + }); + } } + goBack(): void { this.location.back(); } diff --git a/src/app/history-tracking/history-tracking.component.ts b/src/app/history-tracking/history-tracking.component.ts index d16d73dd986899a91ceb5a3b8a213656dd670574..c32905d9670bd5bff62147883105a69c5d852336 100644 --- a/src/app/history-tracking/history-tracking.component.ts +++ b/src/app/history-tracking/history-tracking.component.ts @@ -23,8 +23,8 @@ export class HistoryTrackingComponent implements OnInit { } - activation(data){ - this.documentTracking = data; + activation(parentComponent){ + this.documentTracking = parentComponent.document; } getTracking(): void { diff --git a/src/app/model/document.ts b/src/app/model/document.ts index dddaa5cfb8f6295ceb45d3e08ed7b4507d3e51f2..fb507d10ae8caac059d07fa97c9cd9bd958479fb 100644 --- a/src/app/model/document.ts +++ b/src/app/model/document.ts @@ -9,6 +9,6 @@ export class Document { status: string; statusColor: string = 'warning'; textWithAnnotations: string; - findings: SRDomainFinding[]; + srdomainfindings: SRDomainFinding[]; relevantSentences: Annotation[]; } diff --git a/src/app/model/srdomainfindingstatus.ts b/src/app/model/srdomainfindingstatus.ts new file mode 100644 index 0000000000000000000000000000000000000000..85adb548e27399bb9715964b7f2f38414b681e24 --- /dev/null +++ b/src/app/model/srdomainfindingstatus.ts @@ -0,0 +1,6 @@ +export enum Status { + NON_CURATED = "non_curated", + REJECTED = "rejected", + ACCEPTED = "accepted", + ADDED = "added" +} \ No newline at end of file diff --git a/src/app/pretoxsentences-tabulator/pretoxsentences-tabulator.component.css b/src/app/pretoxsentences-tabulator/pretoxsentences-tabulator.component.css index 80ba5c291a029e18670bc80b3e25786f2505e6f4..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 --- a/src/app/pretoxsentences-tabulator/pretoxsentences-tabulator.component.css +++ b/src/app/pretoxsentences-tabulator/pretoxsentences-tabulator.component.css @@ -1,14 +0,0 @@ -.tabulator { - font-size: 100px; - border: none; - } - .tabulator-row-odd { - background-color: #553333 !important; -} -.tabulator-row-even { - background-color: #335533 !important; -} - -.tabulator-row tabulator-selectable tabulator-row-odd { - font-size: 20px; -} \ No newline at end of file diff --git a/src/app/pretoxsentences-tabulator/pretoxsentences-tabulator.component.ts b/src/app/pretoxsentences-tabulator/pretoxsentences-tabulator.component.ts index aea3f5c9e4297f0442fda6c27dbded11c6628d21..5e053ba7117c618d06897038f51e7621f4ddc2b0 100644 --- a/src/app/pretoxsentences-tabulator/pretoxsentences-tabulator.component.ts +++ b/src/app/pretoxsentences-tabulator/pretoxsentences-tabulator.component.ts @@ -17,6 +17,7 @@ export class PretoxsentencesTabulatorComponent implements OnInit { //@Input() columnNames: any[] = []; tableData: any[] = []; + sentence_data: any[] = []; @Input() document: Document; @Input() height = '100%'; //@Input() height = '600px'; @@ -35,121 +36,28 @@ export class PretoxsentencesTabulatorComponent implements OnInit { } ngOnInit(): void { - this.getDocument(); - //this.drawTable(this); + this.tableData = this.sentence_data; + this.drawTable(this); } - activation(data) { - this.document = data; - } + activation(parentComponent){ + this.document = parentComponent.document; + this.sentence_data = parentComponent.tableDataPretoxSentences; + } ngOnChanges(changes: SimpleChanges): void { this.drawTable(this); } - getDocument(): void { - const id = this.document.documentId; - this.documentService.getDocument(id) - .subscribe(document => { - this.document = document; - //var data = []; - var data_relevant_sentences = []; - //var srDomainFindingsGlobal = []; - //relevant sentence table - document.relevantSentences.forEach(annotation => { - //var findings = []; - var srDomainFindings_2 = []; - annotation.findings.forEach(find => { - //var srDomainFindings = []; - find.srDomainFindings.forEach(srDomainFinding => { - srDomainFindings_2.push({ - studyid: srDomainFinding.studyid, - domain: srDomainFinding.domain, - srseq: srDomainFinding.srseq, - srrisk: srDomainFinding.srrisk, - - spgrpcd: srDomainFinding.spgrpcd, - srgrpnam: srDomainFinding.srgrpnam, - srgrpdos: srDomainFinding.srgrpdos, - srsex: srDomainFinding.srsex, - - srstdy: srDomainFinding.srstdy, - srstphse: srDomainFinding.srstphse, - srobstdy: srDomainFinding.srobstdy, - srendy: srDomainFinding.srendy, - - - srenphse: srDomainFinding.srenphse, - srobendy: srDomainFinding.srobendy, - srdomain: srDomainFinding.srdomain, - srspec: srDomainFinding.srspec, - - srtstcd: srDomainFinding.srtstcd, - srfndg: srDomainFinding.srfndg, - srores: srDomainFinding.srores, - srobsv: srDomainFinding.srobsv, - - srobsq: srDomainFinding.srobsq, - srsev: srDomainFinding.srsev, - srpcnt: srDomainFinding.srpcnt, - srsigf: srDomainFinding.srsigf, - - srtrtef: srDomainFinding.srpcnt, - srcomnt: srDomainFinding.srsigf, - - export: srDomainFinding.export, - status: srDomainFinding.status, - srDomainId: srDomainFinding.srDomainId, - findingId: srDomainFinding.findingId, - - }) - - }); - - // findings.push({ - // id : find.findingId, - // finding: find.finding != null ? find.finding.value : '', - // study_testcd: find.study_testcd != null ? find.study_testcd.value : '', - // manifestation_finding: find.manifestation_finding != null ? find.manifestation_finding.value : '', - // study_domain: find.study_domain != null ? find.study_domain.value : '', - // specimen: find.specimen != null ? find.specimen.value : '', - // sex: find.sex != null ? find.sex.value : '', - // dose: find.dose != null ? find.dose.value : '', - // group: find.group != null ? find.group.value : '', - // is_trf: find.is_treatment_related != null ? find.is_treatment_related.value : '', - // export: find.export, - // status: find.status, - // selected: false, - // srDomainFindings:srDomainFindings - // }); - - //srDomainFindingsGlobal = srDomainFindingsGlobal.concat(srDomainFindings); - - }) - - data_relevant_sentences.push({ - id: annotation.id, - text : annotation.text, - //findings: findings, - srDomainFindings: srDomainFindings_2 - }); - }); - this.tableData = data_relevant_sentences; - this.drawTable(this); - }); - - - } - private drawTable(pretoxSentencesTab): void { const table = new Tabulator(this.tab, { data: this.tableData, height: this.height, persistentLayout: false, - layout:"fitColumns", + layout: "fitColumns", persistentSort: false, pagination: true, - selectable: 0, + selectable: false, paginationSize: 10, paginationSizeSelector: [5, 10, 20, 40], columns: [ @@ -224,7 +132,7 @@ export class PretoxsentencesTabulatorComponent implements OnInit { var subTable = new Tabulator(tableEl, { //layout: 'fitDataFill', layout: "fitColumns", - data: row.getData().srDomainFindings, + data: row.getData().findings, columns: [ diff --git a/src/app/reports/reports.component.ts b/src/app/reports/reports.component.ts index 9ea34c0bcb8733d7582bc8e53aa2608b2782b7fb..dbd3028a436fa331b1ea3a1b9149722be0d6fd63 100644 --- a/src/app/reports/reports.component.ts +++ b/src/app/reports/reports.component.ts @@ -118,7 +118,7 @@ drawTable(documentTab): void { layout: 'fitColumns', data:this.tableData, pagination: true, - selectable: 0, + selectable: false, debugInvalidOptions: false, paginationSize: 20, paginationSizeSelector: [ 10, 20, 40], diff --git a/src/app/services/document.service.ts b/src/app/services/document.service.ts index 3cd9d8b1e3223ffafbe0953329917dbc9bd977b6..422a521fca89b47da5ed7bd91e346ad6809cdc86 100644 --- a/src/app/services/document.service.ts +++ b/src/app/services/document.service.ts @@ -10,15 +10,16 @@ import { Report } from '../model/report'; import { environment } from '../../environments/environment'; import { DocumentTracking } from '../model/document-tracking'; import { FindingSR } from '../model/findingsr'; +import { SRDomainFinding } from '../model/srdomainfinding'; const httpOptions = { - headers: new HttpHeaders({ 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*' }) + headers: new HttpHeaders({ 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*' }) }; @Injectable({ providedIn: 'root' }) export class DocumentService { - private pretoxUrl = environment.apiUrl; + private pretoxUrl = environment.apiUrl; private documentsUrl = environment.apiUrl + "/documents/"; private reportsUrl = environment.apiUrl + "/reports/"; private apiSRDomainURL = environment.apiSRDomainUrl + "/reports/"; @@ -48,13 +49,13 @@ export class DocumentService { ); } - /** GET document by id. Will 404 if id not found */ - exportDocument(id: number, name: string): any { - const url = `${this.documentsUrl}export/${id}`; - return this.http.get(url, { - responseType: 'blob', - observe: 'response' - }) + /** GET document by id. Will 404 if id not found */ + exportDocument(id: number, name: string): any { + const url = `${this.documentsUrl}export/${id}`; + return this.http.get(url, { + responseType: 'blob', + observe: 'response' + }) .pipe(map(res => { console.log(res.headers.get('content-disposition')); return { @@ -73,15 +74,15 @@ export class DocumentService { window.URL.revokeObjectURL(url); a.remove(); }); - } - - /** GET the legacy pdf report */ - openLegacyReport(gridFSId: number): any { - const url = `${this.reportsUrl}download/${gridFSId}`; - return this.http.get(url, { - responseType: 'blob', - observe: 'response' - }) + } + + /** GET the legacy pdf report */ + openLegacyReport(gridFSId: number): any { + const url = `${this.reportsUrl}download/${gridFSId}`; + return this.http.get(url, { + responseType: 'blob', + observe: 'response' + }) .pipe(map(res => { console.log(res.headers.get('content-disposition')); return { @@ -100,95 +101,103 @@ export class DocumentService { window.URL.revokeObjectURL(url); a.remove(); }); - } - - - - /** DEPRECATED, no more levels of findings set validation of finding */ - setFindingValidation(id: number, findingId: number, finding_validation: string): Observable { - const url = `${this.documentsUrl}${id}/findingValidation/${findingId}/${finding_validation}`; - return this.http.get(url , {responseType: 'text'}).pipe( - tap(_ => this.log(`finding_validation id=${findingId}`)), - catchError(this.handleError(`finding_validation id=${findingId}`)) - ); - } - - /** set validation of finding, indicate if is coreect or not the finding */ - setSRFindingValidation(id: number, srfindingId: number, finding_validation: string): Observable { - const url = `${this.documentsUrl}${id}/srfinding/${srfindingId}/validation/${finding_validation}`; - return this.http.put(url,{responseType: 'text'}).pipe( - tap(_ => this.log(`finding_validation id=${srfindingId}`)), - catchError(this.handleError(`finding_validation id=${srfindingId}`)) - ); - } - - /** set export finding */ - setExportSRDomain(id: number, srfindingId: number, export_finding: string): Observable { - const url = `${this.documentsUrl}${id}/srfinding/${srfindingId}/export/${export_finding}`; - return this.http.put(url,{responseType: 'text'}).pipe( - tap(_ => this.log(`export finding id=${srfindingId}`)), - catchError(this.handleError(`setExportSRDomain id=${srfindingId}`)) - ); - } - - /** move document */ - moveDocument(id: number, status: string): any { - const url = `${this.documentsUrl}${id}/move/${status}`; - return this.http.put(url,{responseType: 'text'}).pipe( - tap(_ => this.log(`moveDocument id=${id}`)), - catchError(this.handleError(`moveDocument id=${id}`)) - ); - } - - /** Update Finding */ - updateFinding(id: number, finding: FindingSR): any { - const url = `${this.documentsUrl}${id}/srfinding/update/`; - return this.http.put(url, finding).pipe( - tap(_ => this.log(`updateFinding`)), - catchError(this.handleError('updateFinding')) - ); - /*return this.http.post(url, finding).subscribe({ - next: data => { - alert(1); - alert(data); - }, - error: error => { - //this.errorMessage = error.message; - console.error('There was an error!', error); - } - })*/ + } + + + + /** DEPRECATED, no more levels of findings set validation of finding */ + setFindingValidation(id: number, findingId: number, finding_validation: string): Observable { + const url = `${this.documentsUrl}${id}/findingValidation/${findingId}/${finding_validation}`; + return this.http.get(url, { responseType: 'text' }).pipe( + tap(_ => this.log(`finding_validation id=${findingId}`)), + catchError(this.handleError(`finding_validation id=${findingId}`)) + ); + } + + /** set validation of finding, indicate if is coreect or not the finding */ + setSRFindingValidation(id: number, srfindingId: number, finding_validation: string): Observable { + const url = `${this.documentsUrl}${id}/srfinding/${srfindingId}/validation/${finding_validation}`; + return this.http.put(url, { responseType: 'text' }).pipe( + tap(_ => this.log(`finding_validation id=${srfindingId}`)), + catchError(this.handleError(`finding_validation id=${srfindingId}`)) + ); + } + + /** set export finding */ + setExportSRDomain(id: number, srfindingId: number, export_finding: string): Observable { + const url = `${this.documentsUrl}${id}/srfinding/${srfindingId}/export/${export_finding}`; + return this.http.put(url, { responseType: 'text' }).pipe( + tap(_ => this.log(`export finding id=${srfindingId}`)), + catchError(this.handleError(`setExportSRDomain id=${srfindingId}`)) + ); + } + + /** move document */ + moveDocument(id: number, status: string): any { + const url = `${this.documentsUrl}${id}/move/${status}`; + return this.http.put(url, { responseType: 'text' }).pipe( + tap(_ => this.log(`moveDocument id=${id}`)), + catchError(this.handleError(`moveDocument id=${id}`)) + ); + } + + /** Update Finding */ + updateFinding(id: number, finding: SRDomainFinding): any { + const url = `${this.documentsUrl}${id}/srfinding/update/`; + return this.http.put(url, finding).pipe( + tap(_ => this.log(`updateFinding`)), + catchError(this.handleError('updateFinding')) + ); + /*return this.http.post(url, finding).subscribe({ + next: data => { + alert(1); + alert(data); + }, + error: error => { + //this.errorMessage = error.message; + console.error('There was an error!', error); + } + })*/ - } + } + + addFinding(id: number, finding: SRDomainFinding): any { + const url = `${this.documentsUrl}${id}/srfinding/add/`; + return this.http.put(url, finding).pipe( + tap(_ => this.log(`addFinding`)), + catchError(this.handleError('addFinding')) + ); + } - /** show history tracking */ - getHistory(id: number): Observable { - const url = `${this.documentsUrl}${id}/tracking`; - return this.http.get(url).pipe( + /** show history tracking */ + getHistory(id: number): Observable { + const url = `${this.documentsUrl}${id}/tracking`; + return this.http.get(url).pipe( tap(_ => this.log(`fetched document id=${id}`)), catchError(this.handleError(`getDocument id=${id}`)) - ); - } - - /** GET Snipped of finding selected */ - findingSelected(id: number, finding: Finding): Observable { - const url = `${this.documentsUrl}${id}/evidence/finding/${finding.findingId}`; - return this.http.get(url , {responseType: 'text'}).pipe( - tap(_ => this.log(`fetched finding id=${finding.findingId}`)), - catchError(this.handleError(`getFinding id=${finding.findingId}`)) - ); - } - - /** GET Snipped of the full text with no annotations */ - findDocumentText(id: number): Observable { - const url = `${this.documentsUrl}${id}/text/`; - return this.http.get(url , {responseType: 'text'}).pipe( - tap(_ => this.log(`fetched text id=${id}`)), - catchError(this.handleError(`getText id=${id}`)) - ); - } - - /** Get SRDomain format and send to srdomain api */ + ); + } + + /** GET Snipped of finding selected */ + findingSelected(id: number, finding: Finding): Observable { + const url = `${this.documentsUrl}${id}/evidence/finding/${finding.findingId}`; + return this.http.get(url, { responseType: 'text' }).pipe( + tap(_ => this.log(`fetched finding id=${finding.findingId}`)), + catchError(this.handleError(`getFinding id=${finding.findingId}`)) + ); + } + + /** GET Snipped of the full text with no annotations */ + findDocumentText(id: number): Observable { + const url = `${this.documentsUrl}${id}/text/`; + return this.http.get(url, { responseType: 'text' }).pipe( + tap(_ => this.log(`fetched text id=${id}`)), + catchError(this.handleError(`getText id=${id}`)) + ); + } + + /** Get SRDomain format and send to srdomain api */ sendToSRDomain(id: number): any { //call to get srdomain const url_2 = `${this.documentsUrl}srdomain/${id}`; @@ -198,69 +207,69 @@ export class DocumentService { const url = `${this.apiSRDomainURL}`; return this.http.post(url, doc).subscribe({ next: data => { - alert(data); + alert(data); }, error: error => { - //this.errorMessage = error.message; - console.error('There was an error!', error); + //this.errorMessage = error.message; + console.error('There was an error!', error); } - }) - + }) + }, error: error => { - //this.errorMessage = error.message; - console.error('There was an error!', error); + //this.errorMessage = error.message; + console.error('There was an error!', error); } - }) + }) + + } + + /** GET Snipped of findings selected just in case is needed, is not complete only the calls againt rest api is done*/ + findingsSelected(id: number, finding: Finding): Observable { + //const url = `${this.documentsUrl}/${id}/finding/${finding.findingId}`; + const url = `${this.documentsUrl}${id}/findings/1,2`; + return this.http.get(url, { responseType: 'text' }).pipe( + tap(_ => this.log(`fetched finding id=${finding.findingId}`)), + catchError(this.handleError(`getFinding id=${finding.findingId}`)) + ); + } + + /** GET Snipped of all finding evidence */ + getAllEvidence(id: number): Observable { + const url = `${this.documentsUrl}${id}/evidence/findings`; + return this.http.get(url, { responseType: 'text' }).pipe( + tap(_ => this.log(`fetched all evidence id=${id}`)), + catchError(this.handleError(`getFindings id=${id}`)) + ); + } + + /** GET Snipped of all finding evidence */ + getEvidence(id: number): Observable { + const url = `${this.documentsUrl}${id}/evidence/all`; + return this.http.get(url, { responseType: 'text' }).pipe( + tap(_ => this.log(`fetched all evidence id=${id}`)), + catchError(this.handleError(`getFindings id=${id}`)) + ); + } + /** GET Snipped of sentences evidence */ + getSentencesEvidence(id: number): Observable { + const url = `${this.documentsUrl}${id}/evidence/sentences`; + return this.http.get(url, { responseType: 'text' }).pipe( + tap(_ => this.log(`fetched all sentences evidence id=${id}`)), + catchError(this.handleError(`getSentencesEvidence id=${id}`)) + ); } - /** GET Snipped of findings selected just in case is needed, is not complete only the calls againt rest api is done*/ - findingsSelected(id: number, finding: Finding): Observable { - //const url = `${this.documentsUrl}/${id}/finding/${finding.findingId}`; - const url = `${this.documentsUrl}${id}/findings/1,2`; - return this.http.get(url , {responseType: 'text'}).pipe( - tap(_ => this.log(`fetched finding id=${finding.findingId}`)), - catchError(this.handleError(`getFinding id=${finding.findingId}`)) - ); - } - - /** GET Snipped of all finding evidence */ - getAllEvidence(id: number): Observable { - const url = `${this.documentsUrl}${id}/evidence/findings`; - return this.http.get(url , {responseType: 'text'}).pipe( - tap(_ => this.log(`fetched all evidence id=${id}`)), - catchError(this.handleError(`getFindings id=${id}`)) - ); - } - - /** GET Snipped of all finding evidence */ - getEvidence(id: number): Observable { - const url = `${this.documentsUrl}${id}/evidence/all`; - return this.http.get(url , {responseType: 'text'}).pipe( - tap(_ => this.log(`fetched all evidence id=${id}`)), - catchError(this.handleError(`getFindings id=${id}`)) - ); - } - - /** GET Snipped of sentences evidence */ - getSentencesEvidence(id: number): Observable { - const url = `${this.documentsUrl}${id}/evidence/sentences`; - return this.http.get(url , {responseType: 'text'}).pipe( - tap(_ => this.log(`fetched all sentences evidence id=${id}`)), - catchError(this.handleError(`getSentencesEvidence id=${id}`)) - ); - } - - pretoxSentenceSelected(id: number, pretoxSentence: Annotation): Observable { - const url = `${this.documentsUrl}${id}/evidence/sentence/${pretoxSentence.id}`; - //const url = `${this.documentsUrl}/${id}/sentence/1`; - return this.http.get(url , {responseType: 'text'}).pipe( - tap(_ => this.log(`fetched pretox sentence id=${pretoxSentence.id}`)), - catchError(this.handleError(`getPretoxSentence id=${pretoxSentence.id}`)) - ); - } + pretoxSentenceSelected(id: number, pretoxSentence: Annotation): Observable { + const url = `${this.documentsUrl}${id}/evidence/sentence/${pretoxSentence.id}`; + //const url = `${this.documentsUrl}/${id}/sentence/1`; + return this.http.get(url, { responseType: 'text' }).pipe( + tap(_ => this.log(`fetched pretox sentence id=${pretoxSentence.id}`)), + catchError(this.handleError(`getPretoxSentence id=${pretoxSentence.id}`)) + ); + } /** PUT: update the document on the server */ updateDocument(document: Document): Observable { @@ -282,19 +291,19 @@ export class DocumentService { deleteDocument(id: number): Observable { const url = `${this.documentsUrl}remove/${id}`; alert(url); - return this.http.delete(url , {responseType: 'text'}).pipe( + return this.http.delete(url, { responseType: 'text' }).pipe( tap(_ => this.log(`finding_validation id=${id}`)), catchError(this.handleError(`finding_validation id=${id}`)) - ); + ); } /** Delete report */ deleteReport(id: string): Observable { const url = `${this.reportsUrl}remove/${id}`; - return this.http.delete(url , {responseType: 'text'}).pipe( + return this.http.delete(url, { responseType: 'text' }).pipe( tap(_ => this.log(`deleteReport id=${id}`)), catchError(this.handleError(`deleteReport id=${id}`)) - ); + ); } /** Log a DocumentService message with the MessageService */ @@ -310,13 +319,13 @@ export class DocumentService { */ private handleError(operation = 'operation', result?: T) { return (error: any): Observable => { - // TODO: send the error to remote logging infrastructure - console.error(error); // log to console instead - // TODO: better job of transforming error for user consumption - this.log(`${operation} failed: ${error.message}`); - // Let the app keep running by returning an empty result. - return of(result as T); + // TODO: send the error to remote logging infrastructure + console.error(error); // log to console instead + // TODO: better job of transforming error for user consumption + this.log(`${operation} failed: ${error.message}`); + // Let the app keep running by returning an empty result. + return of(result as T); }; } - + } diff --git a/src/app/services/event.service.ts b/src/app/services/event.service.ts new file mode 100644 index 0000000000000000000000000000000000000000..4b80dd04145fe76409761d55d112eaabba92018e --- /dev/null +++ b/src/app/services/event.service.ts @@ -0,0 +1,11 @@ +import { EventEmitter, Injectable } from "@angular/core"; + +@Injectable({ + providedIn: 'root' +}) +export class EventService { + + addFindingEvent: EventEmitter = new EventEmitter(); + + constructor() { } +} \ No newline at end of file diff --git a/src/app/srdomaintemplate-tabulator/srdomaintemplate-tabulator.component.ts b/src/app/srdomaintemplate-tabulator/srdomaintemplate-tabulator.component.ts index ad07205d2365ccf56d65023b6ef0a3492c4da567..fbea754f356271a9a537e48701df48379e57f312 100644 --- a/src/app/srdomaintemplate-tabulator/srdomaintemplate-tabulator.component.ts +++ b/src/app/srdomaintemplate-tabulator/srdomaintemplate-tabulator.component.ts @@ -1,10 +1,13 @@ import { Component, Input, OnInit, EventEmitter, Output } from '@angular/core'; -import {TabulatorFull as Tabulator} from 'tabulator-tables'; +import { TabulatorFull as Tabulator } from 'tabulator-tables'; import { CdisSendCtService } from '../services/cdis-send-ct.service'; import { ActivatedRoute } from '@angular/router'; import { DocumentService } from '../services/document.service'; import { Document } from '../model/document'; import { cloneDeep } from 'lodash'; +import { EventService } from '../services/event.service'; +import { Status } from '../model/srdomainfindingstatus'; +import { SRDomainFinding } from '../model/srdomainfinding'; @Component({ selector: 'app-srdomaintemplate-tabulator', @@ -12,11 +15,13 @@ import { cloneDeep } from 'lodash'; styleUrls: ['./srdomaintemplate-tabulator.component.css'] }) export class SrdomaintemplateTabulatorComponent implements OnInit { - + tableData: any[] = []; + table: Tabulator; originalData: any[] = []; + finding_data: any[] = []; @Input() document: Document; - + @Input() height = '100%'; @Output() rowClickEventSRDomainTemplateEvidence = new EventEmitter(); @@ -24,39 +29,51 @@ export class SrdomaintemplateTabulatorComponent implements OnInit { @Output() rowClickSRFindingValidationEvent = new EventEmitter(); @Output() rowClickUpdateFindingEvent = new EventEmitter(); @Output() srFindingType = new EventEmitter(); + @Output() enableAddFindingEvent = new EventEmitter(); tab = document.createElement('div'); - - constructor(private route: ActivatedRoute, private documentService: DocumentService,private cdiscSendCTService: CdisSendCtService,) { } + + constructor(private route: ActivatedRoute, private documentService: DocumentService, private cdiscSendCTService: CdisSendCtService, private eventService: EventService) { } ellipsisFormatter(cell, formatterParams, onRendered) { - onRendered(function(){ - var element = cell.getElement(); - element.title = cell.getValue() + onRendered(function () { + var element = cell.getElement(); + element.title = cell.getValue() }); return cell.getValue(); }; ngOnInit(): void { - this.getDocument(); + this.tableData = this.finding_data; + this.originalData = cloneDeep(this.finding_data); + this.drawTable(this); + this.enableAddFindingEvent.emit(true); + this.eventService.addFindingEvent.subscribe(() => { + this.addFinding(); + }); } - - activation(data){ - this.document=data; + + ngOnDestroy() { + this.enableAddFindingEvent.emit(false); } - - editCheck(cell){ + + activation(parentComponent){ + this.document = parentComponent.document; + this.finding_data= parentComponent.tableDataSRDomainTemplate; + } + + editCheck(cell) { return cell.getRow().getData().inEdition == true; } searchFunction(term, values) { var matches = [] var text = term.split(' '); - matches = values.filter(function(item) { - return text.every(function(el) { - return item.title.toLowerCase().indexOf(el.toLowerCase()) > -1; - }); + matches = values.filter(function (item) { + return text.every(function (el) { + return item.title.toLowerCase().indexOf(el.toLowerCase()) > -1; + }); }); return matches; @@ -66,11 +83,11 @@ export class SrdomaintemplateTabulatorComponent implements OnInit { var v = [] var field = cell.getColumn().getField(); var rowNum = cell.getRow().getData().findingId; - var originalValue = this.originalData[rowNum - 1][field]; + var originalValue = rowNum < this.originalData.length ? this.originalData[rowNum - 1][field] : null; var originalIsCodedValue = false; var codeLists = []; var constantValues = []; - + if (field == "srtstcd") { // study test var cellData = cell.getRow().getData(); codeLists.push(this.cdiscSendCTService.study_testcd_list_by_domain.get(cellData.domain)); @@ -95,7 +112,7 @@ export class SrdomaintemplateTabulatorComponent implements OnInit { description: codedValue.description }) }); - }); + }); } if (constantValues[0] != undefined) { @@ -110,19 +127,19 @@ export class SrdomaintemplateTabulatorComponent implements OnInit { }) } - if (!originalIsCodedValue) v.push({ + if (originalValue != null && originalValue != undefined && !originalIsCodedValue) v.push({ label: originalValue, value: originalValue, name: originalValue, description: originalValue }); - return { - freetext : true, + return { + freetext: true, values: v, sort: "asc", - listOnEmpty:true, - itemFormatter: function(label, value, item, element) { + listOnEmpty: true, + itemFormatter: function (label, value, item, element) { //label - the text lable for the item //value - the value for the item //item - the original value object for the item @@ -138,19 +155,19 @@ export class SrdomaintemplateTabulatorComponent implements OnInit { return this.paramLookupGeneric(cell); } - paramLookupManifestation(cell){ + paramLookupManifestation(cell) { return this.paramLookupGeneric(cell); } - paramLookupStudyTest(cell){ + paramLookupStudyTest(cell) { return this.paramLookupGeneric(cell); } - paramLookupSpecies(cell){ + paramLookupSpecies(cell) { return this.paramLookupGeneric(cell); } - paramLookupFinding(cell){ + paramLookupFinding(cell) { return this.paramLookupGeneric(cell); } @@ -158,237 +175,215 @@ export class SrdomaintemplateTabulatorComponent implements OnInit { var srdomainCode = this.cdiscSendCTService.getStudyDomainCode(cell.getValue()) var cellData = cell.getRow().getData() cellData.domain = srdomainCode - cell.getRow().update({srtstcd: ""}) - } - - getDocument(): void { - const id = this.document.documentId; - this.documentService.getDocument(id) - .subscribe(document => { - this.document = document; - var srDomainFindingsGlobal = []; - //relevant sentence table - document.relevantSentences.forEach(annotation => { - var findings = []; - annotation.findings.forEach(find => { - var srDomainFindings = []; - find.srDomainFindings.forEach(srDomainFinding => { - srDomainFindings.push({ - studyid : srDomainFinding.studyid, - domain : srDomainFinding.domain, - srseq : srDomainFinding.srseq, - srrisk : srDomainFinding.srrisk, - - spgrpcd : srDomainFinding.spgrpcd, - srgrpnam : srDomainFinding.srgrpnam, - srgrpdos : srDomainFinding.srgrpdos, - srsex : srDomainFinding.srsex, - - srstdy : srDomainFinding.srstdy, - srstphse : srDomainFinding.srstphse, - srobstdy : srDomainFinding.srobstdy, - srendy : srDomainFinding.srendy, - - srenphse : srDomainFinding.srenphse, - srobendy : srDomainFinding.srobendy, - srdomain : srDomainFinding.srdomain, - srspec : srDomainFinding.srspec, - - srtstcd : srDomainFinding.srtstcd, - srfndg : srDomainFinding.srfndg, - srores : srDomainFinding.srores, - srobsv : srDomainFinding.srobsv, - - srobsq : srDomainFinding.srobsq, - srsev : srDomainFinding.srsev, - srpcnt : srDomainFinding.srpcnt, - srsigf : srDomainFinding.srsigf, - - srtrtef : srDomainFinding.srtrtef, - srcomnt : srDomainFinding.srsigf, - - export: srDomainFinding.export, - status: srDomainFinding.status, - srDomainId: srDomainFinding.srDomainId, - findingId: srDomainFinding.findingId, + cell.getRow().update({ srtstcd: "" }) + } - }); - }); - - srDomainFindingsGlobal = srDomainFindingsGlobal.concat(srDomainFindings); - }); - }); - this.tableData = srDomainFindingsGlobal; - this.originalData = cloneDeep(srDomainFindingsGlobal); - this.drawTable(this); - }); + addFinding() { + const findingId = this.table.getDataCount() + 1; + const newFinding = new SRDomainFinding(); + newFinding.studyid = this.document.name; + newFinding.srDomainId = findingId; + newFinding.findingId = findingId; + newFinding.status = Status.ADDED; + + this.tableData.push(newFinding); + this.table.addRow(newFinding); } private drawTable(pretoxSRDomainTemplateTab): void { - const table = new Tabulator(this.tab, { + const addedStatus = Status.ADDED; + const acceptedStatus = Status.ACCEPTED; + const rejectedStatus = Status.REJECTED + const nonCuratedStatus = Status.NON_CURATED; + this.table = new Tabulator(this.tab, { layout: 'fitColumns', pagination: true, + selectable: false, paginationSize: 10, paginationSizeSelector: [5, 10, 20, 40], data: this.tableData, columns: [ { - title:'', width: 5, hozAlign: 'center', headerSort: false, - cellClick: function(e, cell) { - //cell.getRow().getElement().style.backgroundColor = "#e2fcad"; //apply css change to row element + title: '', width: 5, hozAlign: 'center', headerSort: false, cssClass: "tabulator-cell non-editable-cell", + cellClick: function (e, cell) { var data = cell.getRow().getData(); - - if (data.status == "accepted") { - data.status="rejected"; - cell.getElement().innerHTML=''; - } else if(data.status == "rejected") { - data.status = "non_curated"; - cell.getElement().innerHTML = ''; - } else { - data.status = "accepted"; - cell.getElement().innerHTML = ''; + if (data.status != addedStatus) { + if (data.status == acceptedStatus) { + data.status = rejectedStatus; + cell.getElement().innerHTML = '
'; + } else if (data.status == rejectedStatus) { + data.status = nonCuratedStatus; + cell.getElement().innerHTML = '
'; + } else { + data.status = acceptedStatus; + cell.getElement().innerHTML = '
'; + } + + pretoxSRDomainTemplateTab.rowClickSRFindingValidationEvent.emit(data); } - - pretoxSRDomainTemplateTab.rowClickSRFindingValidationEvent.emit(data); }, - formatter: function(cell, formatterParams, onRendered) { + formatter: function (cell, formatterParams, onRendered) { var data = cell.getRow().getData(); - if (data.status == "accepted") { - return ''; - } else if (data.status == "rejected") { - return ''; + if (data.status == addedStatus) { + return '
'; + } else if (data.status == acceptedStatus) { + return '
'; + } else if (data.status == rejectedStatus) { + return '
'; } else { - return ''; - } + return '
'; + } } }, { - title:'', width: 5, hozAlign: 'center', headerSort: false, - cellClick: function(e, cell) { + title: '', width: 5, hozAlign: 'center', headerSort: false, cssClass: "tabulator-cell non-editable-cell", + cellClick: function (e, cell) { var data = cell.getRow().getData(); - if (data.export == undefined || data.export == true) { - cell.getRow().getData().export = false; - cell.getElement().innerHTML = ''; - } else if (data.export == false) { - cell.getRow().getData().export = true; - cell.getElement().innerHTML = ''; - } + if (data.status != addedStatus) { + if (data.export == undefined || data.export == true) { + data.export = false; + cell.getElement().innerHTML = '
'; + } else if (data.export == false) { + data.export = true; + cell.getElement().innerHTML = '
'; + } - pretoxSRDomainTemplateTab.rowClickExportSRDomainEvent.emit(cell.getData()); + pretoxSRDomainTemplateTab.rowClickExportSRDomainEvent.emit(cell.getData()); + } }, - formatter: function(cell, formatterParams, onRendered) { + formatter: function (cell, formatterParams, onRendered) { var data = cell.getRow().getData(); + if (data.status == addedStatus) { + return '
'; + } + if (data.export == undefined || data.export == true) { - return ''; + return '
'; } else { - return ''; + return '
'; } } }, { - title:'', width: 5, hozAlign: 'center', headerSort: false, - cellClick: function(e, cell) { - pretoxSRDomainTemplateTab.rowClickEventSRDomainTemplateEvidence.emit(cell.getData()); - var table = cell.getRow().getTable(); - var data = table.getRows(); - data.forEach(row => { - row.getElement().style.border = ""; - }); - cell.getRow().getElement().style.border = "1px solid black"; - cell.getRow().getData().selected = true; + title: '', width: 5, hozAlign: 'center', headerSort: false, cssClass: "tabulator-cell non-editable-cell", + cellClick: function (e, cell) { + if (cell.getRow().getData().status != addedStatus && cell.getRow().getData().selected != true) { + cell.getRow().getData().selected = true; + cell.getRow().getElement().className = "tabulator-row evidence-selected"; + pretoxSRDomainTemplateTab.rowClickEventSRDomainTemplateEvidence.emit(cell.getData()); + } else { + cell.getRow().getData().selected = false; + cell.getRow().getElement().className = "tabulator-row"; + } }, - formatter: function(cell, formatterParams, onRendered) { - return ''; + formatter: function (cell, formatterParams, onRendered) { + if (cell.getRow().getData().status == addedStatus) { + return '
'; + } + + return '
'; } }, { - title:'', field: 'ed', width: 5, hozAlign: 'center', headerSort: false, - cellClick: function(e, cell) { - var data = cell.getRow().getData(); - if(data.inEdition == false || data.inEdition == undefined) { - if (pretoxSRDomainTemplateTab.document.findingInEdition == undefined || - pretoxSRDomainTemplateTab.document.findingInEdition == -1) { - cell.getRow().getData().inEdition = true; - cell.getRow().getElement().style.backgroundColor = "#ffcc66"; - //cell.getRow().getElement().style.backgroundColor = "#fad7a0 "; - cell.getRow().getCell('ed2').getElement().innerHTML = ''; - cell.getElement().innerHTML = ' '; - pretoxSRDomainTemplateTab.document.findingInEdition = 1; - } else { - alert('Only one edition permited'); - } - } else if (data.inEdition == true) { - cell.getRow().getData().inEdition = false; - cell.getRow().getElement().style.backgroundColor = "#ffffff"; - cell.getRow().getCell('ed2').getElement().innerHTML = ''; - cell.getElement().innerHTML = ''; - pretoxSRDomainTemplateTab.document.findingInEdition = -1; + title: '', field: 'ed', width: 5, hozAlign: 'center', headerSort: false, cssClass: "tabulator-cell non-editable-cell", + cellClick: function (e, cell) { + var row = cell.getRow(); + var data = row.getData(); + if (data.inEdition == false || data.inEdition == undefined) { + if (pretoxSRDomainTemplateTab.document.findingInEdition == undefined || + pretoxSRDomainTemplateTab.document.findingInEdition == -1) { + data.inEdition = true; + pretoxSRDomainTemplateTab.document.findingInEdition = 1; + pretoxSRDomainTemplateTab.enableAddFindingEvent.emit(false); + row.getCell('ed2').getElement().innerHTML = '
'; + cell.getElement().innerHTML = '
'; + row.getElement().className = "tabulator-row editable"; + cell.getColumn().getCells().forEach(rowCell => { + if (cell != rowCell) rowCell.getElement().childNodes[0]["className"] = "edition-unabled"; + }); } + } else if (data.inEdition == true) { + data.inEdition = false; + pretoxSRDomainTemplateTab.document.findingInEdition = -1; + pretoxSRDomainTemplateTab.enableAddFindingEvent.emit(true); + row.getCell('ed2').getElement().innerHTML = ''; + cell.getElement().innerHTML = '
'; + row.getElement().className = "tabulator-row"; + cell.getColumn().getCells().forEach(rowCell => { + if (cell != rowCell) rowCell.getElement().childNodes[0]["className"] = "enable-edition"; + }); + } }, - formatter: function(cell, formatterParams, onRendered) { - return ''; + formatter: function (cell, formatterParams, onRendered) { + return '
'; } }, { - title:'', field: 'ed2', width: 5, hozAlign: 'center', headerSort: false, //edition logic save button - cellClick: function(e, cell) { + title: '', field: 'ed2', width: 5, hozAlign: 'center', headerSort: false, cssClass: "tabulator-cell non-editable-cell", //edition logic save button + cellClick: function (e, cell) { + var row = cell.getRow(); var data = cell.getRow().getData(); if (data.inEdition == true) { - pretoxSRDomainTemplateTab.rowClickUpdateFindingEvent.emit(cell.getData()); - pretoxSRDomainTemplateTab.document.findingInEdition = -1; - cell.getRow().getData().inEdition = false; - cell.getRow().getElement().style.backgroundColor = "#ffffff"; - cell.getElement().innerHTML = ''; - cell.getRow().getCell('ed').getElement().innerHTML = ''; + data.inEdition = false; + pretoxSRDomainTemplateTab.document.findingInEdition = -1; + pretoxSRDomainTemplateTab.enableAddFindingEvent.emit(true); + row.getElement().className = "tabulator-row"; + row.getCells().forEach(rowCell => { + rowCell.getElement().className = "tabulator-cell non-editable-cell"; + }); + cell.getElement().innerHTML = ''; + row.getCell('ed').getElement().innerHTML = '
'; + pretoxSRDomainTemplateTab.rowClickUpdateFindingEvent.emit(cell.getData()); } }, - formatter: function(cell, formatterParams, onRendered) { - return ''; + formatter: function (cell, formatterParams, onRendered) { + return ''; } }, { - title:'', width: 5, field: 'srDomainId' + title: '', width: 5, field: 'srDomainId', cssClass: "tabulator-cell non-editable-cell", }, { - title: 'Finding', field: 'srfndg', headerSort: true , editor: 'autocomplete' , editable: this.editCheck.bind(this), - editorParams:this.paramLookupFinding.bind(this), sorter: "string", formatter: this.ellipsisFormatter + title: 'Finding', field: 'srfndg', cssClass: "tabulator-cell non-editable-cell", headerSort: true, editor: 'autocomplete', editable: this.editCheck.bind(this), + editorParams: this.paramLookupFinding.bind(this), sorter: "string", formatter: this.ellipsisFormatter }, - //{title: 'Finding (Free Text)', field: 'srores', headerSort: true , headerFilter: false},//SRORES { - title: 'Test Name', field: 'srtstcd', headerSort: true , editor: 'autocomplete', editable: this.editCheck.bind(this), - editorParams:this.paramLookupStudyTest.bind(this), sorter: "string", formatter: this.ellipsisFormatter + title: 'Test Name', field: 'srtstcd', cssClass: "tabulator-cell non-editable-cell", headerSort: true, editor: 'autocomplete', editable: this.editCheck.bind(this), + editorParams: this.paramLookupStudyTest.bind(this), sorter: "string", formatter: this.ellipsisFormatter }, { - title: 'Manifestation', field: 'srobsv', headerSort: true , editable: this.editCheck.bind(this), editor: "autocomplete", - editorParams:this.paramLookupManifestation.bind(this) + title: 'Manifestation', field: 'srobsv', cssClass: "tabulator-cell non-editable-cell", headerSort: true, editable: this.editCheck.bind(this), editor: "autocomplete", + editorParams: this.paramLookupManifestation.bind(this) }, { - title: 'Domain', field: 'srdomain', headerSort: true , editor: 'autocomplete', editable: this.editCheck.bind(this), + title: 'Domain', field: 'srdomain', cssClass: "tabulator-cell non-editable-cell", headerSort: true, editor: 'autocomplete', editable: this.editCheck.bind(this), editorParams: this.paramLookupStudyDomain.bind(this), sorter: "string", formatter: this.ellipsisFormatter, cellEdited: this.onStudyDomainChange.bind(this) }, { - title: 'Specimen', field: 'srspec', headerSort: true , editor: 'autocomplete', editable: this.editCheck.bind(this), - editorParams:this.paramLookupSpecies.bind(this), sorter: "string", formatter: this.ellipsisFormatter + title: 'Specimen', field: 'srspec', cssClass: "tabulator-cell non-editable-cell", headerSort: true, editor: 'autocomplete', editable: this.editCheck.bind(this), + editorParams: this.paramLookupSpecies.bind(this), sorter: "string", formatter: this.ellipsisFormatter }, { - title: 'Sex', field: 'srsex', headerSort: true, editor: 'select', editable: this.editCheck.bind(this), editorParams:{ - values:['Female','Male','Both']} + title: 'Sex', field: 'srsex', cssClass: "tabulator-cell non-editable-cell", headerSort: true, editor: 'select', editable: this.editCheck.bind(this), editorParams: { + values: ['Female', 'Male', 'Both'] + } }, { - title: 'Dose', field: 'srgrpdos', headerSort: true, editor: 'input', editable: this.editCheck.bind(this) + title: 'Dose', field: 'srgrpdos', cssClass: "tabulator-cell non-editable-cell", headerSort: true, editor: 'input', editable: this.editCheck.bind(this) }, { - title: 'Group', field: 'spgrpcd', headerSort: true, editor: 'input', editable: this.editCheck.bind(this), + title: 'Group', field: 'spgrpcd', cssClass: "tabulator-cell non-editable-cell", headerSort: true, editor: 'input', editable: this.editCheck.bind(this), }, { - title: 'Treatment Related?', field: 'srtrtef', headerSort: true, editor: 'select', editable: this.editCheck.bind(this), editorParams: { - values:['Yes','No','Uncertain']} + title: 'Treatment Related?', field: 'srtrtef', cssClass: "tabulator-cell non-editable-cell", headerSort: true, editor: 'select', editable: this.editCheck.bind(this), editorParams: { + values: ['Yes', 'No', 'Uncertain'] + } }, ] }); document.getElementById('my-tabular-table-srdomaintemplate').appendChild(this.tab); - table.redraw(true); + //this.table.redraw(true); } } diff --git a/src/styles.css b/src/styles.css index 74eeba021b3b3c797b0ebfbe4f326c6cf65dd9d0..25f1418bab05954844fb016688b66a26ac8d8154 100644 --- a/src/styles.css +++ b/src/styles.css @@ -1,11 +1 @@ -@import "./node_modules/@angular/material/prebuilt-themes/indigo-pink.css"; -/* .tabulator { - font-size: 100px; - border: none; - } - .tabulator-row-odd { - background-color: #553333 !important; -} -.tabulator-row-even { - background-color: #335533 !important; -} */ \ No newline at end of file +@import "./node_modules/@angular/material/prebuilt-themes/indigo-pink.css"; \ No newline at end of file diff --git a/src/tabulator.css b/src/tabulator.css new file mode 100644 index 0000000000000000000000000000000000000000..d7dfa61147e39bc19ea13e25464e3f0b1d9e9012 --- /dev/null +++ b/src/tabulator.css @@ -0,0 +1,84 @@ +.tabulator-cell .non-curated .fa.fa-square { + color: grey; + cursor: pointer; +} + +.tabulator-cell .non-curable .fa.fa-square { + color: grey; + cursor: default; + opacity: 0.6; +} + +.tabulator-cell .not-exported .fa.fa-square { + color: grey; + cursor: pointer; +} + +.tabulator-cell .rejected .fa.fa-times { + color: red; + cursor: pointer; +} + +.tabulator-cell .accepted .fa.fa-check { + color: green; + cursor: pointer; +} + +.tabulator-cell .exported .fa.fa-file-circle-check { + color: blue; + cursor: pointer; +} + +.tabulator-cell .non-exportable .fa.fa-file-circle-check { + color: grey; + cursor: default; + opacity: 0.6; +} + +.tabulator-cell .evidence .fa.fa-eye { + color: #8e44ad; + cursor: pointer; +} + +.tabulator-cell .no-evidence .fa.fa-eye { + color: #8e44ad; + cursor: default; + opacity: 0.6; +} + +.tabulator-cell .save-finding .fa-solid.fa-floppy-disk { + color: black; + cursor: pointer; +} + +.tabulator-cell .cancel-edition .fa-solid.fa-pencil { + color: #abb2b9; + cursor: pointer; +} + +.tabulator-cell .edition-unabled .fa-solid.fa-pencil { + color: #566573; + cursor: default; +} + +.tabulator-cell .enable-edition .fa-solid.fa-pencil { + color: #566573; + cursor: pointer; +} + +.tabulator-cell.editable-cell { + cursor: pointer; + background-color: #ffcc66; +} + +.tabulator-cell.non-editable-cell { + cursor: default; +} + +.tabulator-row.editable { + background-color: #ffcc66; +} + +.tabulator-row.evidence-selected { + border: 1px solid black; +}