Skip to content

FE: types, global store, and data hooks for categorical metadata - #1746

Merged
ikondrat merged 61 commits into
mainfrom
kondrat-lig-9585-frontend-categorical-metadata-bar-chart-filter-ui-8-sp.p5
Jul 27, 2026
Merged

FE: types, global store, and data hooks for categorical metadata#1746
ikondrat merged 61 commits into
mainfrom
kondrat-lig-9585-frontend-categorical-metadata-bar-chart-filter-ui-8-sp.p5

Conversation

@ikondrat

@ikondrat ikondrat commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Summary

Stacked on p4. Pure data layer — no UI changes.

  • CategoricalMetadataValue / CategoricalMetadataValues types (services/types.ts): map field name → set of selected values; the sentinel string "__missing__" represents samples with no value for the field
  • categoricalMetadataValues session-storage slot (useGlobalStorage.ts): persists categorical selections across page navigation, cleared when the collection changes
  • createMetadataFilters extended: converts the selected values map into one in filter per non-empty field (calls the BE operator added in p4)
  • useCategoricalMetadataDistribution hook: calls GET /metadata/value_counts, disambiguates literal "Missing"/"Other" strings from the sentinel buckets, and returns typed CategoricalMetadataBucket[] arrays per field

Test plan

  • make static-checks (frontend) passes
  • npm run test:unit passes (new tests in useCategoricalMetadataDistribution, useMetadataFilters)

Part of LIG-9585.

Summary by CodeRabbit

  • New Features
    • Added categorical metadata filtering (string/boolean values) with dedicated missing/other handling alongside numeric filters.
    • Introduced a categorical metadata distributions helper to convert value-count responses into UI-ready buckets.
    • Persisted categorical filter selections in session storage for the session.
  • Bug Fixes
    • Improved bucket mapping to preserve runtime value types and correctly disambiguate “Missing”/“Other” when literal labels coexist with placeholders.
  • Tests
    • Added unit coverage for categorical bucket transformation, request option construction, and combined categorical+numeric filter generation.

ikondrat and others added 2 commits July 22, 2026 18:03
Adds weather (skewed string), reviewed (boolean), camera_id (25 values,
exercises the "Other" bucket), and split (~20% missing, exercises the
"Missing" bucket) alongside the existing numeric fields. location now
uses weighted sampling instead of uniform.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@ikondrat
ikondrat requested a review from a team as a code owner July 22, 2026 16:18
@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Adds categorical metadata types, session-backed selection state, categorical in predicates, and a query hook that transforms metadata value-count responses into typed value, missing, and other buckets.

Changes

Categorical metadata

Layer / File(s) Summary
Categorical metadata state and filters
lightly_studio_view/src/lib/services/types.ts, lightly_studio_view/src/lib/hooks/useGlobalStorage.ts, lightly_studio_view/src/lib/hooks/useMetadataFilters/...
Categorical values and sentinel constants are typed, persisted in session storage, exposed through metadata hooks, reset during metadata loading, and converted into in predicates alongside numeric filters.
Categorical distribution query and buckets
lightly_studio_view/src/lib/hooks/useCategoricalMetadataDistribution/..., lightly_studio_view/src/lib/hooks/index.ts
The distribution hook maps value counts and missing/other sentinels into typed buckets with deterministic IDs and disambiguated labels, forwards request filters, and is publicly exported with test coverage.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant MetadataView
  participant useCategoricalMetadataDistribution
  participant getMetadataValueCounts
  MetadataView->>useCategoricalMetadataDistribution: provide collectionId and filter
  useCategoricalMetadataDistribution->>getMetadataValueCounts: request value counts
  getMetadataValueCounts-->>useCategoricalMetadataDistribution: return value_counts
  useCategoricalMetadataDistribution-->>MetadataView: return typed value, missing, and other buckets
Loading

Possibly related PRs

Suggested reviewers: leonardorosaa, jonaswurst

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and accurately reflects the main frontend data-layer changes for categorical metadata.
Description check ✅ Passed The description covers the summary and test plan, but it omits the required changelog checkbox section.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch kondrat-lig-9585-frontend-categorical-metadata-bar-chart-filter-ui-8-sp.p5

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@lightly-fast-track-bot

lightly-fast-track-bot Bot commented Jul 22, 2026

Copy link
Copy Markdown

❌  Fast Track: checks did not pass

Guardrail Result Message
dummy Always passes.
frontend/complexity 7 file(s) checked, no violations.
backend/complexity 0 file(s) checked.
backend/coverage 0 file(s) checked.
diff-size PR adds 252 line(s), which exceeds the limit of 215.
frontend/coverage [FAIL] lightly_studio_view/src/lib/hooks/index.ts: no test file found [FAIL] lightly_studio_view/src/lib/services/types.ts: no test file found [FAIL] lightly_studio_view/src/lib/hooks/useCategoricalMetadataDistribution/useCategoricalMetadataDistribution.svelte.ts: coverage data not found [FAIL] lightly_studio_view/src/lib/hooks/useGlobalStorage.ts: coverage data not found [FAIL] lightly_studio_view/src/lib/hooks/useMetadataFilters/useMetadataFilters.ts: coverage data not found

View the guardrail run

To run the guardrails locally, from fast_track/ run make install once, then make run-guardrails (or GUARDRAILS=<name1>,<name2> make run-guardrails for some guardrails).

Reflects 00938e8.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d54a61f998

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

ikondrat and others added 11 commits July 22, 2026 18:29
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds an 'in' operator that accepts a list of string/boolean/null values
and builds an OR predicate, using a LEFT OUTER JOIN when null is present
to match samples with no metadata entry.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Introduces the CategoricalMetadataValue/CategoricalMetadataValues types
and a session-storage-backed store for selected categorical filter values,
alongside an export for the upcoming useCategoricalMetadataDistribution hook.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
createMetadataFilters now accepts an optional categoricalMetadataValues map
and appends one 'in' filter per non-empty key; also clears the categorical
store when the collection changes.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Fetches value-counts for all categorical metadata fields and shapes the
response into typed CategoricalMetadataBucket arrays, disambiguating
literal 'Missing'/'Other' values from the sentinel missing/other buckets.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@ikondrat
ikondrat force-pushed the kondrat-lig-9585-frontend-categorical-metadata-bar-chart-filter-ui-8-sp.p4 branch from 55ec580 to cf40cb2 Compare July 22, 2026 17:06
@ikondrat
ikondrat force-pushed the kondrat-lig-9585-frontend-categorical-metadata-bar-chart-filter-ui-8-sp.p5 branch from d54a61f to 8d4e752 Compare July 22, 2026 17:06
@ikondrat

Copy link
Copy Markdown
Contributor Author

/review

@ikondrat

Copy link
Copy Markdown
Contributor Author

/review

ikondrat and others added 4 commits July 23, 2026 09:58
The hook used .svelte.ts but doesn't use Svelte reactivity primitives
directly; .ts matches the convention of useNumericMetadataDistribution.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
TanStack Query v6 hooks must live in .svelte.ts files per frontend guidelines.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Split the combined test into focused cases for string values vs booleans,
use keyword arguments for clarity, and tighten resolver call assertions
with assert_called_once_with.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When a function and its module file share the same name, mypy resolves the
attribute as the module (not callable). Add a __init__.pyi stub for
metadata_resolver to declare the four exported functions explicitly, and
use explicit re-exports (as) in both __init__.py files to signal intent.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
ikondrat and others added 17 commits July 24, 2026 11:39
…t-filter-ui-8-sp.p1.p2' into kondrat-lig-9585-frontend-categorical-metadata-bar-chart-filter-ui-8-sp.p2
…t-filter-ui-8-sp.p1.p2' into kondrat-lig-9585-frontend-categorical-metadata-bar-chart-filter-ui-8-sp.p2
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
…t-filter-ui-8-sp.p1.p2' into kondrat-lig-9585-frontend-categorical-metadata-bar-chart-filter-ui-8-sp.p2
…t-filter-ui-8-sp.p2' into kondrat-lig-9585-frontend-categorical-metadata-bar-chart-filter-ui-8-sp.p4
…t-filter-ui-8-sp.p4' into kondrat-lig-9585-frontend-categorical-metadata-bar-chart-filter-ui-8-sp.p5
Base automatically changed from kondrat-lig-9585-frontend-categorical-metadata-bar-chart-filter-ui-8-sp.p4 to main July 27, 2026 09:34

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@lightly_studio_view/src/lib/services/types.ts`:
- Around line 90-91: The categorical metadata contract currently represents
missing selections as null instead of "__missing__". In
lightly_studio_view/src/lib/services/types.ts lines 90-91, remove null from
CategoricalMetadataValue and expose the missing sentinel; in
lightly_studio_view/src/lib/hooks/useMetadataFilters/useMetadataFilters.ts lines
52-55, type and translate categorical selections using that sentinel per the API
contract; in
lightly_studio_view/src/lib/hooks/useMetadataFilters/useMetadataFilters.test.ts
lines 86-96, update coverage so the expected in predicate includes
"__missing__".
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: a635c7ec-3c84-485d-8772-f802f2f2fec0

📥 Commits

Reviewing files that changed from the base of the PR and between 86ea268 and 0137600.

📒 Files selected for processing (7)
  • lightly_studio_view/src/lib/hooks/index.ts
  • lightly_studio_view/src/lib/hooks/useCategoricalMetadataDistribution/useCategoricalMetadataDistribution.svelte.ts
  • lightly_studio_view/src/lib/hooks/useCategoricalMetadataDistribution/useCategoricalMetadataDistribution.test.ts
  • lightly_studio_view/src/lib/hooks/useGlobalStorage.ts
  • lightly_studio_view/src/lib/hooks/useMetadataFilters/useMetadataFilters.test.ts
  • lightly_studio_view/src/lib/hooks/useMetadataFilters/useMetadataFilters.ts
  • lightly_studio_view/src/lib/services/types.ts

Comment thread lightly_studio_view/src/lib/services/types.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
lightly_studio_view/src/lib/hooks/useCategoricalMetadataDistribution/useCategoricalMetadataDistribution.test.ts (1)

9-42: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Add coverage for sentinel buckets.

These tests cover literal "Missing" and empty value_counts, but no missing_count/other_count input. Add assertions proving literal values remain normal value buckets while sentinel buckets are emitted separately; otherwise the selector regression is not detected.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@lightly_studio_view/src/lib/hooks/useCategoricalMetadataDistribution/useCategoricalMetadataDistribution.test.ts`
around lines 9 - 42, Add test coverage for missing_count and other_count
handling in selectCategoricalDistributions. Verify literal "Missing" entries
remain normal kind "value" buckets, while missing_count and other_count inputs
produce separate sentinel buckets with their expected kinds, labels, counts, and
IDs.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@lightly_studio_view/src/lib/hooks/useCategoricalMetadataDistribution/useCategoricalMetadataDistribution.svelte.ts`:
- Around line 6-32: Restore separate sentinel bucket types in
selectCategoricalDistributions: map missing_count and other_count to distinct
buckets with stable IDs, while preserving literal value buckets including string
values "Missing" and "Other". In
lightly_studio_view/src/lib/hooks/useCategoricalMetadataDistribution/useCategoricalMetadataDistribution.svelte.ts#L6-L32,
update the bucket type definitions and selector mapping; in
lightly_studio_view/src/lib/hooks/useCategoricalMetadataDistribution/useCategoricalMetadataDistribution.test.ts#L9-L42,
add fixtures and assertions covering both sentinel buckets and literal
"Missing"/"Other" values.

---

Outside diff comments:
In
`@lightly_studio_view/src/lib/hooks/useCategoricalMetadataDistribution/useCategoricalMetadataDistribution.test.ts`:
- Around line 9-42: Add test coverage for missing_count and other_count handling
in selectCategoricalDistributions. Verify literal "Missing" entries remain
normal kind "value" buckets, while missing_count and other_count inputs produce
separate sentinel buckets with their expected kinds, labels, counts, and IDs.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: ce45d3ad-69cd-45aa-9342-8b7b089494e7

📥 Commits

Reviewing files that changed from the base of the PR and between 0137600 and 7b84dd4.

📒 Files selected for processing (2)
  • lightly_studio_view/src/lib/hooks/useCategoricalMetadataDistribution/useCategoricalMetadataDistribution.svelte.ts
  • lightly_studio_view/src/lib/hooks/useCategoricalMetadataDistribution/useCategoricalMetadataDistribution.test.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@lightly_studio_view/src/lib/hooks/useCategoricalMetadataDistribution/useCategoricalMetadataDistribution.svelte.ts`:
- Around line 7-10: Update the categorical metadata bucket mapper to emit
"__missing__" as the value for buckets recognized as missing instead of null,
and align CategoricalMetadataBucket’s missing variant with that sentinel so
bucket.value remains a valid CategoricalMetadataValue for filtering.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 2313f6b7-e5d8-4730-8792-916c0402af1e

📥 Commits

Reviewing files that changed from the base of the PR and between 31e3b0b and 00938e8.

📒 Files selected for processing (3)
  • lightly_studio_view/src/lib/hooks/useCategoricalMetadataDistribution/useCategoricalMetadataDistribution.svelte.ts
  • lightly_studio_view/src/lib/hooks/useCategoricalMetadataDistribution/useCategoricalMetadataDistribution.test.ts
  • lightly_studio_view/src/lib/services/types.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • lightly_studio_view/src/lib/hooks/useCategoricalMetadataDistribution/useCategoricalMetadataDistribution.test.ts

@ikondrat
ikondrat added this pull request to the merge queue Jul 27, 2026
Merged via the queue into main with commit 822fd47 Jul 27, 2026
22 checks passed
@ikondrat
ikondrat deleted the kondrat-lig-9585-frontend-categorical-metadata-bar-chart-filter-ui-8-sp.p5 branch July 27, 2026 10:38
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