Mercurial > hg > orthanc
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> » '); | 353 $('.orthanc-name').html($('<a>') |
327 } | 354 .addClass('ui-link') |
328 } | 355 .attr('href', 'explorer.html') |
329 }); | 356 .text(s.Name) |
330 }); | 357 .append(' » ')); |
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 '&': '&', | |
695 '<': '<', | |
696 '>': '>', | |
697 '"': '"', | |
698 "'": ''', | |
699 '/': '/', | |
700 '`': '`', | |
701 '=': '=' | |
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 }); |