Skip to content

Commit ce34d5b

Browse files
Copilotcubap
andauthored
Fix blank canvas on pages without line annotations and add user guidance (#371)
* Initial plan * Fix blank page when loading pages with no lines Handle pages without lines in updateTranscriptionImages by still loading and displaying the canvas even when there are no line annotations. Shows the full page image instead of returning early. Co-authored-by: cubap <1119165+cubap@users.noreply.github.com> * Add dismissible modal for pages without lines Shows an alert when a page has no line annotations with a link to the annotation interface where users can manually define lines. The alert is dismissible by clicking the "Got it" button. Co-authored-by: cubap <1119165+cubap@users.noreply.github.com> * Improve alert security and encapsulation - Encode URL parameters to prevent injection vulnerabilities - Replace innerHTML with DOM element creation for better security - Add CSS via style element instead of inline styles - Add fallback for potential future public API on AlertContainer Co-authored-by: cubap <1119165+cubap@users.noreply.github.com> * fix links and build alert cleanly * Update index.js --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: cubap <1119165+cubap@users.noreply.github.com> Co-authored-by: cubap <cubap@slu.edu>
1 parent b51a33f commit ce34d5b

2 files changed

Lines changed: 65 additions & 1 deletion

File tree

components/gui/alert/AlertContainer.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,10 @@ class AlertContainer extends HTMLElement {
8686
transition: all 0.3s ease-in-out;
8787
font-size: 14pt;
8888
}
89+
tpen-alert a {
90+
color: var(--primary-color);
91+
text-decoration: underline;
92+
}
8993
.alert-area tpen-alert {
9094
top: 0px;
9195
right: 0px;

interfaces/transcription/index.js

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import '../../components/line-image/index.js'
77
import CheckPermissions from "../../components/check-permissions/checkPermissions.js"
88
import { orderPageItemsByColumns } from "../../utilities/columnOrdering.js"
99
import { renderPermissionError } from "../../utilities/renderPermissionError.js"
10+
import '../../components/gui/alert/AlertContainer.js'
1011
export default class TranscriptionInterface extends HTMLElement {
1112
#page
1213
#canvas
@@ -419,6 +420,49 @@ export default class TranscriptionInterface extends HTMLElement {
419420
})
420421
}
421422

423+
showNoLinesAlert() {
424+
const alertContainer = document.querySelector('tpen-alert-container')
425+
if (!alertContainer) return
426+
427+
const projectId = encodeURIComponent(TPEN.screen?.projectInQuery ?? '')
428+
const pageId = encodeURIComponent(TPEN.screen?.pageInQuery ?? '')
429+
const annotatorUrl = `/interfaces/annotator?projectID=${projectId}&pageID=${pageId}`
430+
431+
const alertElem = document.createElement('tpen-alert')
432+
alertElem.innerHTML = `
433+
<style>
434+
.no-lines-message p:first-child {
435+
margin-bottom: 1em;
436+
}
437+
.alert-link {
438+
color: var(--primary-color, #4fc3f7);
439+
text-decoration: underline;
440+
}
441+
</style>
442+
<div class="no-lines-message">
443+
<p>This page has no line annotations defined.</p>
444+
<p>To add lines, visit the <a href="${annotatorUrl}" class="alert-link">column and line interface</a>.</p>
445+
</div>
446+
<div class="button-container">
447+
<button id="no-lines-ok">Got it</button>
448+
</div>
449+
`
450+
451+
alertElem.querySelector('#no-lines-ok').addEventListener('click', () => {
452+
alertElem.dismiss()
453+
})
454+
455+
if (typeof alertContainer.addCustomAlert === 'function') {
456+
alertContainer.addCustomAlert(alertElem)
457+
} else {
458+
const screenLockingSection = alertContainer.shadowRoot.querySelector('.alert-area')
459+
if (screenLockingSection) {
460+
screenLockingSection.appendChild(alertElem)
461+
alertElem.show()
462+
}
463+
}
464+
}
465+
422466
updateLines() {
423467
if (TPEN.activeLineIndex < 0 || !this.#page) return
424468
const topImage = this.shadowRoot.querySelector('#topImage')
@@ -518,7 +562,23 @@ export default class TranscriptionInterface extends HTMLElement {
518562
const { orderedItems, columnsInPage } = orderPageItemsByColumns(projectPage, this.#page)
519563
this.#page.items = orderedItems
520564
let thisLine = this.#page.items?.[0]
521-
if (!thisLine) return
565+
566+
// Handle pages with no lines - still load the canvas
567+
if (!thisLine) {
568+
// Get canvas from page target even when there are no lines
569+
const { canvasID } = this.setCanvasAndSelector(null, this.#page)
570+
if (!canvasID) return
571+
const canvas = this.#canvas = await vault.get(canvasID, 'canvas')
572+
// Show full page when there are no lines
573+
const regionValue = `0,0,${canvas?.width ?? 'full'},${(canvas?.height && canvas?.height / 10) ?? 120}`
574+
topImage.canvas = canvasID
575+
bottomImage.canvas = canvas
576+
topImage.setAttribute('region', regionValue)
577+
// Show alert to inform user about missing lines
578+
this.showNoLinesAlert()
579+
return
580+
}
581+
522582
if (!(thisLine?.body)) thisLine = await vault.get(thisLine, 'annotation', true)
523583
const { canvasID, region } = this.setCanvasAndSelector(thisLine, this.#page)
524584
const canvas = this.#canvas = await vault.get(canvasID, 'canvas')

0 commit comments

Comments
 (0)