Compare commits

..

2 Commits

Author SHA1 Message Date
Chris Coutinho 006a3d95d6 fix(astrolabe): address review feedback for Vue 3 bindings
- Change limit initialization from string '20' to number 20 in App.vue
- Update AdminSettings.vue NcTextField to use v-model instead of legacy
  :value/@update:value bindings
- Update AdminSettings.vue NcSelect components to use :model-value with
  computed getters and @update:model-value for proper object-to-id
  conversion (same pattern as App.vue)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-15 12:16:08 +01:00
Chris Coutinho cb4e8acd9f fix(astrolabe): update Vue component bindings for Vue 3 compatibility
The astrolabe app was using Vue 2 style bindings that don't work with
@nextcloud/vue 9.x and Vue 3:

- NcTextField: Changed from :value/@update:value to v-model
- NcSelect: Changed from v-model (with computed prop) to
  :model-value/@update:model-value

The legacy :value and @update:value props were being ignored because
@nextcloud/vue 9.x components use modelValue/update:modelValue internally.
This caused the search button to remain disabled and the algorithm
dropdown to be unresponsive.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-15 12:06:20 +01:00
2 changed files with 23 additions and 15 deletions
+6 -8
View File
@@ -48,19 +48,18 @@
<div class="mcp-search-card">
<div class="mcp-search-row">
<NcTextField
:value="query"
v-model="query"
:label="t('astrolabe', 'Search query')"
:placeholder="t('astrolabe', 'Enter your search query...')"
class="mcp-search-input"
@update:value="query = $event"
@keyup.enter="performSearch" />
<NcSelect
v-model="selectedAlgorithmOption"
:model-value="selectedAlgorithmOption"
:options="algorithmOptions"
:placeholder="t('astrolabe', 'Algorithm')"
class="mcp-algorithm-select"
@input="algorithm = $event ? $event.id : 'hybrid'" />
@update:model-value="algorithm = $event ? $event.id : 'hybrid'" />
<NcButton
type="primary"
@@ -105,11 +104,10 @@
<div class="mcp-option-group">
<label>{{ t('astrolabe', 'Result Limit') }}</label>
<NcTextField
:value="limit"
v-model="limit"
type="number"
:min="1"
:max="100"
@update:value="limit = Number($event)" />
:max="100" />
</div>
<div class="mcp-option-group">
@@ -445,7 +443,7 @@ export default {
algorithm: 'hybrid',
showAdvanced: false,
selectedDocTypes: [],
limit: '20',
limit: 20,
scoreThreshold: 0,
loading: false,
error: null,
@@ -152,19 +152,21 @@
<div class="settings-form">
<NcSelect
v-model="settings.algorithm"
:model-value="selectedAlgorithmOption"
:options="algorithmOptions"
:label="t('astrolabe', 'Search Algorithm')"
class="form-field" />
class="form-field"
@update:model-value="settings.algorithm = $event ? $event.id : 'hybrid'" />
<p class="help-text">
{{ t('astrolabe', 'Hybrid combines semantic understanding with keyword matching. Semantic finds conceptually similar content. BM25 matches exact keywords.') }}
</p>
<NcSelect
v-model="settings.fusion"
:model-value="selectedFusionOption"
:options="fusionOptions"
:label="t('astrolabe', 'Fusion Method')"
class="form-field" />
class="form-field"
@update:model-value="settings.fusion = $event ? $event.id : 'rrf'" />
<p class="help-text">
{{ t('astrolabe', 'Only applies to hybrid search. RRF balances results well for most queries. DBSF may work better when keyword matches are over/under-weighted.') }}
</p>
@@ -184,14 +186,13 @@
</div>
<NcTextField
:value="settings.limit"
v-model="settings.limit"
:label="t('astrolabe', 'Maximum Results')"
type="number"
:min="5"
:max="100"
:step="5"
class="form-field"
@update:value="settings.limit = Number($event)" />
class="form-field" />
<p class="help-text">
{{ t('astrolabe', 'Maximum number of results to return per search query (5-100).') }}
</p>
@@ -276,6 +277,15 @@ const fusionOptions = computed(() => [
{ id: 'dbsf', label: t('astrolabe', 'DBSF - Distribution-Based Score Fusion') },
])
// Computed properties for NcSelect (converts between stored ID and option object)
const selectedAlgorithmOption = computed(() =>
algorithmOptions.value.find(opt => opt.id === settings.value.algorithm) || algorithmOptions.value[0],
)
const selectedFusionOption = computed(() =>
fusionOptions.value.find(opt => opt.id === settings.value.fusion) || fusionOptions.value[0],
)
// Methods
async function loadServerStatus() {
loading.value = true