Skip to content

Commit 1cd43bd

Browse files
authored
Inter-interface Navigation (#390)
* Make sure navigation through workflow interfaces is available * changes from updating claude and reviewing with '/static-review' * changes from updating claude and reviewing with '/static-review' * changes in response to copilot review * Let's try and make sure the latest code is deployed * Changes from review and discussion at standup * changes from /static-review * changes from /static-review * changes from /static-review * changes from /static-review * Button back to project management from manage collaborators * touched up * touched up * Add focus indicators for keyboard selections to new project management buttons * border control * Change this link to use the interface instead of the component
1 parent d91138d commit 1cd43bd

13 files changed

Lines changed: 357 additions & 91 deletions

File tree

.claude/settings.json

Lines changed: 0 additions & 18 deletions
This file was deleted.

.claude/statusline-command.sh

Lines changed: 0 additions & 51 deletions
This file was deleted.

about.html

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ <h2>TPEN 3.0</h2>
1818
It provides a user-friendly interface for transcribing, annotating, and analyzing texts, making it
1919
an invaluable tool for historians, archivists, and researchers.
2020
</p>
21+
<p>
22+
<a href="https://three.t-pen.org/about/">Learn more at the TPEN3 home site!</a>
23+
</p>
2124
</tpen-page>
2225
</body>
2326

components/annotorious-annotator/line-parser.js

Lines changed: 45 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ class AnnotoriousAnnotator extends HTMLElement {
6969

7070
// Initialize HTML after loading in a TPEN3 Project
7171
render() {
72-
if (!CheckPermissions.checkAllAccess("line", "selector")) {
72+
if (!CheckPermissions.checkAllAccess("LINE", "SELECTOR")) {
7373
this.shadowRoot.innerHTML = "You do not have the proper project permissions to use this interface."
7474
return
7575
}
@@ -227,6 +227,7 @@ class AnnotoriousAnnotator extends HTMLElement {
227227
}
228228
#autoParseBtn {
229229
position: absolute;
230+
display: none;
230231
top: 10px;
231232
right: 10px;
232233
background-color: var(--primary-color);
@@ -235,10 +236,39 @@ class AnnotoriousAnnotator extends HTMLElement {
235236
border-radius: 5px;
236237
cursor: pointer;
237238
transition: background-color 0.3s;
238-
z-index: 10;
239+
z-index: 9;
240+
}
241+
#autoParseBtn:hover,
242+
#autoParseBtn:focus-visible {
243+
background-color: var(--primary-light);
244+
outline: 2px solid var(--primary-color);
245+
outline-offset: 2px;
246+
}
247+
#projectManagementBtn {
248+
position: absolute;
249+
display: none;
250+
bottom: 10px;
251+
left: 5px;
252+
background-color: var(--primary-color);
253+
padding: 10px 20px;
254+
color: var(--white);
255+
border-radius: 5px;
256+
cursor: pointer;
257+
transition: background-color 0.3s;
258+
z-index: 9;
259+
border: none;
239260
}
240-
#autoParseBtn:hover {
261+
#projectManagementBtn:hover,
262+
#projectManagementBtn:focus-visible {
241263
background-color: var(--primary-light);
264+
outline: 2px solid var(--primary-color);
265+
outline-offset: 2px;
266+
}
267+
#projectManagementBtn span {
268+
position: relative;
269+
left: -10px;
270+
display: inline-block;
271+
transform: rotate(180deg);
242272
}
243273
</style>
244274
<div>
@@ -277,7 +307,8 @@ class AnnotoriousAnnotator extends HTMLElement {
277307
<a id="createColumnsBtn" href="#">Manage Columns</a>
278308
<input id="saveBtn" type="button" value="Save Annotations"/>
279309
</div>
280-
<button id="autoParseBtn">Auto Parse</button>
310+
<button type="button" id="autoParseBtn">Auto Parse</button>
311+
<button type="button" id="projectManagementBtn"><span aria-hidden="true">↪</span> Go to Project Management</button>
281312
<div id="annotator-container"> Loading Annotorious and getting the TPEN3 Page information... </div>
282313
<div id="ruler"></div>
283314
<span id="sampleRuler"></span>
@@ -348,6 +379,7 @@ class AnnotoriousAnnotator extends HTMLElement {
348379
const addLinesBtn = this.shadowRoot.getElementById("addLinesBtn")
349380
const mergeLinesBtn = this.shadowRoot.getElementById("mergeLinesBtn")
350381
const drag = this.shadowRoot.querySelectorAll(".dragMe")
382+
351383
drag.forEach(elem => elem.addEventListener("mousedown", (e) => this.dragging(e)))
352384
addLinesBtn.addEventListener("click", (e) => this.toggleAddLines(e))
353385
mergeLinesBtn.addEventListener("click", (e) => this.toggleMergeLines(e))
@@ -356,7 +388,7 @@ class AnnotoriousAnnotator extends HTMLElement {
356388
eraseTool.addEventListener("change", (e) => this.toggleErasingMode(e))
357389
seeTool.addEventListener("change", (e) => this.toggleAnnotationVisibility(e))
358390
createColumnsBtn.addEventListener("click", () =>
359-
window.location.href = `../../components/create-column/?projectID=${TPEN.activeProject._id}&pageID=${this.#annotationPageID}`
391+
window.location.href = `/manage-columns?projectID=${TPEN.activeProject._id}&pageID=${this.#annotationPageID}`
360392
)
361393
saveButton.addEventListener("click", (e) => {
362394
this.#annotoriousInstance.cancelSelected()
@@ -589,7 +621,7 @@ class AnnotoriousAnnotator extends HTMLElement {
589621
}
590622
})
591623
// Link to transcribe if they have view permissions for it
592-
if(CheckPermissions.checkViewAccess("line", "text")) {
624+
if (CheckPermissions.checkViewAccess("LINE", "TEXT") || CheckPermissions.checkEditAccess("LINE", "TEXT")) {
593625
let parsingRedirectButton = new OpenSeadragon.Button({
594626
tooltip: "Go Transcribe",
595627
srcRest: "../interfaces/annotator/images/transcribe.png",
@@ -598,7 +630,7 @@ class AnnotoriousAnnotator extends HTMLElement {
598630
srcDown: "../interfaces/annotator/images/transcribe.png",
599631
onClick: (e) => {
600632
if (this.#resolvedAnnotationPage?.$isDirty) {
601-
if (confirm("Stop line parsing and go transcribe? Unsaved changes will be lost."))
633+
if (confirm("Stop identifying lines and go transcribe? Unsaved changes will be lost."))
602634
location.href = `/transcribe?projectID=${TPEN.activeProject._id}&pageID=${this.#annotationPageID}`
603635
}
604636
else {
@@ -768,6 +800,12 @@ class AnnotoriousAnnotator extends HTMLElement {
768800
this.#annotoriousInstance.setAnnotations(allAnnotations, false)
769801
this.#annotoriousContainer.style.backgroundImage = "none"
770802
this.shadowRoot.getElementById("tools-container").style.display = "block"
803+
this.shadowRoot.querySelector("#autoParseBtn").style.display = "block"
804+
if (CheckPermissions.checkEditAccess("PROJECT")) {
805+
const manageProjectBtn = this.shadowRoot.querySelector("#projectManagementBtn")
806+
manageProjectBtn.style.display = "block"
807+
manageProjectBtn.addEventListener("click", (e) => document.location.href = `/project/manage?projectID=${TPEN.activeProject._id}`)
808+
}
771809
}
772810

773811
/**

components/leave-project/index.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ class LeaveProject extends HTMLElement {
6060
}
6161
this.shadowRoot.innerHTML = `
6262
<style>
63-
#leaveBtn {
63+
#leaveBtn, #noLeaveBtn {
6464
background-color: var(--primary-color);
6565
padding: 10px 20px;
6666
cursor: pointer;
@@ -86,14 +86,17 @@ class LeaveProject extends HTMLElement {
8686
longer appear as a collaborator and the project will not appear in your projects
8787
list. To restore access you will have to be invited into the project again.
8888
</p>
89-
<button id="leaveBtn">I Am Ready To Leave This Project</button>
89+
<button type="button" id="noLeaveBtn">I Am Not Ready To Leave!</button>
90+
<button type="button" id="leaveBtn">I Am Ready To Leave This Project</button>
9091
`
9192
this.attachEventListeners()
9293
}
9394

9495
attachEventListeners() {
9596
const leaveBtn = this.shadowRoot.getElementById("leaveBtn")
97+
const noLeaveBtn = this.shadowRoot.getElementById("noLeaveBtn")
9698
leaveBtn.addEventListener('click', (ev) => this.leaveProject())
99+
noLeaveBtn.addEventListener('click', (ev) => document.location.href = `/project?projectID=${TPEN.activeProject._id}`)
97100
}
98101

99102
leaveProject() {

components/manage-role/index.js

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,32 @@ class ManageRole extends HTMLElement {
245245
width: 60%;
246246
}
247247
}
248+
249+
#projectManagementBtn {
250+
position: absolute;
251+
display: none;
252+
background-color: var(--primary-color);
253+
padding: 10px 20px;
254+
color: var(--white);
255+
border-radius: 5px;
256+
cursor: pointer;
257+
transition: background-color 0.3s;
258+
border: none;
259+
}
260+
261+
#projectManagementBtn:hover,
262+
#projectManagementBtn:focus-visible {
263+
background-color: var(--primary-light);
264+
outline: 2px solid var(--primary-color);
265+
outline-offset: 2px;
266+
}
267+
268+
#projectManagementBtn span {
269+
position: relative;
270+
left: -10px;
271+
display: inline-block;
272+
transform: rotate(180deg);
273+
}
248274
</style>
249275
<h3>Edit Roles & Permissions</h3>
250276
<div class="xyz">
@@ -352,13 +378,19 @@ class ManageRole extends HTMLElement {
352378
</div>
353379
</div>
354380
</div>
381+
<button type="button" id="projectManagementBtn"><span aria-hidden="true">↪</span> Go to Project Management</button>
355382
`
356383

357384
this.shadowRoot.getElementById("add-permissions").addEventListener('click', () => this.addPermissions(group))
358385
this.shadowRoot.getElementById("resetPermissions").addEventListener('click', () => this.resetPermissions())
359386
this.shadowRoot.getElementById("edit-role-name").addEventListener('click', () => this.editRoleName())
360387
this.shadowRoot.getElementById("save-role").addEventListener('click', () => this.addRole(group))
361388
this.shadowRoot.getElementById("update-role").addEventListener('click', () => this.updateRole(group))
389+
if (CheckPermissions.checkEditAccess("PROJECT")) {
390+
const manageBtn = this.shadowRoot.getElementById("projectManagementBtn")
391+
manageBtn.style.display = "block"
392+
manageBtn.addEventListener('click', () => document.location.href = `/project/manage?projectID=${TPEN.activeProject._id}`)
393+
}
362394

363395
const rolesList = this.shadowRoot.querySelector(".roles-list")
364396
Object.entries(group || {}).map(([key, value]) => ({ id: key, name: value }))

components/page-tool/index.js

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import TPEN from '../../api/TPEN.js'
12
import CheckPermissions from "../check-permissions/checkPermissions.js"
23
import { onProjectReady } from "../../utilities/projectReady.js"
34

@@ -351,6 +352,10 @@ export default class PageTool extends HTMLElement {
351352
margin-bottom: 20px;
352353
}
353354
355+
.parsing-section {
356+
display: none;
357+
}
358+
354359
.tool-section-title {
355360
font-size: 0.95rem;
356361
font-weight: 700;
@@ -370,7 +375,13 @@ export default class PageTool extends HTMLElement {
370375
width: fit-content;
371376
}
372377
373-
.grayscale-btn, .invert-btn, .reset-btn {
378+
.lines-btn, .columns-btn {
379+
margin: 10px auto;
380+
display: none;
381+
width: fit-content;
382+
}
383+
384+
.grayscale-btn, .invert-btn, .reset-btn, .lines-btn, .columns-btn {
374385
min-width: 220px;
375386
padding: 10px 18px;
376387
border: 2px solid rgb(0, 90, 140);
@@ -382,8 +393,8 @@ export default class PageTool extends HTMLElement {
382393
transition: background-color 0.3s ease, color 0.3s ease, border-color 0.3s ease;
383394
}
384395
385-
.grayscale-btn:hover, .invert-btn:hover, .reset-btn:hover,
386-
.grayscale-btn:focus, .invert-btn:focus, .reset-btn:focus {
396+
.grayscale-btn:hover, .invert-btn:hover, .reset-btn:hover, .lines-btn:hover, .columns-btn:hover,
397+
.grayscale-btn:focus, .invert-btn:focus, .reset-btn:focus, .lines-btn:focus, .columns-btn:focus {
387398
background-color: rgb(0, 90, 140);
388399
color: white;
389400
}
@@ -442,9 +453,9 @@ export default class PageTool extends HTMLElement {
442453
<button class="drawer-close-btn" type="button" title="Close" aria-label="Close">×</button>
443454
</div>
444455
<div class="drawer-content">
445-
<button type="button" class="reset-btn">RESET TO DEFAULTS</button>
446456
<div class="tool-section">
447457
<h4 class="tool-section-title">IMAGE CONTROLS</h4>
458+
<button type="button" class="reset-btn">RESET TO DEFAULTS</button>
448459
<button type="button" class="grayscale-btn">GRAYSCALE</button>
449460
<button type="button" class="invert-btn">INVERT</button>
450461
<div class="tool-sliders">
@@ -456,6 +467,11 @@ export default class PageTool extends HTMLElement {
456467
<input type="range" class="brightness-slider" min="0" max="200" value="100">
457468
</div>
458469
</div>
470+
<div class="tool-section parsing-section">
471+
<h4 class="tool-section-title">LINES & COLUMNS</h4>
472+
<button type="button" class="lines-btn">IDENTIFY LINES</button>
473+
<button type="button" class="columns-btn">IDENTIFY COLUMNS</button>
474+
</div>
459475
</div>
460476
</div>
461477
`
@@ -465,6 +481,17 @@ export default class PageTool extends HTMLElement {
465481
this.shadowRoot.querySelector('.contrast-slider')?.addEventListener('input', (e) => this.setContrast(e))
466482
this.shadowRoot.querySelector('.brightness-slider')?.addEventListener('input', (e) => this.setBrightness(e))
467483
this.shadowRoot.querySelector('.reset-btn')?.addEventListener('click', () => this.resetFilters())
484+
if (CheckPermissions.checkEditAccess("LINE", "SELECTOR")) {
485+
const linesBtn = this.shadowRoot.querySelector('.lines-btn')
486+
const columnsBtn = this.shadowRoot.querySelector('.columns-btn')
487+
this.shadowRoot.querySelector('.parsing-section').style.display = "block"
488+
linesBtn.style.display = "block"
489+
columnsBtn.style.display = "block"
490+
linesBtn.addEventListener('click', () =>
491+
document.location.href = `/annotator?projectID=${TPEN.activeProject._id}&pageID=${TPEN.screen.pageInQuery}`)
492+
columnsBtn.addEventListener('click', () =>
493+
document.location.href = `/manage-columns?projectID=${TPEN.activeProject._id}&pageID=${TPEN.screen.pageInQuery}`)
494+
}
468495
}
469496
}
470497

components/projects/project-header.js

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ export default class ProjectHeader extends HTMLElement {
2222
@keyframes blink { 0% { opacity: 1; } 50% { opacity: 0.2; } 100% { opacity: 1; } }
2323
.title-placeholder { width: 7.2rem; height: 1.5em; background-color: #ccc; border-radius: 4px; animation: blink 1s infinite; }
2424
.canvas-label select { padding: 5px; border-radius: 5px; border: none; background-color: white; color: rgb(166, 65, 41); cursor: pointer; }
25+
.manage-project { display:none }
2526
`
2627
this.shadowRoot.appendChild(style)
2728
this.content = document.createElement('div')
@@ -91,9 +92,9 @@ export default class ProjectHeader extends HTMLElement {
9192
<tpen-column-selector></tpen-column-selector>
9293
<div class="line-indicator">Line indicator</div>
9394
<div class="control-buttons">
94-
<a class="nav-icon" href="/index"><img draggable="false" src="../../assets/icons/home.png" alt="Home"></a>
95-
<a class="nav-icon" href="/project/manage?projectID=${TPEN.screen.projectInQuery}"><img draggable="false" src="../../assets/icons/contact.png" alt="Manage Project"></a>
96-
<a class="nav-icon" href="/profile"><img draggable="false" src="../../assets/icons/profile.png" alt="Profile"></a>
95+
<a title="Home" class="nav-icon" href="/index"><img draggable="false" src="../../assets/icons/home.png" alt="Home"></a>
96+
<a title="Manage Project" class="nav-icon manage-project"><img draggable="false" src="../../assets/icons/contact.png" alt="Manage Project"></a>
97+
<a title="My Profile" class="nav-icon" href="/profile"><img draggable="false" src="../../assets/icons/profile.png" alt="Profile"></a>
9798
</div>
9899
</nav>
99100
`
@@ -111,6 +112,11 @@ export default class ProjectHeader extends HTMLElement {
111112
location.href = url.toString()
112113
return
113114
}
115+
if (CheckPermissions.checkEditAccess("PROJECT")) {
116+
const projectManagementBtn = this.shadowRoot.querySelector('.manage-project')
117+
projectManagementBtn.style.display = "inline-block"
118+
projectManagementBtn.href = `/project/manage?projectID=${TPEN.activeProject._id}`
119+
}
114120
const CanvasSelectOptions = projectCanvasLabels.map((canvasLabel, index) => {
115121
const option = document.createElement('option')
116122
const canvasId = projectCanvases[index]

0 commit comments

Comments
 (0)