tnc-ca-geo / animl-frontend

A frontend web app for viewing & labeling camera trap data by The Nature Conservancy.
https://animl.camera
15 stars 0 forks source link

Filter by Tags #165

Open nathanielrindlaub opened 8 months ago

nathanielrindlaub commented 8 months ago

Once we implement image-level Tags, we'll need a way for users to filter images by them. I imagine we could create a new section on the filter's panel for filtering by tag, and for each available tag create filter checkboxes for both a positive ("") and negative ("not-"), the same way we currently have two checkboxes for "reviewed" and "not-reviewed".

nathanielrindlaub commented 3 months ago

Updated UX thoughts

After giving this a bit more thought, I don't love the idea of providing pairs of "positive" and "negative" checkboxes for each tag, in the same way we do for "reviewed"/"not-reviewed". The point of having the pair is that sometimes you may want to just show reviewed images, or sometimes just show not-reviewed images, and sometimes you want to see both. If we just had a "reviewed" checkbox, we would only be able to see both "reviewed" + "not-reviewed" (if "reviewed" was checked) or "not-reviewed" (if "reviewed" was unchecked). There would be no way to ever hide the "not-reviewed" images, and just show "reviewed".

So for the "reviewed" filter the pair of checkboxes makes sense, but I don't think we can assume it will make sense for all tags a user might possible make available for their Project. For example, there probably isn't ever a need to only show not-favorite images, or not-no-rat images.

The other thing that makes this UX a bit challenging is that because images can have multiple tags (e.g., a single image could have a seen tag and a no-rat tag and a favorite tag), the implications of unchecking a tag checkbox might be a little little confusing for users. For example, imagine a user wanted to filter out all seen images, so they uncheck that checkbox. How do we handle images that have seen tags but also have other tags that are currently selected? Does that mean that we filter out all images that have a seen tag, or do we filter out all images that ONLY have a seen tag?

My proposed solution, and one that I think would give the user the most amount of expressive control, is a UI that looks like the following:

TAG FILTERS 

[ show ] / [ hide ]
[ at least one of the following ] / [ exact match ]

- [x] rat
- [x] no-rat
- [x] favorite
- [x] radio-collared
- [x] seen
- [x] retired
- [x] night
- [x] no-tags

Where:

The show/hide switch would give users the ability explicitly suppress the items they have selected, or explicitly show them, and the at least one of the following / exact match allows them to tell Animl how to handle situations in which there's more than one tag associated with the image, some of which are checked on and some of which are checked off.

To illustrate the problem and how that approach solves it, imagine you had the following 4 images the DB and you wanted to hide all seen images. :

Image 1
- tags: []

Image 2
- tags: ['no-rat', 'favorite', 'seen']

Image 3
- tags: ['seen']

Image 4
- tags: ['radio-collared', 'seen']

Using a traditional, pure checkbox-list approach, a user might try to uncheck seen, but, had we decided that a checked-on checkbox means include any images that have that tag, the only image filtered out of that user's query would be Image 3, and it would return Image 2 and 4 because they have other tags that are still checked-on. If we had instead decided that a checked-off checkbox means hide images with that tag, whether or not they had other tags, that would have returned just Image 1 and likely would have met the user's expectations.

However, that latter decision would have made doing something like "show me all radio-collared images" impossible, because if you only had radio-collared checked on, seen would need to be checked off, and the user would get nothing back from that query. In that situation, the user wants a checked-on checkbox to mean "include all instances of this tag".

If the user had the ability to express whether they were trying to "show" or "hide" things with their selections, and the ability to explicitly set the "includes at least one of the following" or "exact match" rule, both scenarios would be straight forward:

To hide all seen images, they'd simply select "hide" + "includes at least one of the following" + only select seen, and that would get them the desired result (only Image 1 would be returned).

To show all radio-collared images, they'd select "show" + "includes at least one of the following" and only select radio-collared from the list.

nathanielrindlaub commented 3 months ago

To be honest, I am having a bit of trouble thinking of a real-world use case for the "exact match" option. A user wouldn't know what tags may or may not be applied to their images, so why would they use "exact match"? For example even if I just wanted to see my "radio-collared" images at "night", if I selected "exact match" I'd be filtering out any images that had any other tags on them, which would be hard to predict.

The "exact match" option does have utility in the sense that it makes explicit and educates the user on how the query is working: i.e., if "hide", "includes at least one of the following", and the seen checkbox is on, the user will know that it's not just filtering out images that only have a seen tag.

nathanielrindlaub commented 3 months ago

Also realizing we might want work on that at least one of the following language. If two or more checkboxes are checked on, does that mean show/hide images where at least one of the selected tags is present? Or show/hide images where all of the selected tags are present? I had meant the latter but it's not clear from that phrase.

exact match I had envisioned meaning show/hide images with this exact set of tags, nothing more nothing less.

jue-henry commented 3 months ago

Nattys approach gives the user the option to filter-for or filter-tags, but we run into issues when users wish to filter-for a certain tag, while filtering out certain tags, which I think would be the primary use case. So we can instead build out a more fully-fledged query builder, where we give the user both options to filter-for and filter-out certain tags. This approach would present to the user 2 dropdowns. The first dropdown will include a list of statements like must include, must exclude, etc, and the second dropdown will be a list of tags. From there, we can add a new row to this list anytime a user fills out a row, and essentially give them a way to build their own unique query when needed. This approach may be a bit unintuitive initially, but gives the user most flexibility. Will have to consider if this is too technically involved for our user base.