comparison OrthancExplorer/explorer.js @ 2884:497a637366b4 db-changes

integration mainline->db-changes
author Sebastien Jodogne <s.jodogne@gmail.com>
date Fri, 12 Oct 2018 15:18:10 +0200
parents 67ebfacf4467
children e0c620f964e5
comparison
equal deleted inserted replaced
1762:2b91363cc1d1 2884:497a637366b4
11 //$.mobile.ajaxEnabled = false; 11 //$.mobile.ajaxEnabled = false;
12 //$.mobile.page.prototype.options.addBackBtn = true; 12 //$.mobile.page.prototype.options.addBackBtn = true;
13 //$.mobile.defaultPageTransition = 'slide'; 13 //$.mobile.defaultPageTransition = 'slide';
14 14
15 15
16 var LIMIT_RESOURCES = 100;
17
16 var currentPage = ''; 18 var currentPage = '';
17 var currentUuid = ''; 19 var currentUuid = '';
18 20
19 21
20 // http://stackoverflow.com/a/4673436 22 function DeepCopy(obj)
21 String.prototype.format = function() { 23 {
22 var args = arguments; 24 return jQuery.extend(true, {}, obj);
23 return this.replace(/{(\d+)}/g, function(match, number) { 25 }
24 /*return typeof args[number] != 'undefined' 26
25 ? args[number] 27
26 : match;*/ 28 function ChangePage(page, options)
27 29 {
28 return args[number]; 30 var first = true;
29 }); 31 if (options) {
30 }; 32 for (var key in options) {
33 var value = options[key];
34 if (first) {
35 page += '?';
36 first = false;
37 } else {
38 page += '&';
39 }
40
41 page += key + '=' + value;
42 }
43 }
44
45 window.location.replace('explorer.html#' + page);
46 /*$.mobile.changePage('#' + page, {
47 changeHash: true
48 });*/
49 }
31 50
32 51
33 function Refresh() 52 function Refresh()
34 { 53 {
35 if (currentPage == 'patient') 54 if (currentPage == 'patient')
177 } 196 }
178 }); 197 });
179 } 198 }
180 199
181 200
182 function CompleteFormatting(s, link, isReverse) 201 function CompleteFormatting(node, link, isReverse, count)
183 { 202 {
203 if (count != null)
204 {
205 node = node.add($('<span>')
206 .addClass('ui-li-count')
207 .text(count));
208 }
209
184 if (link != null) 210 if (link != null)
185 { 211 {
186 s = 'href="' + link + '">' + s + '</a>'; 212 node = $('<a>').attr('href', link).append(node);
187 213
188 if (isReverse) 214 if (isReverse)
189 s = 'data-direction="reverse" '+ s; 215 node.attr('data-direction', 'reverse')
190 216 }
191 s = '<a ' + s; 217
192 } 218 node = $('<li>').append(node);
193 219
194 if (isReverse) 220 if (isReverse)
195 return '<li data-icon="back">' + s + '</li>'; 221 node.attr('data-icon', 'back');
196 else 222
197 return '<li>' + s + '</li>'; 223 return node;
198 } 224 }
199 225
200 226
201 function FormatMainDicomTags(tags, tagsToIgnore) 227 function FormatMainDicomTags(target, tags, tagsToIgnore)
202 { 228 {
203 var s = '';
204
205 for (var i in tags) 229 for (var i in tags)
206 { 230 {
207 if (tagsToIgnore.indexOf(i) == -1) 231 if (tagsToIgnore.indexOf(i) == -1)
208 { 232 {
209 var v = tags[i]; 233 var v = tags[i];
218 i == "DicomSeriesInstanceUID") 242 i == "DicomSeriesInstanceUID")
219 { 243 {
220 v = SplitLongUid(v); 244 v = SplitLongUid(v);
221 } 245 }
222 246
223 247 target.append($('<p>')
224 s += ('<p>{0}: <strong>{1}</strong></p>').format(i, v); 248 .text(i + ': ')
225 } 249 .append($('<strong>').text(v)));
226 } 250 }
227 251 }
228 return s;
229 } 252 }
230 253
231 254
232 function FormatPatient(patient, link, isReverse) 255 function FormatPatient(patient, link, isReverse)
233 { 256 {
234 var s = ('<h3>{0}</h3>{1}' + 257 var node = $('<div>').append($('<h3>').text(patient.MainDicomTags.PatientName));
235 '<span class="ui-li-count">{2}</span>' 258
236 ).format 259 FormatMainDicomTags(node, patient.MainDicomTags, [
237 (patient.MainDicomTags.PatientName, 260 "PatientName"
238 FormatMainDicomTags(patient.MainDicomTags, [ 261 // "OtherPatientIDs"
239 "PatientName" 262 ]);
240 /*"OtherPatientIDs" */ 263
241 ]), 264 return CompleteFormatting(node, link, isReverse, patient.Studies.length);
242 patient.Studies.length 265 }
243 ); 266
244 267
245 return CompleteFormatting(s, link, isReverse); 268
246 } 269 function FormatStudy(study, link, isReverse, includePatient)
247 270 {
248 271 var label;
249 272
250 function FormatStudy(study, link, isReverse) 273 if (includePatient) {
251 { 274 label = study.Label;
252 var s = ('<h3>{0}</h3>{1}' + 275 } else {
253 '<span class="ui-li-count">{2}</span>' 276 label = study.MainDicomTags.StudyDescription;
254 ).format 277 }
255 (study.MainDicomTags.StudyDescription, 278
256 FormatMainDicomTags(study.MainDicomTags, [ 279 var node = $('<div>').append($('<h3>').text(label));
257 "StudyDescription", 280
258 "StudyTime" 281 if (includePatient) {
259 ]), 282 FormatMainDicomTags(node, study.PatientMainDicomTags, [
260 study.Series.length 283 'PatientName'
261 ); 284 ]);
262 285 }
263 return CompleteFormatting(s, link, isReverse); 286
287 FormatMainDicomTags(node, study.MainDicomTags, [
288 'StudyDescription',
289 'StudyTime'
290 ]);
291
292 return CompleteFormatting(node, link, isReverse, study.Series.length);
264 } 293 }
265 294
266 295
267 296
268 function FormatSeries(series, link, isReverse) 297 function FormatSeries(series, link, isReverse)
275 } 304 }
276 else 305 else
277 { 306 {
278 c = series.Instances.length + '/' + series.ExpectedNumberOfInstances; 307 c = series.Instances.length + '/' + series.ExpectedNumberOfInstances;
279 } 308 }
280 309
281 var s = ('<h3>{0}</h3>' + 310 var node = $('<div>')
282 '<p><em>Status: <strong>{1}</strong></em></p>{2}' + 311 .append($('<h3>').text(series.MainDicomTags.SeriesDescription))
283 '<span class="ui-li-count">{3}</span>').format 312 .append($('<p>').append($('<em>')
284 (series.MainDicomTags.SeriesDescription, 313 .text('Status: ')
285 series.Status, 314 .append($('<strong>').text(series.Status))));
286 FormatMainDicomTags(series.MainDicomTags, [ 315
316 FormatMainDicomTags(node, series.MainDicomTags, [
287 "SeriesDescription", 317 "SeriesDescription",
288 "SeriesTime", 318 "SeriesTime",
289 "Manufacturer", 319 "Manufacturer",
290 "ImagesInAcquisition", 320 "ImagesInAcquisition",
291 "SeriesDate", 321 "SeriesDate",
292 "ImageOrientationPatient" 322 "ImageOrientationPatient"
293 ]), 323 ]);
294 c 324
295 ); 325 return CompleteFormatting(node, link, isReverse, c);
296
297 return CompleteFormatting(s, link, isReverse);
298 } 326 }
299 327
300 328
301 function FormatInstance(instance, link, isReverse) 329 function FormatInstance(instance, link, isReverse)
302 { 330 {
303 var s = ('<h3>Instance {0}</h3>{1}').format 331 var node = $('<div>').append($('<h3>').text('Instance: ' + instance.IndexInSeries));
304 (instance.IndexInSeries, 332
305 FormatMainDicomTags(instance.MainDicomTags, [ 333 FormatMainDicomTags(node, instance.MainDicomTags, [
306 "AcquisitionNumber", 334 "AcquisitionNumber",
307 "InstanceNumber", 335 "InstanceNumber",
308 "InstanceCreationDate", 336 "InstanceCreationDate",
309 "InstanceCreationTime", 337 "InstanceCreationTime",
310 "ImagePositionPatient" 338 "ImagePositionPatient"
311 ]) 339 ]);
312 ); 340
313 341 return CompleteFormatting(node, link, isReverse);
314 return CompleteFormatting(s, link, isReverse);
315 } 342 }
316 343
317 344
318 $('[data-role="page"]').live('pagebeforeshow', function() { 345 $('[data-role="page"]').live('pagebeforeshow', function() {
319 $.ajax({ 346 $.ajax({
321 dataType: 'json', 348 dataType: 'json',
322 async: false, 349 async: false,
323 cache: false, 350 cache: false,
324 success: function(s) { 351 success: function(s) {
325 if (s.Name != "") { 352 if (s.Name != "") {
326 $('.orthanc-name').html('<a class="ui-link" href="explorer.html">' + s.Name + '</a> &raquo; '); 353 $('.orthanc-name').html($('<a>')
327 } 354 .addClass('ui-link')
328 } 355 .attr('href', 'explorer.html')
329 }); 356 .text(s.Name)
330 }); 357 .append(' &raquo; '));
331 358 }
359 }
360 });
361 });
362
363
364
365 $('#lookup').live('pagebeforeshow', function() {
366 // NB: "GenerateDicomDate()" is defined in "query-retrieve.js"
367 var target = $('#lookup-study-date');
368 $('option', target).remove();
369 target.append($('<option>').attr('value', '*').text('Any date'));
370 target.append($('<option>').attr('value', GenerateDicomDate(0)).text('Today'));
371 target.append($('<option>').attr('value', GenerateDicomDate(-1)).text('Yesterday'));
372 target.append($('<option>').attr('value', GenerateDicomDate(-7) + '-').text('Last 7 days'));
373 target.append($('<option>').attr('value', GenerateDicomDate(-31) + '-').text('Last 31 days'));
374 target.append($('<option>').attr('value', GenerateDicomDate(-31 * 3) + '-').text('Last 3 months'));
375 target.append($('<option>').attr('value', GenerateDicomDate(-365) + '-').text('Last year'));
376 target.selectmenu('refresh');
377
378 $('#lookup-result').hide();
379 });
380
381
382 $('#lookup-submit').live('click', function() {
383 $('#lookup-result').hide();
384
385 var lookup = {
386 'Level' : 'Study',
387 'Expand' : true,
388 'Limit' : LIMIT_RESOURCES + 1,
389 'Query' : {
390 'StudyDate' : $('#lookup-study-date').val()
391 }
392 };
393
394 $('#lookup-form input').each(function(index, input) {
395 if (input.value.length != 0) {
396 if (input.id == 'lookup-patient-id') {
397 lookup['Query']['PatientID'] = input.value;
398 }
399 else if (input.id == 'lookup-patient-name') {
400 lookup['Query']['PatientName'] = input.value;
401 }
402 else if (input.id == 'lookup-accession-number') {
403 lookup['Query']['AccessionNumber'] = input.value;
404 }
405 else if (input.id == 'lookup-study-description') {
406 lookup['Query']['StudyDescription'] = input.value;
407 }
408 else {
409 console.error('Unknown lookup field: ' + input.id);
410 }
411 }
412 });
413
414 $.ajax({
415 url: '../tools/find',
416 type: 'POST',
417 data: JSON.stringify(lookup),
418 dataType: 'json',
419 async: false,
420 error: function() {
421 alert('Error during lookup');
422 },
423 success: function(studies) {
424 FormatListOfStudies('#lookup-result ul', '#lookup-alert', '#lookup-count', studies);
425 $('#lookup-result').show();
426 }
427 });
428
429 return false;
430 });
332 431
333 432
334 $('#find-patients').live('pagebeforeshow', function() { 433 $('#find-patients').live('pagebeforeshow', function() {
335 GetResource('/patients?expand', function(patients) { 434 GetResource('/patients?expand&since=0&limit=' + (LIMIT_RESOURCES + 1), function(patients) {
336 var target = $('#all-patients'); 435 var target = $('#all-patients');
337 $('li', target).remove(); 436 $('li', target).remove();
338 437
339 SortOnDicomTag(patients, 'PatientName', false, false); 438 SortOnDicomTag(patients, 'PatientName', false, false);
340 439
341 for (var i = 0; i < patients.length; i++) { 440 var count, showAlert;
342 var p = FormatPatient(patients[i], '#patient?uuid=' + patients[i].ID); 441 if (patients.length <= LIMIT_RESOURCES) {
343 target.append(p); 442 count = patients.length;
344 } 443 showAlert = false;
345 444 }
346 target.listview('refresh'); 445 else {
446 count = LIMIT_RESOURCES;
447 showAlert = true;
448 }
449
450 for (var i = 0; i < count; i++) {
451 var p = FormatPatient(patients[i], '#patient?uuid=' + patients[i].ID);
452 target.append(p);
453 }
454
455 target.listview('refresh');
456
457 if (showAlert) {
458 $('#count-patients').text(LIMIT_RESOURCES);
459 $('#alert-patients').show();
460 } else {
461 $('#alert-patients').hide();
462 }
463 });
464 });
465
466
467
468 function FormatListOfStudies(targetId, alertId, countId, studies)
469 {
470 var target = $(targetId);
471 $('li', target).remove();
472
473 for (var i = 0; i < studies.length; i++) {
474 var patient = studies[i].PatientMainDicomTags.PatientName;
475 var study = studies[i].MainDicomTags.StudyDescription;
476
477 var s;
478 if (typeof patient === 'string') {
479 s = patient;
480 }
481
482 if (typeof study === 'string') {
483 if (s.length > 0) {
484 s += ' - ';
485 }
486
487 s += study;
488 }
489
490 studies[i]['Label'] = s;
491 }
492
493 Sort(studies, function(a) { return a.Label }, false, false);
494
495
496 var count, showAlert;
497 if (studies.length <= LIMIT_RESOURCES) {
498 count = studies.length;
499 showAlert = false;
500 }
501 else {
502 count = LIMIT_RESOURCES;
503 showAlert = true;
504 }
505
506 for (var i = 0; i < count; i++) {
507 var p = FormatStudy(studies[i], '#study?uuid=' + studies[i].ID, false, true);
508 target.append(p);
509 }
510
511 target.listview('refresh');
512
513 if (showAlert) {
514 $(countId).text(LIMIT_RESOURCES);
515 $(alertId).show();
516 } else {
517 $(alertId).hide();
518 }
519 }
520
521
522 $('#find-studies').live('pagebeforeshow', function() {
523 GetResource('/studies?expand&since=0&limit=' + (LIMIT_RESOURCES + 1), function(studies) {
524 FormatListOfStudies('#all-studies', '#alert-studies', '#count-studies', studies);
347 }); 525 });
348 }); 526 });
349 527
350 528
351 529
367 545
368 546
369 function RefreshPatient() 547 function RefreshPatient()
370 { 548 {
371 if ($.mobile.pageData) { 549 if ($.mobile.pageData) {
372 GetResource('/patients/' + $.mobile.pageData.uuid, function(patient) { 550 var pageData = DeepCopy($.mobile.pageData);
373 GetResource('/patients/' + $.mobile.pageData.uuid + '/studies', function(studies) { 551
552 GetResource('/patients/' + pageData.uuid, function(patient) {
553 GetResource('/patients/' + pageData.uuid + '/studies', function(studies) {
374 SortOnDicomTag(studies, 'StudyDate', false, true); 554 SortOnDicomTag(studies, 'StudyDate', false, true);
375 555
376 $('#patient-info li').remove(); 556 $('#patient-info li').remove();
377 $('#patient-info') 557 $('#patient-info')
378 .append('<li data-role="list-divider">Patient</li>') 558 .append('<li data-role="list-divider">Patient</li>')
383 $('li', target).remove(); 563 $('li', target).remove();
384 564
385 for (var i = 0; i < studies.length; i++) { 565 for (var i = 0; i < studies.length; i++) {
386 if (i == 0 || studies[i].MainDicomTags.StudyDate != studies[i - 1].MainDicomTags.StudyDate) 566 if (i == 0 || studies[i].MainDicomTags.StudyDate != studies[i - 1].MainDicomTags.StudyDate)
387 { 567 {
388 target.append('<li data-role="list-divider">{0}</li>'.format 568 target.append($('<li>')
389 (FormatDicomDate(studies[i].MainDicomTags.StudyDate))); 569 .attr('data-role', 'list-divider')
570 .text(FormatDicomDate(studies[i].MainDicomTags.StudyDate)));
390 } 571 }
391 572
392 target.append(FormatStudy(studies[i], '#study?uuid=' + studies[i].ID)); 573 target.append(FormatStudy(studies[i], '#study?uuid=' + studies[i].ID));
393 } 574 }
394 575
397 578
398 target.listview('refresh'); 579 target.listview('refresh');
399 580
400 // Check whether this patient is protected 581 // Check whether this patient is protected
401 $.ajax({ 582 $.ajax({
402 url: '../patients/' + $.mobile.pageData.uuid + '/protected', 583 url: '../patients/' + pageData.uuid + '/protected',
403 type: 'GET', 584 type: 'GET',
404 dataType: 'text', 585 dataType: 'text',
405 async: false, 586 async: false,
406 cache: false, 587 cache: false,
407 success: function (s) { 588 success: function (s) {
409 $('#protection').val(v).slider('refresh'); 590 $('#protection').val(v).slider('refresh');
410 } 591 }
411 }); 592 });
412 593
413 currentPage = 'patient'; 594 currentPage = 'patient';
414 currentUuid = $.mobile.pageData.uuid; 595 currentUuid = pageData.uuid;
415 }); 596 });
416 }); 597 });
417 } 598 }
418 } 599 }
419 600
420 601
421 function RefreshStudy() 602 function RefreshStudy()
422 { 603 {
423 if ($.mobile.pageData) { 604 if ($.mobile.pageData) {
424 GetResource('/studies/' + $.mobile.pageData.uuid, function(study) { 605 var pageData = DeepCopy($.mobile.pageData);
606
607 GetResource('/studies/' + pageData.uuid, function(study) {
425 GetResource('/patients/' + study.ParentPatient, function(patient) { 608 GetResource('/patients/' + study.ParentPatient, function(patient) {
426 GetResource('/studies/' + $.mobile.pageData.uuid + '/series', function(series) { 609 GetResource('/studies/' + pageData.uuid + '/series', function(series) {
427 SortOnDicomTag(series, 'SeriesDate', false, true); 610 SortOnDicomTag(series, 'SeriesDate', false, true);
428 611
429 $('#study .patient-link').attr('href', '#patient?uuid=' + patient.ID); 612 $('#study .patient-link').attr('href', '#patient?uuid=' + patient.ID);
430 $('#study-info li').remove(); 613 $('#study-info li').remove();
431 $('#study-info') 614 $('#study-info')
441 var target = $('#list-series'); 624 var target = $('#list-series');
442 $('li', target).remove(); 625 $('li', target).remove();
443 for (var i = 0; i < series.length; i++) { 626 for (var i = 0; i < series.length; i++) {
444 if (i == 0 || series[i].MainDicomTags.SeriesDate != series[i - 1].MainDicomTags.SeriesDate) 627 if (i == 0 || series[i].MainDicomTags.SeriesDate != series[i - 1].MainDicomTags.SeriesDate)
445 { 628 {
446 target.append('<li data-role="list-divider">{0}</li>'.format 629 target.append($('<li>')
447 (FormatDicomDate(series[i].MainDicomTags.SeriesDate))); 630 .attr('data-role', 'list-divider')
631 .text(FormatDicomDate(series[i].MainDicomTags.SeriesDate)));
448 } 632 }
633
449 target.append(FormatSeries(series[i], '#series?uuid=' + series[i].ID)); 634 target.append(FormatSeries(series[i], '#series?uuid=' + series[i].ID));
450 } 635 }
451 target.listview('refresh'); 636 target.listview('refresh');
452 637
453 currentPage = 'study'; 638 currentPage = 'study';
454 currentUuid = $.mobile.pageData.uuid; 639 currentUuid = pageData.uuid;
455 }); 640 });
456 }); 641 });
457 }); 642 });
458 } 643 }
459 } 644 }
460 645
461 646
462 function RefreshSeries() 647 function RefreshSeries()
463 { 648 {
464 if ($.mobile.pageData) { 649 if ($.mobile.pageData) {
465 GetResource('/series/' + $.mobile.pageData.uuid, function(series) { 650 var pageData = DeepCopy($.mobile.pageData);
651
652 GetResource('/series/' + pageData.uuid, function(series) {
466 GetResource('/studies/' + series.ParentStudy, function(study) { 653 GetResource('/studies/' + series.ParentStudy, function(study) {
467 GetResource('/patients/' + study.ParentPatient, function(patient) { 654 GetResource('/patients/' + study.ParentPatient, function(patient) {
468 GetResource('/series/' + $.mobile.pageData.uuid + '/instances', function(instances) { 655 GetResource('/series/' + pageData.uuid + '/instances', function(instances) {
469 Sort(instances, function(x) { return x.IndexInSeries; }, true, false); 656 Sort(instances, function(x) { return x.IndexInSeries; }, true, false);
470 657
471 $('#series .patient-link').attr('href', '#patient?uuid=' + patient.ID); 658 $('#series .patient-link').attr('href', '#patient?uuid=' + patient.ID);
472 $('#series .study-link').attr('href', '#study?uuid=' + study.ID); 659 $('#series .study-link').attr('href', '#study?uuid=' + study.ID);
473 660
490 target.append(FormatInstance(instances[i], '#instance?uuid=' + instances[i].ID)); 677 target.append(FormatInstance(instances[i], '#instance?uuid=' + instances[i].ID));
491 } 678 }
492 target.listview('refresh'); 679 target.listview('refresh');
493 680
494 currentPage = 'series'; 681 currentPage = 'series';
495 currentUuid = $.mobile.pageData.uuid; 682 currentUuid = pageData.uuid;
496 }); 683 });
497 }); 684 });
498 }); 685 });
499 }); 686 });
500 } 687 }
501 } 688 }
502 689
503 690
691 function EscapeHtml(value)
692 {
693 var ENTITY_MAP = {
694 '&': '&amp;',
695 '<': '&lt;',
696 '>': '&gt;',
697 '"': '&quot;',
698 "'": '&#39;',
699 '/': '&#x2F;',
700 '`': '&#x60;',
701 '=': '&#x3D;'
702 };
703
704 return String(value).replace(/[&<>"'`=\/]/g, function (s) {
705 return ENTITY_MAP[s];
706 });
707 }
708
504 709
505 function ConvertForTree(dicom) 710 function ConvertForTree(dicom)
506 { 711 {
507 var result = []; 712 var result = [];
508 713
509 for (var i in dicom) { 714 for (var i in dicom) {
510 if (dicom[i] != null) { 715 if (dicom[i] != null) {
511 var label = i + '<span class="tag-name"> (<i>' + dicom[i]["Name"] + '</i>)</span>: '; 716 var label = (i + '<span class="tag-name"> (<i>' +
717 EscapeHtml(dicom[i]["Name"]) +
718 '</i>)</span>: ');
512 719
513 if (dicom[i]["Type"] == 'String') 720 if (dicom[i]["Type"] == 'String')
514 { 721 {
515 result.push({ 722 result.push({
516 label: label + '<strong>' + dicom[i]["Value"] + '</strong>', 723 label: label + '<strong>' + EscapeHtml(dicom[i]["Value"]) + '</strong>',
517 children: [] 724 children: []
518 }); 725 });
519 } 726 }
520 else if (dicom[i]["Type"] == 'TooLong') 727 else if (dicom[i]["Type"] == 'TooLong')
521 { 728 {
554 761
555 762
556 function RefreshInstance() 763 function RefreshInstance()
557 { 764 {
558 if ($.mobile.pageData) { 765 if ($.mobile.pageData) {
559 GetResource('/instances/' + $.mobile.pageData.uuid, function(instance) { 766 var pageData = DeepCopy($.mobile.pageData);
767
768 GetResource('/instances/' + pageData.uuid, function(instance) {
560 GetResource('/series/' + instance.ParentSeries, function(series) { 769 GetResource('/series/' + instance.ParentSeries, function(series) {
561 GetResource('/studies/' + series.ParentStudy, function(study) { 770 GetResource('/studies/' + series.ParentStudy, function(study) {
562 GetResource('/patients/' + study.ParentPatient, function(patient) { 771 GetResource('/patients/' + study.ParentPatient, function(patient) {
563 772
564 $('#instance .patient-link').attr('href', '#patient?uuid=' + patient.ID); 773 $('#instance .patient-link').attr('href', '#patient?uuid=' + patient.ID);
583 792
584 SetupAnonymizedOrModifiedFrom('#instance-anonymized-from', instance, 'instance', 'AnonymizedFrom'); 793 SetupAnonymizedOrModifiedFrom('#instance-anonymized-from', instance, 'instance', 'AnonymizedFrom');
585 SetupAnonymizedOrModifiedFrom('#instance-modified-from', instance, 'instance', 'ModifiedFrom'); 794 SetupAnonymizedOrModifiedFrom('#instance-modified-from', instance, 'instance', 'ModifiedFrom');
586 795
587 currentPage = 'instance'; 796 currentPage = 'instance';
588 currentUuid = $.mobile.pageData.uuid; 797 currentUuid = pageData.uuid;
589 }); 798 });
590 }); 799 });
591 }); 800 });
592 }); 801 });
593 } 802 }
702 911
703 912
704 913
705 $('#instance-preview').live('click', function(e) { 914 $('#instance-preview').live('click', function(e) {
706 if ($.mobile.pageData) { 915 if ($.mobile.pageData) {
707 var pdf = '../instances/' + $.mobile.pageData.uuid + '/pdf'; 916 var pageData = DeepCopy($.mobile.pageData);
917
918 var pdf = '../instances/' + pageData.uuid + '/pdf';
708 $.ajax({ 919 $.ajax({
709 url: pdf, 920 url: pdf,
710 cache: false, 921 cache: false,
711 success: function(s) { 922 success: function(s) {
712 window.location.assign(pdf); 923 window.location.assign(pdf);
713 }, 924 },
714 error: function() { 925 error: function() {
715 GetResource('/instances/' + $.mobile.pageData.uuid + '/frames', function(frames) { 926 GetResource('/instances/' + pageData.uuid + '/frames', function(frames) {
716 if (frames.length == 1) 927 if (frames.length == 1)
717 { 928 {
718 // Viewing a single-frame image 929 // Viewing a single-frame image
719 jQuery.slimbox('../instances/' + $.mobile.pageData.uuid + '/preview', '', { 930 jQuery.slimbox('../instances/' + pageData.uuid + '/preview', '', {
720 overlayFadeDuration : 1, 931 overlayFadeDuration : 1,
721 resizeDuration : 1, 932 resizeDuration : 1,
722 imageFadeDuration : 1 933 imageFadeDuration : 1
723 }); 934 });
724 } 935 }
726 { 937 {
727 // Viewing a multi-frame image 938 // Viewing a multi-frame image
728 939
729 var images = []; 940 var images = [];
730 for (var i = 0; i < frames.length; i++) { 941 for (var i = 0; i < frames.length; i++) {
731 images.push([ '../instances/' + $.mobile.pageData.uuid + '/frames/' + i + '/preview' ]); 942 images.push([ '../instances/' + pageData.uuid + '/frames/' + i + '/preview' ]);
732 } 943 }
733 944
734 jQuery.slimbox(images, 0, { 945 jQuery.slimbox(images, 0, {
735 overlayFadeDuration : 1, 946 overlayFadeDuration : 1,
736 resizeDuration : 1, 947 resizeDuration : 1,
746 957
747 958
748 959
749 $('#series-preview').live('click', function(e) { 960 $('#series-preview').live('click', function(e) {
750 if ($.mobile.pageData) { 961 if ($.mobile.pageData) {
751 GetResource('/series/' + $.mobile.pageData.uuid, function(series) { 962 var pageData = DeepCopy($.mobile.pageData);
752 GetResource('/series/' + $.mobile.pageData.uuid + '/instances', function(instances) { 963
964 GetResource('/series/' + pageData.uuid, function(series) {
965 GetResource('/series/' + pageData.uuid + '/instances', function(instances) {
753 Sort(instances, function(x) { return x.IndexInSeries; }, true, false); 966 Sort(instances, function(x) { return x.IndexInSeries; }, true, false);
754 967
755 var images = []; 968 var images = [];
756 for (var i = 0; i < instances.length; i++) { 969 for (var i = 0; i < instances.length; i++) {
757 images.push([ '../instances/' + instances[i].ID + '/preview', 970 images.push([ '../instances/' + instances[i].ID + '/preview',
758 '{0}/{1}'.format(i + 1, instances.length) ]) 971 (i + 1).toString() + '/' + instances.length.toString() ])
759 } 972 }
760 973
761 jQuery.slimbox(images, 0, { 974 jQuery.slimbox(images, 0, {
762 overlayFadeDuration : 1, 975 overlayFadeDuration : 1,
763 resizeDuration : 1, 976 resizeDuration : 1,
856 } 1069 }
857 1070
858 1071
859 $('#instance-store,#series-store,#study-store,#patient-store').live('click', function(e) { 1072 $('#instance-store,#series-store,#study-store,#patient-store').live('click', function(e) {
860 ChooseDicomModality(function(modality, peer) { 1073 ChooseDicomModality(function(modality, peer) {
1074 var pageData = DeepCopy($.mobile.pageData);
1075
861 var url; 1076 var url;
862 var loading; 1077 var loading;
863 1078
864 if (modality != '') 1079 if (modality != '')
865 { 1080 {
876 if (url != '') { 1091 if (url != '') {
877 $.ajax({ 1092 $.ajax({
878 url: url, 1093 url: url,
879 type: 'POST', 1094 type: 'POST',
880 dataType: 'text', 1095 dataType: 'text',
881 data: $.mobile.pageData.uuid, 1096 data: pageData.uuid,
882 async: true, // Necessary to block UI 1097 async: true, // Necessary to block UI
883 beforeSend: function() { 1098 beforeSend: function() {
884 $.blockUI({ message: $(loading) }); 1099 $.blockUI({ message: $(loading) });
885 }, 1100 },
886 complete: function(s) { 1101 complete: function(s) {
1050 1265
1051 target.listview('refresh'); 1266 target.listview('refresh');
1052 } 1267 }
1053 }); 1268 });
1054 }); 1269 });
1270
1271
1272
1273 function ParseJobTime(s)
1274 {
1275 var t = (s.substr(0, 4) + '-' +
1276 s.substr(4, 2) + '-' +
1277 s.substr(6, 5) + ':' +
1278 s.substr(11, 2) + ':' +
1279 s.substr(13));
1280 var utc = new Date(t);
1281
1282 // Convert from UTC to local time
1283 return new Date(utc.getTime() - utc.getTimezoneOffset() * 60000);
1284 }
1285
1286
1287 function AddJobField(target, description, field)
1288 {
1289 if (!(typeof field === 'undefined')) {
1290 target.append($('<p>')
1291 .text(description)
1292 .append($('<strong>').text(field)));
1293 }
1294 }
1295
1296
1297 function AddJobDateField(target, description, field)
1298 {
1299 if (!(typeof field === 'undefined')) {
1300 target.append($('<p>')
1301 .text(description)
1302 .append($('<strong>').text(ParseJobTime(field))));
1303 }
1304 }
1305
1306
1307 $('#jobs').live('pagebeforeshow', function() {
1308 $.ajax({
1309 url: '../jobs?expand',
1310 dataType: 'json',
1311 async: false,
1312 cache: false,
1313 success: function(jobs) {
1314 var target = $('#all-jobs');
1315 $('li', target).remove();
1316
1317 var running = $('<li>')
1318 .attr('data-role', 'list-divider')
1319 .text('Currently running');
1320
1321 var pending = $('<li>')
1322 .attr('data-role', 'list-divider')
1323 .text('Pending jobs');
1324
1325 var inactive = $('<li>')
1326 .attr('data-role', 'list-divider')
1327 .text('Inactive jobs');
1328
1329 target.append(running);
1330 target.append(pending);
1331 target.append(inactive);
1332
1333 jobs.map(function(job) {
1334 var li = $('<li>');
1335 var item = $('<a>');
1336 li.append(item);
1337 item.attr('href', '#job?uuid=' + job.ID);
1338 item.append($('<h1>').text(job.Type));
1339 item.append($('<span>').addClass('ui-li-count').text(job.State));
1340 AddJobField(item, 'ID: ', job.ID);
1341 AddJobField(item, 'Local AET: ', job.Content.LocalAet);
1342 AddJobField(item, 'Remote AET: ', job.Content.RemoteAet);
1343 AddJobDateField(item, 'Creation time: ', job.CreationTime);
1344 AddJobDateField(item, 'Completion time: ', job.CompletionTime);
1345 AddJobDateField(item, 'ETA: ', job.EstimatedTimeOfArrival);
1346
1347 if (job.State == 'Running' ||
1348 job.State == 'Pending' ||
1349 job.State == 'Paused') {
1350 AddJobField(item, 'Priority: ', job.Priority);
1351 AddJobField(item, 'Progress: ', job.Progress);
1352 }
1353
1354 if (job.State == 'Running') {
1355 li.insertAfter(running);
1356 } else if (job.State == 'Pending' ||
1357 job.State == 'Paused') {
1358 li.insertAfter(pending);
1359 } else {
1360 li.insertAfter(inactive);
1361 }
1362 });
1363
1364 target.listview('refresh');
1365 }
1366 });
1367 });
1368
1369
1370 $('#job').live('pagebeforeshow', function() {
1371 if ($.mobile.pageData) {
1372 var pageData = DeepCopy($.mobile.pageData);
1373
1374 $.ajax({
1375 url: '../jobs/' + pageData.uuid,
1376 dataType: 'json',
1377 async: false,
1378 cache: false,
1379 success: function(job) {
1380 var target = $('#job-info');
1381 $('li', target).remove();
1382
1383 target.append($('<li>')
1384 .attr('data-role', 'list-divider')
1385 .text('General information about the job'));
1386
1387 var block = $('<li>');
1388 for (var i in job) {
1389 if (i == 'CreationTime' ||
1390 i == 'CompletionTime' ||
1391 i == 'EstimatedTimeOfArrival') {
1392 AddJobDateField(block, i + ': ', job[i]);
1393 } else if (i != 'InternalContent' &&
1394 i != 'Content' &&
1395 i != 'Timestamp') {
1396 AddJobField(block, i + ': ', job[i]);
1397 }
1398 }
1399
1400 target.append(block);
1401
1402 target.append($('<li>')
1403 .attr('data-role', 'list-divider')
1404 .text('Detailed information'));
1405
1406 var block = $('<li>');
1407
1408 for (var item in job.Content) {
1409 var value = job.Content[item];
1410 if (typeof value !== 'string') {
1411 value = JSON.stringify(value);
1412 }
1413
1414 AddJobField(block, item + ': ', value);
1415 }
1416
1417 target.append(block);
1418
1419 target.listview('refresh');
1420
1421 $('#job-cancel').closest('.ui-btn').hide();
1422 $('#job-retry').closest('.ui-btn').hide();
1423 $('#job-resubmit').closest('.ui-btn').hide();
1424 $('#job-pause').closest('.ui-btn').hide();
1425 $('#job-resume').closest('.ui-btn').hide();
1426
1427 if (job.State == 'Running' ||
1428 job.State == 'Pending' ||
1429 job.State == 'Retry') {
1430 $('#job-cancel').closest('.ui-btn').show();
1431 $('#job-pause').closest('.ui-btn').show();
1432 }
1433 else if (job.State == 'Success') {
1434 }
1435 else if (job.State == 'Failure') {
1436 $('#job-resubmit').closest('.ui-btn').show();
1437 }
1438 else if (job.State == 'Paused') {
1439 $('#job-resume').closest('.ui-btn').show();
1440 }
1441 }
1442 });
1443 }
1444 });
1445
1446
1447
1448 function TriggerJobAction(action)
1449 {
1450 $.ajax({
1451 url: '../jobs/' + $.mobile.pageData.uuid + '/' + action,
1452 type: 'POST',
1453 async: false,
1454 cache: false,
1455 complete: function(s) {
1456 window.location.reload();
1457 }
1458 });
1459 }
1460
1461 $('#job-cancel').live('click', function() {
1462 TriggerJobAction('cancel');
1463 });
1464
1465 $('#job-resubmit').live('click', function() {
1466 TriggerJobAction('resubmit');
1467 });
1468
1469 $('#job-pause').live('click', function() {
1470 TriggerJobAction('pause');
1471 });
1472
1473 $('#job-resume').live('click', function() {
1474 TriggerJobAction('resume');
1475 });