Skip to content

Commit

Permalink
UI Navigation Patients : Enable to use Patient Management services in…
Browse files Browse the repository at this point in the history
… external archive #4195
  • Loading branch information
vrindanayak committed Aug 24, 2023
1 parent d1b6774 commit fa7e136
Show file tree
Hide file tree
Showing 8 changed files with 306 additions and 0 deletions.
7 changes: 7 additions & 0 deletions dcm4chee-arc-ui2/src/app/constants/globalvar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3911,6 +3911,13 @@ export class Globalvar {
"restore":undefined,
}
},
"action-patients-merge":{
type:"action",
title:"Action - Patients - Merge",
params:{
"visible":undefined,
}
},
"action-studies-copy_merge_move":{
type:"action",
title:"Action - Studies - Copy Merge Move",
Expand Down
20 changes: 20 additions & 0 deletions dcm4chee-arc-ui2/src/app/helpers/j4care.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1826,4 +1826,24 @@ export class j4care {
return false;
}
}

static extractPropertiesFromWebApp(dcmWebApp:DcmWebApp){
try{
let properties = {};
const regex = /([\w-]*)=([\w -]*)/;
let m;
if(_.hasIn(dcmWebApp,"dcmProperty")){
dcmWebApp.dcmProperty.forEach(prop=>{
if ((m = regex.exec(prop)) !== null) {
properties[m[1]] = m[2];
}
})
}
return properties;
}catch(e){
this.log("Error on getting properties dcmWebApp:",dcmWebApp);
this.log("e:",e);
return {};
}
}
}
17 changes: 17 additions & 0 deletions dcm4chee-arc-ui2/src/app/study/study/study.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,23 @@ <h2>{{studyConfig.title}}</h2>
</div>
</div>
</div>
<div class="selection_actions" *ngIf="tableParam.config.showCheckboxes && studyWebService && studyWebService.selectedWebService
&& studyWebService.selectedWebService.dcmProperty && studyWebService.selectedWebService.dcmProperty.indexOf('PAMWebApp') > -1"
[permission]="{id:'action-patients-merge',param:'visible'}">
<ul class="selection_functions">
<li class="ignore_click_outside"><button class="ignore_click_outside" [ngClass]="{'active':checkboxFunctions}" (click)="selectionAction('checkbox_functions')"><i class="ignore_click_outside material-icons">playlist_add_check</i></button></li>
<li><button [disabled]="selectedElements.action" (click)="selectionAction('patient_merge')" i18n-title="@@title.study.mark_selected_patient_for_merge" title="Mark selected patient for merge"><i class="material-icons">supervisor_account</i></button></li>
<li><button (click)="selectionAction('paste')" i18n-title="@@title.study.start_the_process_of_merge" title="Start the process of merging"><i class="glyphicon glyphicon-paste"></i></button></li>
</ul>
<ul *ngIf="checkboxFunctions" class="checkbox_functions" (clickOutside)='checkboxFunctions = !checkboxFunctions' [clickOutsideExceptionClass]="['ignore_click_outside']">
<li class="ignore_click_outside"><button class="ignore_click_outside" (click)="selectionAction('remove_selection')" i18n="@@remove_all_selections">Remove all selections</button></li>
<li class="ignore_click_outside"><button class="ignore_click_outside" (click)="selectionAction('check_selection_study')" i18n="@@select_all_studies">Select all studies</button></li>
<li class="ignore_click_outside"><button class="ignore_click_outside" (click)="selectionAction('uncheck_selection_study')" i18n="@@unselect_all_studies">Unselect all studies</button></li>
<li class="ignore_click_outside"><button class="ignore_click_outside" (click)="selectionAction('check_selection_patient')" i18n="@@select_all_patients">Select all patients</button></li>
<li class="ignore_click_outside"><button class="ignore_click_outside" (click)="selectionAction('uncheck_selection_patient')" i18n="@@unselect_all_patients">Unselect all patients</button></li>
<li class="ignore_click_outside"><button class="ignore_click_outside" (click)="selectionAction('hide_checkboxes')" i18n="@@hide_checkboxes">Hide checkboxes</button></li>
</ul>
</div>
<div class="selection_actions" *ngIf="tableParam.config.showCheckboxes && studyWebService && studyWebService.selectedWebService && studyWebService.selectedWebService.dcmWebServiceClass.indexOf('DCM4CHEE_ARC_AET') > -1" [permission]="{id:'action-studies-copy_merge_move',param:'visible'}">
<ul class="selection_functions">
<li class="ignore_click_outside"><button class="ignore_click_outside" [ngClass]="{'active':checkboxFunctions}" (click)="selectionAction('checkbox_functions')"><i class="ignore_click_outside material-icons">playlist_add_check</i></button></li>
Expand Down
27 changes: 27 additions & 0 deletions dcm4chee-arc-ui2/src/app/study/study/study.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,7 @@ export class StudyComponent implements OnInit, OnDestroy, AfterContentChecked{
placeholder: $localize `:@@more_functions:More functions`,
options:[
new SelectDropdown("create_patient",$localize `:@@study.create_patient:Create patient`),
new SelectDropdown("create_patient_ext_arc",$localize `:@@study.create_patient_ext_arc:Create patient in external archive`),
new SelectDropdown("supplement_issuer",$localize `:@@supplement_issuer:Supplement Issuer`),
new SelectDropdown("update_charset",$localize `:@@update_charset:Update Character Set of patients`),
new SelectDropdown("create_ups",$localize `:@@create_new_ups:Create new UPS Workitem`),
Expand Down Expand Up @@ -535,6 +536,9 @@ export class StudyComponent implements OnInit, OnDestroy, AfterContentChecked{
case "create_patient":
this.createPatient();
break;
case "create_patient_ext_arc":
this.createPatientInExternalArchive();
break;
case "supplement_issuer":
this.supplementIssuer();
break;
Expand Down Expand Up @@ -3037,6 +3041,11 @@ export class StudyComponent implements OnInit, OnDestroy, AfterContentChecked{
let studyConfig = args[1];
return value.filter(option=>{
console.log("option",option);
if (option.value === "create_patient_ext_arc") {
return studyConfig && studyConfig.tab === "patient"
&& this.service.webAppHasPAMWebApp(this.studyWebService, "QIDO_RS")
&& !this.service.webAppGroupHasClass(this.studyWebService,"DCM4CHEE_ARC_AET");
}
if(option.value === "create_patient"
|| option.value === "supplement_issuer"
|| option.value === "update_charset"
Expand Down Expand Up @@ -3234,6 +3243,24 @@ export class StudyComponent implements OnInit, OnDestroy, AfterContentChecked{
});
}

createPatientInExternalArchive() {
let config:ModifyConfig = {
saveLabel:$localize `:@@CREATE:CREATE`,
titleLabel:$localize `:@@study.create_new_patient:Create new patient`
};
let newPatient: any = {
'attrs': {
'00100010': { 'vr': 'PN', 'Value': [{
Alphabetic: ''
}]},
'00100020': { 'vr': 'LO', 'Value': ['']},
'00100021': { 'vr': 'LO', 'Value': ['']},
'00100030': { 'vr': 'DA', 'Value': ['']},
'00100040': { 'vr': 'CS', 'Value': ['']}
}
};
}

createPatient(){
let config:ModifyConfig = {
saveLabel:$localize `:@@CREATE:CREATE`,
Expand Down
13 changes: 13 additions & 0 deletions dcm4chee-arc-ui2/src/app/study/study/study.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4268,6 +4268,19 @@ export class StudyService {
}));
}

webAppHasPAMWebApp(studyWebService:StudyWebService, webServiceClass:WebServiceClass) {
try {
return _.hasIn(studyWebService,"selectedWebService.dcmWebServiceClass")
&& studyWebService.selectedWebService.dcmWebServiceClass.indexOf(webServiceClass) > -1
&& studyWebService.webServices.filter((webApp:DcmWebApp) => {
const webAppProperties = j4care.extractPropertiesFromWebApp(webApp);
return _.hasIn(webAppProperties, "PAMWebApp");
})
} catch(e){
return false;
}
}

webAppGroupHasClass(studyWebService:StudyWebService, webServiceClass:WebServiceClass){
try{
return (_.hasIn(studyWebService,"selectedWebService.dcmWebServiceClass") && studyWebService.selectedWebService.dcmWebServiceClass.indexOf(webServiceClass) > -1) ||
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
.issuerpicker{
max-height: 350px;
overflow: auto;
position: absolute;
z-index: 98;
background: white;
-webkit-box-shadow: 3px 4px 8px 6px #cccccc;
-moz-box-shadow: 3px 4px 8px 6px #cccccc;
box-shadow: 3px 4px 8px 6px #cccccc;
padding:20px 30px;
}
.issuerpicker .msg{
float: left;
margin: 20px 0 0px 0;
width: 100%;
font-size:12px;
}
.issuerpicker .close{
position: absolute;
right: 10px;
top: 10px;
font-size: 13px;
}
.issuerpicker .btn_content{
width: 100%;
}

.issuer-picker-element {
margin-left: 5px;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<div class="issuerpicker" (keyup)="onModelChange($event)">
<div class="close issuer-picker-element" (click)="close()"><span class="glyphicon glyphicon-remove issuer-picker-element"></span></div>
<h6 *ngIf="mode === 'dcmIssuer'" i18n="@@add_issuer">Add Issuer</h6>
<div class="form-group" *ngIf="mode === 'dcmIssuer'">
<label class="control-label text-right col-md-5" for="hour" i18n="@@local_namespace_id">Local Namespace Entity ID:</label>
<div class="col-md-7">
<input type="string" class="col-md-12" id="hour" [(ngModel)]="localNamespaceEntityID">
</div>
</div>
<div class="form-group" *ngIf="mode === 'dcmIssuer'">
<label class="control-label text-right col-md-5" for="minute" i18n="@@universal_entity_id">Universal Entity ID:</label>
<div class="col-md-7">
<input type="string" class="col-md-12" id="minute" [(ngModel)]="universalEntityID">
</div>
</div>
<div class="form-group" *ngIf="mode === 'dcmIssuer'">
<label class="control-label text-right col-md-5" for="sec" i18n="@@universal_entity_id_type">Universal Entity ID Type:</label>
<div class="col-md-7">
<input type="string" class="col-md-12" id="sec" [(ngModel)]="universalEntityIDType">
</div>
</div>
<p class="msg">
{{message}}
</p>
<div class="btn_content">
<button class="btn issuer-picker-element" (click)="addIssuer()" i18n="@@Set">Set</button>
<button class="btn issuer-picker-element" (click)="clear()" i18n="@@Clear">Clear</button>
</div>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
import {Component, OnInit, EventEmitter, Output, Input} from '@angular/core';
import * as _ from 'lodash-es';

const WEEK = {
plural:$localize `:@@week_plural:weeks`,
singular:$localize `:@@week_singular:week`
};
const YEAR = {
plural:$localize `:@@year_plural:years`,
singular:$localize `:@@year_singular:year`
};
const DAY = {
plural:$localize `:@@day_plural:days`,
singular:$localize `:@@day_singular:day`
};
const HOUR = {
plural:$localize `:@@hour_plural:hours`,
singular:$localize `:@@hour_singular:hour`
};
const MINUTE = {
plural:$localize `:@@minute_plural:minutes`,
singular:$localize `:@@minute_singular:minute`
};
const SECOND = {
plural:$localize `:@@second_plural:seconds`,
singular:$localize `:@@second_singular:second`
};
const MONTH = {
plural:$localize `:@@month_plural:months`,
singular:$localize `:@@month_singular:month`
};

@Component({
selector: 'duration-picker',
templateUrl: './issuer-picker.component.html',
styleUrls: ['./issuer-picker.component.css']
})
export class IssuerPickerComponent implements OnInit {


@Output() onValueSet = new EventEmitter();
@Input() mode;
@Input() value;
constructor() { }
y; //yeaar
d; //day
month;
h; //hour
m; //minute
s; //second
week;
localNamespaceEntityID;
universalEntityID;
universalEntityIDType;
message;

ngOnInit() {
this.extractIssuerFromValue();
this.onModelChange(null);
}

extractIssuerFromValue(){
let match;
let ptrn = /(\d)(\w)/g;
try {
while ((match = ptrn.exec(this.value)) != null) {
if(this.mode === "dcmDuration"){
switch(match[2]) {
case 'D':
this.d = parseInt(match[1]);
break;
case 'H':
this.h = parseInt(match[1]);
break;
case 'M':
this.m = parseInt(match[1]);
break;
case 'S':
this.s = parseInt(match[1]);
break;
}
}else{
if(this.mode === "datePicker"){
switch(match[2]) {
case 'D':
this.d = parseInt(match[1]);
break;
case 'H':
this.h = parseInt(match[1]);
break;
case 'M':
this.m = parseInt(match[1]);
break;
}
}else{
switch(match[2]) {
case 'Y':
this.y = parseInt(match[1]);
break;
case 'W':
this.week = parseInt(match[1]);
break;
case 'M':
this.month = parseInt(match[1]);
break;
case 'D':
this.d = parseInt(match[1]);
break;
}
}
}
}
}catch (e){
console.error("error parsing data!",e);
}
}
addIssuer(){
this.onValueSet.emit(this.generateIssuer());
}
clear(){
this.onValueSet.emit('empty');
}
generateIssuer(){
let issuer = '';
if (this._isset(this.localNamespaceEntityID)) {
issuer = this.localNamespaceEntityID;
if (this._isset(this.universalEntityID) && this._isset(this.universalEntityIDType))
issuer += `&${this.universalEntityID}&${this.universalEntityIDType}`;
} else if (this._isset(this.universalEntityID) && this._isset(this.universalEntityIDType)) {
issuer = `&${this.universalEntityID}&${this.universalEntityIDType}`;
}

return issuer;
}

close(){
this.onValueSet.emit("");
}

onModelChange(e){
this.message = $localize `:@@this_period_will_last_week:The issuer configured will be `;
if (this._isset(this.localNamespaceEntityID)) {
this.message += `${this.localNamespaceEntityID}`;
if (this._isset(this.universalEntityID) && this._isset(this.universalEntityIDType))
this.message += `&${this.universalEntityID}&${this.universalEntityIDType}`;
} else if (this._isset(this.universalEntityID) && this._isset(this.universalEntityIDType))
this.message += `&${this.universalEntityID}&${this.universalEntityIDType}`;

if ((this._isset(this.universalEntityID) && !this._isset(this.universalEntityIDType))
|| (!this._isset(this.universalEntityID) && this._isset(this.universalEntityIDType)))
this.message = $localize `:@@invalid_universal_issuer:Invalid universal issuer: ` + `&${this.universalEntityID}&${this.universalEntityIDType}`;
}

_isset(v){
return v && v != "" && v != null;
}

_clearFromEmptyValue(array, objectKey){
return _.remove(array,(m)=>{
return this._isset(m[objectKey]);
})
}
}

0 comments on commit fa7e136

Please sign in to comment.