Skip to content

Add controlled keywords to score set search filter options.#649

Open
EstelleDa wants to merge 3 commits intorelease-2026.2.1from
feature/estelle/693/addControlledKeywordsToSearchFilterOptions
Open

Add controlled keywords to score set search filter options.#649
EstelleDa wants to merge 3 commits intorelease-2026.2.1from
feature/estelle/693/addControlledKeywordsToSearchFilterOptions

Conversation

@EstelleDa
Copy link
Copy Markdown
Member

@EstelleDa EstelleDa requested a review from bencap April 10, 2026 07:48
Copy link
Copy Markdown
Collaborator

@bencap bencap left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for working on this Estelle. The main comment I have is about the behavior when a user selects a keyword whose value is present across keyword groups, such as 'Other'. We'll need some additional backend changes to fully remedy it.

@update:model-value="$emit('update:publicationDatabases', $event)"
/>
</MvCollapsible>
<MvCollapsible :open="false" title="Keyword">
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
<MvCollapsible :open="false" title="Keyword">
<MvCollapsible :open="false" title="Keywords">

Comment on lines +101 to +111
groupedControlledKeywordOptions(): { key: string; options: FilterOption[] }[] {
const groups: Record<string, FilterOption[]> = {}
for (const opt of this.controlledKeywordOptions) {
const key = opt.groupKey || 'Other'
if (!groups[key]) {
groups[key] = []
}
groups[key].push(opt)
}
return Object.entries(groups).map(([key, options]) => ({key, options}))
}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should consider ordering this list alphabetically. Right now, selecting a keyword can change the group order and it's a bit jarring from a user perspective.

Comment on lines +142 to +160
watch: {
// Keep local selections in sync when parent controlledKeywords changes,
// e.g. from URL or Clear All
controlledKeywords: {
immediate: true,
handler(newVals: string[]) {
const byGroup: Record<string, string[]> = {}
for (const opt of this.controlledKeywordOptions) {
if (newVals.includes(opt.value)) {
const key = opt.groupKey || 'Other'
if (!byGroup[key]) byGroup[key] = []
byGroup[key].push(opt.value)
}
}
this.groupSelections = byGroup
}
}
},

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this block is responsible for a bug where selecting any keyword Other also selects all the other Other keywords from each keyword group.

I think that the most precise way around many Other options existing is to make the a composite identifier. This would look like key::value or MolecularMechanismAssessed::Other. Then before we send to the API, we split on the :: so we can send both the key and the value.

We'd need some additional changes, which I'll put in other comments.

Comment thread src/components/screens/SearchView.vue Outdated
Comment on lines +615 to +619

this.controlledKeywordOptions = (data.controlledKeywords || []).map((option) => ({
value: option.value,
badge: option.count,
groupKey: option.key
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here we could add a title entry which holds just options.value. Then value becomes ${option.key}::${option.value} to disambiguate the keywords across groups.

Comment thread src/lib/search.ts Outdated
databases: filters.filterPublicationDatabases.length > 0 ? filters.filterPublicationDatabases : undefined,
journals: filters.filterPublicationJournals.length > 0 ? filters.filterPublicationJournals : undefined,
keywords: filters.filterKeywords.length > 0 ? filters.filterKeywords : undefined
controlledKeywords: filters.filterControlledKeywords.length > 0 ? filters.filterControlledKeywords : undefined,
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Before sending to the backend, we'd now need to split on ::

Comment thread src/components/screens/SearchView.vue Outdated
filters.push({key, value, label: labelFn ? labelFn(value) : value})
}
}
addFilters('controlledKeywords', this.filterControlledKeywords)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'd need a custom labelFn here that strips the prefix before :: so that we get plain values for display or we could pass through the {key, value} object and extract just value.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants