diff --git a/api/TPEN.js b/api/TPEN.js index 7e4bcd36..56373a16 100644 --- a/api/TPEN.js +++ b/api/TPEN.js @@ -61,6 +61,14 @@ class Tpen { eventDispatcher.on("tpen-user-loaded", ev => this.currentUser = ev.detail) eventDispatcher.on("tpen-project-loaded", ev => this.activeProject = ev.detail) + // Centralized token expiration UX: notify user and redirect to login + let expirationTimeout = null + eventDispatcher.on('token-expiration', () => { + if (expirationTimeout) return + eventDispatcher.dispatch('tpen-toast', { status: 'error', message: 'Your session has expired. Redirecting to login...' }) + expirationTimeout = setTimeout(() => this.login(), 4000) + }) + if (this.screen.projectInQuery) { try { import('./Project.js').then(module => { diff --git a/components/new-action.js b/components/new-action.js index a00c9d0a..21a4d0bb 100644 --- a/components/new-action.js +++ b/components/new-action.js @@ -94,7 +94,8 @@ class NewAction extends HTMLElement { } TPEN2ImportHandler = async () => { - const userToken = localStorage.getItem("userToken") + const userToken = TPEN.getAuthorization() + if (!userToken) return TPEN.login() let tokenDomain let isProdTPEN diff --git a/interfaces/manage-columns/index.js b/interfaces/manage-columns/index.js index c844853b..9b17766d 100644 --- a/interfaces/manage-columns/index.js +++ b/interfaces/manage-columns/index.js @@ -305,7 +305,11 @@ class TpenManageColumns extends HTMLElement { connectedCallback() { TPEN.attachAuthentication(this) - localStorage.removeItem('annotationsState') + if (!TPEN.screen.projectInQuery) { + this.showError("No project id provided") + return + } + localStorage.removeItem(`annotationsState:${TPEN.screen.projectInQuery}`) if (!TPEN.screen.pageInQuery) { this.showError("No page id provided") return @@ -403,7 +407,7 @@ class TpenManageColumns extends HTMLElement { })) }) this.totalIds = annotations.filter(anno => !assignedAnnotationIds.some(a => a.lineId === anno.lineId)).map(a => a.lineId) - localStorage.setItem('annotationsState', JSON.stringify({ + localStorage.setItem(`annotationsState:${TPEN.screen.projectInQuery}`, JSON.stringify({ remainingIDs: this.totalIds, selectedIDs: [] })) @@ -526,7 +530,7 @@ class TpenManageColumns extends HTMLElement { this.totalIds = this.cachedAnnotations .filter(anno => !assignedAnnotationIds.some(a => a.lineId === anno.lineId)) .map(a => a.lineId) - localStorage.setItem('annotationsState', JSON.stringify({ + localStorage.setItem(`annotationsState:${TPEN.screen.projectInQuery}`, JSON.stringify({ remainingIDs: this.totalIds, selectedIDs: [] })) @@ -927,7 +931,7 @@ class TpenManageColumns extends HTMLElement { } restoreAnnotationState() { - const saved = localStorage.getItem('annotationsState') + const saved = localStorage.getItem(`annotationsState:${TPEN.screen.projectInQuery}`) if (!saved) return const { selectedIDs = [] } = JSON.parse(saved) const boxes = Array.from(this.shadowRoot.querySelectorAll('.overlayBox')) @@ -1023,7 +1027,7 @@ class TpenManageColumns extends HTMLElement { const selectedIDs = this.selectedBoxes.map(b => b.dataset.lineId) const remainingIDs = this.totalIds.filter(id => !this.selectedBoxes.some(b => b.dataset.lineId === id)) try { - localStorage.setItem('annotationsState', JSON.stringify({ remainingIDs, selectedIDs })) + localStorage.setItem(`annotationsState:${TPEN.screen.projectInQuery}`, JSON.stringify({ remainingIDs, selectedIDs })) } catch (e) { // localStorage may be unavailable (e.g., private mode, quota exceeded) // Silent fail as this is just a convenience feature