-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(components): Filter suggestion dropdown to only include values that exist with the current filters and add show the number of options #633
Conversation
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
This is a preview of the changelog of the next release. If this branch is not up-to-date with the current main branch, the changelog may not be accurate. Rebase your branch on the main branch to get the most accurate changelog. Note that this might contain changes that are on main, but not yet released. Changelog: 0.11.4 (2025-01-06)Features
Bug Fixes |
b53436b
to
97e1e89
Compare
97e1e89
to
b60df2e
Compare
b60df2e
to
6ded571
Compare
6ded571
to
b83bfe8
Compare
b83bfe8
to
1101bfc
Compare
1101bfc
to
3519e7c
Compare
…-input and lineage-filter using lapisFilter objects
3519e7c
to
e06c074
Compare
7ca6ca1
to
2dabbe9
Compare
<option | ||
value={item[lapisField]} | ||
key={item[lapisField]} | ||
style='white-space: nowrap;' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
style='white-space: nowrap;' | |
className='whitespace-nowrap' |
<option | ||
value={item[lapisField]} | ||
key={item[lapisField]} | ||
>{`${item[lapisField]} (${item['count']})`}</option> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we also want to include
className='whitespace-nowrap'
here?
value={item[lapisField]} | ||
key={item[lapisField]} | ||
style='white-space: nowrap;' | ||
>{`${item[lapisField]} (${item['count']})`}</option> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You don't need a template string here. You can use JSX string rendering directly.
>{`${item[lapisField]} (${item['count']})`}</option> | |
>{item[lapisField]} ({item['count']})</option> |
<option | ||
value={item[lapisField]} | ||
key={item[lapisField]} | ||
>{`${item[lapisField]} (${item['count']})`}</option> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You don't need a template string here. You can use JSX string rendering directly.
>{`${item[lapisField]} (${item['count']})`}</option> | |
>{item[lapisField]} ({item['count']})</option> |
@@ -78,7 +88,7 @@ const TextInputInner: FunctionComponent<TextInputInnerProps> = ({ lapisField, pl | |||
if (value === undefined) { | |||
return true; | |||
} | |||
return data.includes(value); | |||
return data.map((item) => item[lapisField]).includes(value); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would probably be better to put data.map((item) => item[lapisField])
in a useMemo
so that we don't have to map the whole data on every keystroke again.
if (aValue === undefined && bValue !== undefined) { | ||
return 1; | ||
} | ||
if (bValue === undefined && aValue !== undefined) { | ||
return -1; | ||
} | ||
if (aValue === undefined && bValue === undefined) { | ||
return 0; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is shorter, less complicated, but most probably as good as the longer version ;)
if (aValue === undefined && bValue !== undefined) { | |
return 1; | |
} | |
if (bValue === undefined && aValue !== undefined) { | |
return -1; | |
} | |
if (aValue === undefined && bValue === undefined) { | |
return 0; | |
} | |
if (aValue === undefined) { | |
return 1; | |
} | |
if (bValue === undefined) { | |
return -1; | |
} |
field: string, | ||
signal?: AbortSignal, | ||
) { | ||
const fetchAggregatedOperator = new FetchAggregatedOperator<Record<string, string>>(lapisFilter, [field]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually the type Record<string, string>
is not really correct. When you choose a field of type int
for field
, then the sort function won't work.
How do we deal with this? Should we generalize the sort function?
@@ -14,6 +14,7 @@ import { withinShadowRoot } from '../withinShadowRoot.story'; | |||
const codeExample = String.raw` | |||
<gs-text-input | |||
lapisField="host" | |||
lapisFilter={{}} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be good to provide an example with more values here.
@@ -29,6 +29,20 @@ export class TextInputComponent extends PreactLitAdapter { | |||
@property() | |||
initialValue: string | undefined = undefined; | |||
|
|||
/** | |||
* A LAPIS filter to fetch the number of sequences for. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
* A LAPIS filter to fetch the number of sequences for. | |
* A LAPIS filter to fetch the number of sequences that is shown on each autocomplete suggestion. |
const output: (Record<string, string> & { | ||
count: number; | ||
})[] = []; | ||
|
||
const findOrCreateGroup = (pattern: string) => { | ||
let group = output.find((item) => item[field] === pattern) as GroupType | undefined; | ||
if (!group) { | ||
group = { count: 0, [field]: pattern } as GroupType; | ||
output.push(group); | ||
} | ||
return group; | ||
}; | ||
|
||
data.forEach((item) => { | ||
if (!item[field]) { | ||
return; | ||
} | ||
const parts = item[field].split('.'); | ||
for (let step = 0; step < parts.length; step++) { | ||
const section = `${parts.slice(0, step + 1).join('.')}*`; | ||
const group = findOrCreateGroup(section); | ||
group.count += item.count; | ||
} | ||
const group = findOrCreateGroup(item[field]); | ||
group.count += item.count; | ||
}); | ||
|
||
return sortDataByField(output, field); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this tries to do more than it can achieve:
- The sorting is off:
JN.1.1
appears at the top, butJN.1.1*
is somewhere further down. I would expect them to be next to each other. - The computed counts for values that include sublineages are not correct, because they don't consider aliases.
- SILO will already return all possible parent lineage. IMO we should not need to compute them here.
This looks more complicated than initially thought. Let's split the changes?
- Let's discuss counts for lineages and maybe do it later.
- We can get sorting (for gs-text-input and gs-lineage-filter) and counts for gs-text-input done in this PR.
Closing in favor of #666 🤘 |
resolves #609
Summary
This shows the number of values for each option in the dropdown and filters the list of option to options that are available with current filters.
Sadly it is not possible to style the options component so that the number of the options is next to the value and not below, we will need to create a custom component for this. Loculus does this by using
'@headlessui/react'
'sCombobox
class -- however sadly this requires react and thus cannot be used in our webcomponents (?) I have not been able to find a good solution for this without react.Screenshot
PR Checklist