Skip to content

Commit 85c5011

Browse files
committed
feat: implement localStorage management for results view
Signed-off-by: Christian Hartmann <chris-hartmann@gmx.de>
1 parent cb0fb9f commit 85c5011

2 files changed

Lines changed: 110 additions & 2 deletions

File tree

src/Forms.vue

Lines changed: 61 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,53 @@ export default {
351351
loading.value = false
352352
}
353353
354+
/**
355+
* Clean up stale localStorage entries for forms that are no longer available.
356+
* Removes localStorage keys matching the pattern `nextcloud_forms_*_activeResponseView`
357+
* where the form hash no longer exists in the current forms list.
358+
*/
359+
const cleanupStaleLocalStorageEntries = () => {
360+
try {
361+
// Get all current form hashes
362+
const currentFormHashes = new Set(
363+
[...forms.value, ...allSharedForms.value].map(
364+
(form) => form.hash,
365+
),
366+
)
367+
368+
// Iterate through all localStorage keys
369+
const keysToRemove = []
370+
for (let i = 0; i < localStorage.length; i++) {
371+
const key = localStorage.key(i)
372+
if (
373+
key
374+
&& key.startsWith('nextcloud_forms_')
375+
&& key.endsWith('_activeResponseView')
376+
) {
377+
// Extract hash from key: nextcloud_forms_<hash>_activeResponseView
378+
const hash = key.substring(
379+
'nextcloud_forms_'.length,
380+
key.length - '_activeResponseView'.length,
381+
)
382+
// If form hash is not in current forms, mark for removal
383+
if (!currentFormHashes.has(hash)) {
384+
keysToRemove.push(key)
385+
}
386+
}
387+
}
388+
389+
// Remove stale entries
390+
keysToRemove.forEach((key) => {
391+
localStorage.removeItem(key)
392+
logger.debug(`Removed stale localStorage entry: ${key}`)
393+
})
394+
} catch (err) {
395+
logger.debug('Error cleaning up stale localStorage entries', {
396+
error: err,
397+
})
398+
}
399+
}
400+
354401
/**
355402
* Fetch a partial form by its hash after initial load completes.
356403
*
@@ -447,6 +494,17 @@ export default {
447494
forms.value.splice(formIndex, 1)
448495
deletedFormHash.value = deletedHash
449496
497+
// Remove localStorage entry for this form's active response view
498+
try {
499+
localStorage.removeItem(
500+
`nextcloud_forms_${deletedHash}_activeResponseView`,
501+
)
502+
} catch (err) {
503+
logger.debug('Error removing localStorage entry for deleted form', {
504+
error: err,
505+
})
506+
}
507+
450508
if (deletedHash === routeHash.value && route.name !== 'root') {
451509
// Navigate to root without triggering route guards
452510
router.replace({ name: 'root' })
@@ -477,8 +535,9 @@ export default {
477535
}
478536
}
479537
480-
onMounted(() => {
481-
loadForms()
538+
onMounted(async () => {
539+
await loadForms()
540+
cleanupStaleLocalStorageEntries()
482541
subscribe('forms:last-updated:set', onLastUpdatedByEventBus)
483542
subscribe('forms:ownership-transfered', onDeleteForm)
484543
})

src/views/Results.vue

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,7 @@ export default {
498498
// Reload results when form changes
499499
async hash() {
500500
await this.fetchFullForm(this.form.id)
501+
this.loadActiveResponseViewFromLocalStorage()
501502
this.loadFormResults()
502503
SetWindowTitle(this.formTitle)
503504
},
@@ -521,15 +522,63 @@ export default {
521522
})
522523
this.loadFormResults()
523524
}, INPUT_DEBOUNCE_MS),
525+
526+
// Persist active response view to localStorage when it changes
527+
activeResponseView(newView) {
528+
this.saveActiveResponseViewToLocalStorage(newView.id)
529+
},
524530
},
525531
526532
async beforeMount() {
527533
await this.fetchFullForm(this.form.id)
534+
this.loadActiveResponseViewFromLocalStorage()
528535
this.loadFormResults()
529536
SetWindowTitle(this.formTitle)
530537
},
531538
532539
methods: {
540+
/**
541+
* Load the active response view preference from localStorage for the current form.
542+
* Applies stored value if available and otherwise resets to default (summary)
543+
*/
544+
loadActiveResponseViewFromLocalStorage() {
545+
try {
546+
const storedViewId = localStorage.getItem(
547+
`nextcloud_forms_${this.form.hash}_activeResponseView`,
548+
)
549+
if (storedViewId) {
550+
const view = responseViews.find((v) => v.id === storedViewId)
551+
if (view) {
552+
this.activeResponseView = view
553+
}
554+
} else {
555+
this.activeResponseView = responseViews[0]
556+
}
557+
} catch (err) {
558+
logger.debug('Error loading activeResponseView from localStorage', {
559+
error: err,
560+
})
561+
}
562+
},
563+
564+
/**
565+
* Save the active response view preference to localStorage for the current form.
566+
*
567+
* @param {string} viewId - The ID of the view ('summary' or 'responses')
568+
*/
569+
saveActiveResponseViewToLocalStorage(viewId) {
570+
try {
571+
localStorage.setItem(
572+
`nextcloud_forms_${this.form.hash}_activeResponseView`,
573+
viewId,
574+
)
575+
} catch (err) {
576+
logger.debug('Error saving activeResponseView to localStorage', {
577+
error: err,
578+
})
579+
}
580+
},
581+
533582
async onUnlinkFile() {
534583
await axios.patch(
535584
generateOcsUrl('apps/forms/api/v3/forms/{formId}', {

0 commit comments

Comments
 (0)