Image annotations:
+
Image annotations:
{% for image in question.images.all %}
- Image {{ forloop.counter }}: {{image.image_annotations}}
+ Image {{ forloop.counter }}: {{image.image_annotations}}
{% endfor %}
diff --git a/rapids/views.py b/rapids/views.py
index 68ad52b7..fa77810f 100755
--- a/rapids/views.py
+++ b/rapids/views.py
@@ -1160,10 +1160,13 @@ def question_save_annotation(request, pk):
question_images = question.images.all()
- for n, annotation in enumerate(image_annotations):
+ for n, image in enumerate(question_images):
+ annotation = image_annotations[n]
if annotation != "undefined":
- question_images[n].image_annotations = annotation
- question_images[n].save()
+ image.image_annotations = annotation
+ else:
+ image.image_annotations = ""
+ image.save()
data = {"status": "success"}
return JsonResponse(data, status=200)
diff --git a/static/debug_toolbar/css/toolbar.css b/static/debug_toolbar/css/toolbar.css
index 6bbfd3d7..13fbbed0 100644
--- a/static/debug_toolbar/css/toolbar.css
+++ b/static/debug_toolbar/css/toolbar.css
@@ -198,7 +198,7 @@
#djDebug #djDebugToolbarHandle {
position: fixed;
- transform: rotate(-90deg);
+ transform: translateY(-100%) rotate(-90deg);
transform-origin: right bottom;
background-color: #fff;
border: 1px solid #111;
diff --git a/static/debug_toolbar/js/history.js b/static/debug_toolbar/js/history.js
index e20c8543..cc14b2e4 100644
--- a/static/debug_toolbar/js/history.js
+++ b/static/debug_toolbar/js/history.js
@@ -7,21 +7,30 @@ $$.on(djDebug, "click", ".switchHistory", function (event) {
const newStoreId = this.dataset.storeId;
const tbody = this.closest("tbody");
- tbody
- .querySelector(".djdt-highlighted")
- .classList.remove("djdt-highlighted");
+ const highlighted = tbody.querySelector(".djdt-highlighted");
+ if (highlighted) {
+ highlighted.classList.remove("djdt-highlighted");
+ }
this.closest("tr").classList.add("djdt-highlighted");
ajaxForm(this).then(function (data) {
djDebug.setAttribute("data-store-id", newStoreId);
- Object.keys(data).forEach(function (panelId) {
- const panel = document.getElementById(panelId);
- if (panel) {
- panel.outerHTML = data[panelId].content;
- document.getElementById("djdt-" + panelId).outerHTML =
- data[panelId].button;
- }
- });
+ // Check if response is empty, it could be due to an expired store_id.
+ if (Object.keys(data).length === 0) {
+ const container = document.getElementById("djdtHistoryRequests");
+ container.querySelector(
+ 'button[data-store-id="' + newStoreId + '"]'
+ ).innerHTML = "Switch [EXPIRED]";
+ } else {
+ Object.keys(data).forEach(function (panelId) {
+ const panel = document.getElementById(panelId);
+ if (panel) {
+ panel.outerHTML = data[panelId].content;
+ document.getElementById("djdt-" + panelId).outerHTML =
+ data[panelId].button;
+ }
+ });
+ }
});
});
@@ -29,12 +38,14 @@ $$.on(djDebug, "click", ".refreshHistory", function (event) {
event.preventDefault();
const container = document.getElementById("djdtHistoryRequests");
ajaxForm(this).then(function (data) {
+ // Remove existing rows first then re-populate with new data
+ container
+ .querySelectorAll("tr[data-store-id]")
+ .forEach(function (node) {
+ node.remove();
+ });
data.requests.forEach(function (request) {
- if (
- !container.querySelector('[data-store-id="' + request.id + '"]')
- ) {
- container.innerHTML = request.content + container.innerHTML;
- }
+ container.innerHTML = request.content + container.innerHTML;
});
});
});
diff --git a/static/debug_toolbar/js/timer.js b/static/debug_toolbar/js/timer.js
index 1d4ac19d..70d3fe5a 100644
--- a/static/debug_toolbar/js/timer.js
+++ b/static/debug_toolbar/js/timer.js
@@ -1,59 +1,75 @@
-const timingOffset = performance.timing.navigationStart,
- timingEnd = performance.timing.loadEventEnd,
- totalTime = timingEnd - timingOffset;
-function getLeft(stat) {
- return ((performance.timing[stat] - timingOffset) / totalTime) * 100.0;
-}
-function getCSSWidth(stat, endStat) {
- let width =
- ((performance.timing[endStat] - performance.timing[stat]) / totalTime) *
- 100.0;
- // Calculate relative percent (same as sql panel logic)
- width = (100.0 * width) / (100.0 - getLeft(stat));
- return width < 1 ? "2px" : width + "%";
-}
-function addRow(tbody, stat, endStat) {
- const row = document.createElement("tr");
- if (endStat) {
- // Render a start through end bar
- row.innerHTML =
- "
" +
- stat.replace("Start", "") +
- " | " +
- '
| ' +
- "
" +
- (performance.timing[stat] - timingOffset) +
- " (+" +
- (performance.timing[endStat] - performance.timing[stat]) +
- ") | ";
- row.querySelector("rect").setAttribute(
- "width",
- getCSSWidth(stat, endStat)
- );
- } else {
- // Render a point in time
- row.innerHTML =
- "
" +
- stat +
- " | " +
- '
| ' +
- "
" +
- (performance.timing[stat] - timingOffset) +
- " | ";
- row.querySelector("rect").setAttribute("width", 2);
+import { $$ } from "./utils.js";
+
+function insertBrowserTiming() {
+ console.log(["inserted"]);
+ const timingOffset = performance.timing.navigationStart,
+ timingEnd = performance.timing.loadEventEnd,
+ totalTime = timingEnd - timingOffset;
+ function getLeft(stat) {
+ return ((performance.timing[stat] - timingOffset) / totalTime) * 100.0;
+ }
+ function getCSSWidth(stat, endStat) {
+ let width =
+ ((performance.timing[endStat] - performance.timing[stat]) /
+ totalTime) *
+ 100.0;
+ // Calculate relative percent (same as sql panel logic)
+ width = (100.0 * width) / (100.0 - getLeft(stat));
+ return width < 1 ? "2px" : width + "%";
+ }
+ function addRow(tbody, stat, endStat) {
+ const row = document.createElement("tr");
+ if (endStat) {
+ // Render a start through end bar
+ row.innerHTML =
+ "
" +
+ stat.replace("Start", "") +
+ " | " +
+ '
| ' +
+ "
" +
+ (performance.timing[stat] - timingOffset) +
+ " (+" +
+ (performance.timing[endStat] - performance.timing[stat]) +
+ ") | ";
+ row.querySelector("rect").setAttribute(
+ "width",
+ getCSSWidth(stat, endStat)
+ );
+ } else {
+ // Render a point in time
+ row.innerHTML =
+ "
" +
+ stat +
+ " | " +
+ '
| ' +
+ "
" +
+ (performance.timing[stat] - timingOffset) +
+ " | ";
+ row.querySelector("rect").setAttribute("width", 2);
+ }
+ row.querySelector("rect").setAttribute("x", getLeft(stat));
+ tbody.appendChild(row);
+ }
+
+ const browserTiming = document.getElementById("djDebugBrowserTiming");
+ // Determine if the browser timing section has already been rendered.
+ if (browserTiming.classList.contains("djdt-hidden")) {
+ const tbody = document.getElementById("djDebugBrowserTimingTableBody");
+ // This is a reasonably complete and ordered set of timing periods (2 params) and events (1 param)
+ addRow(tbody, "domainLookupStart", "domainLookupEnd");
+ addRow(tbody, "connectStart", "connectEnd");
+ addRow(tbody, "requestStart", "responseEnd"); // There is no requestEnd
+ addRow(tbody, "responseStart", "responseEnd");
+ addRow(tbody, "domLoading", "domComplete"); // Spans the events below
+ addRow(tbody, "domInteractive");
+ addRow(tbody, "domContentLoadedEventStart", "domContentLoadedEventEnd");
+ addRow(tbody, "loadEventStart", "loadEventEnd");
+ browserTiming.classList.remove("djdt-hidden");
}
- row.querySelector("rect").setAttribute("x", getLeft(stat));
- tbody.appendChild(row);
}
-const tbody = document.getElementById("djDebugBrowserTimingTableBody");
-// This is a reasonably complete and ordered set of timing periods (2 params) and events (1 param)
-addRow(tbody, "domainLookupStart", "domainLookupEnd");
-addRow(tbody, "connectStart", "connectEnd");
-addRow(tbody, "requestStart", "responseEnd"); // There is no requestEnd
-addRow(tbody, "responseStart", "responseEnd");
-addRow(tbody, "domLoading", "domComplete"); // Spans the events below
-addRow(tbody, "domInteractive");
-addRow(tbody, "domContentLoadedEventStart", "domContentLoadedEventEnd");
-addRow(tbody, "loadEventStart", "loadEventEnd");
-document.getElementById("djDebugBrowserTiming").classList.remove("djdt-hidden");
+const djDebug = document.getElementById("djDebug");
+// Insert the browser timing now since it's possible for this
+// script to miss the initial panel load event.
+insertBrowserTiming();
+$$.onPanelRender(djDebug, "TimerPanel", insertBrowserTiming);
diff --git a/static/debug_toolbar/js/toolbar.js b/static/debug_toolbar/js/toolbar.js
index d739cbdb..c17ee3ea 100644
--- a/static/debug_toolbar/js/toolbar.js
+++ b/static/debug_toolbar/js/toolbar.js
@@ -20,7 +20,8 @@ const djdt = {
if (!this.className) {
return;
}
- const current = document.getElementById(this.className);
+ const panelId = this.className;
+ const current = document.getElementById(panelId);
if ($$.visible(current)) {
djdt.hide_panels();
} else {
@@ -39,13 +40,24 @@ const djdt = {
window.location
);
url.searchParams.append("store_id", store_id);
- url.searchParams.append("panel_id", this.className);
+ url.searchParams.append("panel_id", panelId);
ajax(url).then(function (data) {
inner.previousElementSibling.remove(); // Remove AJAX loader
inner.innerHTML = data.content;
$$.executeScripts(data.scripts);
$$.applyStyles(inner);
+ djDebug.dispatchEvent(
+ new CustomEvent("djdt.panel.render", {
+ detail: { panelId: panelId },
+ })
+ );
});
+ } else {
+ djDebug.dispatchEvent(
+ new CustomEvent("djdt.panel.render", {
+ detail: { panelId: panelId },
+ })
+ );
}
}
}
@@ -178,6 +190,7 @@ const djdt = {
requestAnimationFrame(function () {
djdt.handleDragged = false;
});
+ djdt.ensure_handle_visibility();
}
});
const show =
@@ -198,6 +211,15 @@ const djdt = {
e.classList.remove("djdt-active");
});
},
+ ensure_handle_visibility() {
+ const handle = document.getElementById("djDebugToolbarHandle");
+ // set handle position
+ const handleTop = Math.min(
+ localStorage.getItem("djdt.top") || 0,
+ window.innerHeight - handle.offsetWidth
+ );
+ handle.style.top = handleTop + "px";
+ },
hide_toolbar() {
djdt.hide_panels();
@@ -205,16 +227,8 @@ const djdt = {
const handle = document.getElementById("djDebugToolbarHandle");
$$.show(handle);
- // set handle position
- let handleTop = localStorage.getItem("djdt.top");
- if (handleTop) {
- handleTop = Math.min(
- handleTop,
- window.innerHeight - handle.offsetHeight
- );
- handle.style.top = handleTop + "px";
- }
-
+ djdt.ensure_handle_visibility();
+ window.addEventListener("resize", djdt.ensure_handle_visibility);
document.removeEventListener("keydown", onKeyDown);
localStorage.setItem("djdt.show", "false");
@@ -237,6 +251,7 @@ const djdt = {
$$.hide(document.getElementById("djDebugToolbarHandle"));
$$.show(document.getElementById("djDebugToolbar"));
localStorage.setItem("djdt.show", "true");
+ window.removeEventListener("resize", djdt.ensure_handle_visibility);
},
cookie: {
get(key) {
diff --git a/static/debug_toolbar/js/utils.js b/static/debug_toolbar/js/utils.js
index 4683b319..da810aad 100644
--- a/static/debug_toolbar/js/utils.js
+++ b/static/debug_toolbar/js/utils.js
@@ -7,6 +7,21 @@ const $$ = {
}
});
},
+ onPanelRender(root, panelId, fn) {
+ /*
+ This is a helper function to attach a handler for a `djdt.panel.render`
+ event of a specific panel.
+
+ root: The container element that the listener should be attached to.
+ panelId: The Id of the panel.
+ fn: A function to execute when the event is triggered.
+ */
+ root.addEventListener("djdt.panel.render", function (event) {
+ if (event.detail.panelId === panelId) {
+ fn.call(event);
+ }
+ });
+ },
show(element) {
element.classList.remove("djdt-hidden");
},
diff --git a/static/js/anatomy.js b/static/js/anatomy.js
index b0b766d2..8bd1d64d 100644
--- a/static/js/anatomy.js
+++ b/static/js/anatomy.js
@@ -178,7 +178,7 @@ function loadDicomViewer(images_to_load, annotations_to_load) {
console.log(images);
let annotations = single_dicom.dataset.annotations;
- if (annotations != undefined) {
+ if (annotations_to_load != undefined) {
annotations = annotations_to_load;
} else if (annotations && annotations.indexOf(",") > 0) {
annotations = JSON.parse(annotations);
diff --git a/static/js/dicomViewer.js b/static/js/dicomViewer.js
index f964ec0f..8183c2f0 100644
--- a/static/js/dicomViewer.js
+++ b/static/js/dicomViewer.js
@@ -11,6 +11,7 @@ cornerstoneWADOImageLoader.external.cornerstone = cornerstone;
cornerstoneTools.init();
+let tool_state = {};
export function loadCornerstone(main_element, db, images, annotations_to_load, load_as_stack = false) {
@@ -180,15 +181,14 @@ export function loadCornerstone(main_element, db, images, annotations_to_load, l
function loadAnnotation(imageId, annotation) {
- console.log("loadAnnotations", imageId, annotations);
+ console.log("loadAnnotations", imageId, annotation);
const toolStateManager = cornerstoneTools.globalImageIdSpecificToolStateManager;
if (annotation == undefined || annotation.length < 1 || annotation == [undefined]) { return }
- console.log(annotation);
+ console.log("1234", annotation);
let tool_state_no_id = JSON.parse(annotation);
- let tool_state = {};
tool_state[imageId] = tool_state_no_id;
toolStateManager.restoreToolState(tool_state);