feat(astrolabe): enable multi-select for document types and refactor PDF viewer

This commit includes two improvements to the Astroglobe semantic search UI:

1. **Multi-select Document Types** (App.vue):
   - Changed NcCheckboxRadioSwitch binding from v-model to :checked/:update:checked
   - Implemented toggleDocType() method to manually manage selectedDocTypes array
   - Fixes issue where only single document type could be selected at a time
   - Users can now filter search results by multiple doc types simultaneously

2. **PDF Viewer Reactive Rendering** (PDFViewer.vue):
   - Refactored canvas rendering to use Vue reactive watcher pattern
   - Added watcher on 'loading' state that triggers rendering when canvas available
   - Removed imperative renderPage() call from loadPDF() method
   - Inspired by files_pdfviewer's promise/event-based initialization approach
   - Improves alignment with Vue's reactive data flow

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
Chris Coutinho
2025-12-15 23:09:09 +01:00
parent 44391d3d1d
commit af9a55cebd
2 changed files with 27 additions and 14 deletions
+14 -3
View File
@@ -93,9 +93,9 @@
<NcCheckboxRadioSwitch
v-for="docType in docTypeOptions"
:key="docType.id"
:checked.sync="selectedDocTypes"
:value="docType.id"
type="checkbox">
:checked="selectedDocTypes.includes(docType.id)"
type="checkbox"
@update:checked="toggleDocType(docType.id, $event)">
{{ docType.label }}
</NcCheckboxRadioSwitch>
</div>
@@ -469,6 +469,17 @@ export default {
},
},
methods: {
toggleDocType(docTypeId, checked) {
if (checked && !this.selectedDocTypes.includes(docTypeId)) {
this.selectedDocTypes.push(docTypeId)
} else if (!checked) {
const index = this.selectedDocTypes.indexOf(docTypeId)
if (index > -1) {
this.selectedDocTypes.splice(index, 1)
}
}
},
async performSearch() {
const queryText = this.query.trim()
if (!queryText) {
+13 -11
View File
@@ -86,6 +86,17 @@ export default {
// Reload PDF if file path changes
this.loadPDF()
},
async loading(newLoading) {
// When loading completes, wait for canvas to be available and render
if (!newLoading && this.pdfDoc && !this.error) {
// Wait for Vue to update DOM
await this.$nextTick()
// Canvas should now be rendered (v-else condition)
if (this.$refs.canvas) {
await this.renderPage(this.pageNumber)
}
}
},
},
async mounted() {
await this.loadPDF()
@@ -121,16 +132,8 @@ export default {
this.totalPages = this.pdfDoc.numPages
this.$emit('loaded', { totalPages: this.totalPages })
// Wait for canvas to be in DOM
await this.$nextTick()
// Canvas should be available now (mounted lifecycle guarantees it)
if (!this.$refs.canvas) {
throw new Error('Canvas element not available after mount')
}
// Render the requested page
await this.renderPage(this.pageNumber)
// Set loading to false - the watcher will handle rendering
this.loading = false
} catch (err) {
console.error('PDF load error:', err)
@@ -148,7 +151,6 @@ export default {
}
this.$emit('error', err)
} finally {
this.loading = false
}
},