Skip to content

feat: adjust function to render filter chip - #1785

Closed
ikondrat wants to merge 1 commit into
mainfrom
lig-9585.adjust-function-to-render-filter-chips
Closed

feat: adjust function to render filter chip#1785
ikondrat wants to merge 1 commit into
mainfrom
lig-9585.adjust-function-to-render-filter-chips

Conversation

@ikondrat

@ikondrat ikondrat commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

What has changed and why?

This PR contains changes for left side bar filtering chips to support categorical metadata filters

How has it been tested?

Accompanied wtih unit test

Did you update CHANGELOG.md?

  • Yes
  • Not needed (internal change)

Summary by CodeRabbit

  • New Features

    • Added metadata filter chips for numeric ranges and categorical selections.
    • Filter chips now remember previous selections, support toggling and clearing, and display formatted values.
  • Tests

    • Improved test setup to reset categorical metadata selections between tests.

@ikondrat
ikondrat requested a review from a team as a code owner July 28, 2026 08:00
@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The metadata filter chip hook is implemented in a nested module with a re-exported entrypoint. It derives remembered numeric and categorical chips, supports toggling and clearing filters, formats values, and resets categorical filter state in tests.

Changes

Metadata filter chips

Layer / File(s) Summary
Hook contract and entrypoint
lightly_studio_view/src/lib/components/MetadataFilterChips/useMetadataFilterChips/index.ts, lightly_studio_view/src/lib/components/MetadataFilterChips/useMetadataFilterChips/useMetadataFilterChips.svelte.ts
Defines MetadataFilterChip, establishes the hook’s metadata filter dependencies, and re-exports useMetadataFilterChips.
Remembered state and chip derivation
lightly_studio_view/src/lib/components/MetadataFilterChips/useMetadataFilterChips/useMetadataFilterChips.svelte.ts
Tracks narrowed numeric ranges and categorical selections, then derives active and remembered chip models.
Chip interactions, formatting, and validation
lightly_studio_view/src/lib/components/MetadataFilterChips/useMetadataFilterChips/useMetadataFilterChips.svelte.ts, lightly_studio_view/src/lib/components/MetadataFilterChips/useMetadataFilterChips/useMetadataFilterChips.test.ts
Adds toggle and clear handlers, numeric and categorical formatting helpers, exposes the hook API, updates the component import, and resets categorical metadata values in test setup.

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

Sequence Diagram(s)

sequenceDiagram
  participant MetadataFilterChips
  participant useMetadataFilterChips
  participant useMetadataFilters
  MetadataFilterChips->>useMetadataFilterChips: request chips and handlers
  useMetadataFilterChips->>useMetadataFilters: read filter bounds and selections
  useMetadataFilters-->>useMetadataFilterChips: return metadata filter state
  useMetadataFilterChips-->>MetadataFilterChips: return active or remembered chips
  MetadataFilterChips->>useMetadataFilterChips: toggle or clear chip
  useMetadataFilterChips->>useMetadataFilters: update or reset filter values
Loading

Possibly related PRs

Suggested reviewers: leonardorosaa

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description has the required headings, but it omits issue/context details and gives only a vague testing note. Add the fixed issue, motivation/context, any dependencies, and concrete test steps or commands with their configuration.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title is related to the filter-chip change, but it is broader and less specific than the actual categorical metadata update.
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 lig-9585.adjust-function-to-render-filter-chips

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.

@ikondrat

Copy link
Copy Markdown
Contributor Author

/review

@lightly-fast-track-bot

Copy link
Copy Markdown

❌  Fast Track: checks did not pass

Guardrail Result Message
dummy Always passes.
frontend/complexity 3 file(s) checked, no violations.
backend/complexity 0 file(s) checked.
backend/coverage 0 file(s) checked.
diff-size PR adds 168 line(s) (limit: 215).
frontend/coverage [FAIL] lightly_studio_view/src/lib/components/MetadataFilterChips/useMetadataFilterChips/index.ts: no test file found [FAIL] lightly_studio_view/src/lib/components/MetadataFilterChips/useMetadataFilterChips/useMetadataFilterChips.svelte.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 3e30b63.

@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: 3e30b63c45

ℹ️ 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".

Comment on lines +143 to +150
const formatCategoricalValues = (values: CategoricalMetadataValue[] = []): string => {
const hasMissingValue = values.includes('Missing');
const hasNoValue = values.includes(null);
return values
.map((value) => {
if (value === null) return hasMissingValue ? 'Missing (no value)' : 'Missing';
if (value === 'Missing' && hasNoValue) return 'Missing (value)';
if (value === 'Other') return 'Other (value)';

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Handle categorical sentinel values explicitly

When a categorical filter contains the supported __missing__ or __other__ sentinel, this formatter falls through to String(value) and exposes the raw token in the chip. CategoricalMetadataValue excludes null, so the null branches cannot handle missing values; compare against MISSING_CATEGORICAL_VALUE and OTHER_CATEGORICAL_VALUE instead.

Useful? React with 👍 / 👎.

Comment on lines +12 to +14
kind: 'numeric' | 'categorical';
range?: Range;
values?: CategoricalMetadataValue[];

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Make chip payloads a discriminated union

Define numeric and categorical chip variants so kind: 'numeric' requires range and kind: 'categorical' requires values. Making both payloads optional permits invalid states and forces consumers to dereference possibly undefined fields instead of narrowing on kind.

AGENTS.md reference: AGENTS.md:L43-L45

Useful? React with 👍 / 👎.

values?: CategoricalMetadataValue[];
}

export function useMetadataFilterChips(collectionId: string | undefined) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Split the expanded hook into focused helpers

This hook now spans nearly 150 lines and combines numeric state, categorical state, chip construction, toggling, clearing, and formatting. Extract the numeric and categorical chip logic into focused helpers to follow the repository guideline that functions remain small and single-purpose.

AGENTS.md reference: AGENTS.md:L43-L45

Useful? React with 👍 / 👎.

beforeEach(() => {
storage.updateMetadataBounds({});
storage.updateMetadataValues({});
storage.updateCategoricalMetadataValues({});

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Add categorical chip behavior tests

The only categorical-related test change clears the store; no test seeds a categorical selection or verifies its subtitle, toggle, remembered value, or clear behavior. Add behavior-focused tests for the new branch so its user-visible contract is covered as required by the frontend TDD guidance.

AGENTS.md reference: AGENTS.md:L43-L45

Useful? React with 👍 / 👎.

Comment on lines +64 to +65
// One chip per key that is narrowed now or has a remembered range: active
// chips show the current range, disabled ones the remembered range.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Update the numeric-only chip comment

This comment now describes every chip as carrying a remembered range, although categorical chips carry value arrays instead. Update it to document both variants so the newly added categorical behavior is not contradicted by the surrounding explanation.

AGENTS.md reference: AGENTS.md:L43-L45

Useful? React with 👍 / 👎.

@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/components/MetadataFilterChips/useMetadataFilterChips/useMetadataFilterChips.svelte.ts`:
- Around line 9-15: Update the MetadataFilterChip model and MetadataFilterChips
rendering to discriminate categorical chips from numeric chips, ensuring
categorical entries do not access chip.range and instead use
hook.formatCategoricalValues(chip.values) for their subtitle. Add coverage for
rendering, toggling, and clearing categorical selections, then run make
static-checks and make test from lightly_studio_view.
🪄 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: 53dd3105-ef6e-4894-804e-658fdd581e2d

📥 Commits

Reviewing files that changed from the base of the PR and between eef6554 and 3e30b63.

📒 Files selected for processing (4)
  • lightly_studio_view/src/lib/components/MetadataFilterChips/useMetadataFilterChips.svelte.ts
  • lightly_studio_view/src/lib/components/MetadataFilterChips/useMetadataFilterChips/index.ts
  • lightly_studio_view/src/lib/components/MetadataFilterChips/useMetadataFilterChips/useMetadataFilterChips.svelte.ts
  • lightly_studio_view/src/lib/components/MetadataFilterChips/useMetadataFilterChips/useMetadataFilterChips.test.ts
💤 Files with no reviewable changes (1)
  • lightly_studio_view/src/lib/components/MetadataFilterChips/useMetadataFilterChips.svelte.ts

Comment on lines +9 to +15
export interface MetadataFilterChip {
key: string;
active: boolean;
kind: 'numeric' | 'categorical';
range?: Range;
values?: CategoricalMetadataValue[];
}

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.

🩺 Stability & Availability | 🔴 Critical | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Find relevant files:"
fd -a 'useMetadataFilterChips\.svelte\.ts|MetadataFilterChips\.svelte|ai_guidelines/frontend\.md' . | sed 's#^\./##'

echo
echo "Inspect target files around relevant content:"
for f in \
  lightly_studio_view/src/lib/components/MetadataFilterChips/useMetadataFilterChips/useMetadataFilterChips.svelte.ts \
  lightly_studio_view/src/lib/components/MetadataFilterChips/MetadataFilterChips.svelte
do
  if [ -f "$f" ]; then
    echo "===== $f ($(wc -l < "$f") lines) ====="
    nl -ba "$f" | sed -n '1,180p'
  else
    echo "MISSING: $f"
  fi
done

echo
echo "Search categorical/numeric chips usage:"
rg -n "MetadataFilterChip|formatCategoricalValues|chip\.range|kind:|CategoricalMetadataValue" lightly_studio_view/src/lib/components/MetadataFilterChips lightly_studio_view/src/lib || true

echo
echo "Check frontend guideline existence/content:"
if [ -f ai_guidelines/frontend.md ]; then
  nl -ba ai_guidelines/frontend.md | sed -n '1,220p'
else
  echo "MISSING ai_guidelines/frontend.md"
fi

echo
echo "Check Makefile/package for static/tests:"
if [ -f lightly_studio_view/Makefile ]; then
  nl -ba lightly_studio_view/Makefile | sed -n '1,180p'
fi
if [ -f lightly_studio_view/package.json ]; then
  node - <<'JS'
const fs=require('fs');
const p=JSON.parse(fs.readFileSync('lightly_studio_view/package.json','utf8'));
console.log(JSON.stringify({scripts:p.scripts, dependencies:p.dependencies, devDependencies:p.devDependencies}, null, 2));
JS
fi

Repository: lightly-ai/lightly-studio

Length of output: 650


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect deterministic Svelte/template expressions involving chip.range without running repo code.
python3 - <<'PY'
from pathlib import Path
p = Path('lightly_studio_view/src/lib/components/MetadataFilterChips/MetadataFilterChips.svelte')
text = p.read_text() if p.exists() else ''
terms = [
    ('chip.range.min', text.find('chip.range.min')),
    ('chip.range.max', text.find('chip.range.max')),
    ('values?: CategoricalMetadataValue', text.find('values?: CategoricalMetadataValue')),
    ('formatCategoricalValues', text.find('formatCategoricalValues')),
    ('chip.kind', text.find('chip.kind')),
]
for term, pos in terms:
    print(f'{term}: {pos}')
PY

Repository: lightly-ai/lightly-studio

Length of output: 285


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "===== lightly_studio_view/src/lib/components/MetadataFilterChips/useMetadataFilterChips/useMetadataFilterChips.svelte.ts ====="
awk '{printf "%5d\t%s\n", NR, $0}' lightly_studio_view/src/lib/components/MetadataFilterChips/useMetadataFilterChips/useMetadataFilterChips.svelte.ts

echo
echo "===== lightly_studio_view/src/lib/components/MetadataFilterChips/MetadataFilterChips.svelte ====="
awk '{printf "%5d\t%s\n", NR, $0}' lightly_studio_view/src/lib/components/MetadataFilterChips/MetadataFilterChips.svelte

echo
echo "===== related usage search ====="
rg -n "MetadataFilterChip|formatCategoricalValues|chip\.range|chip\.kind|CategoricalMetadataValue|Categorical|numeric" lightly_studio_view/src/lib/components/MetadataFilterChips lightly_studio_view/src/lib || true

echo
echo "===== frontend guidelines ====="
if [ -f ai_guidelines/frontend.md ]; then
  awk '{printf "%5d\t%s\n", NR, $0}' ai_guidelines/frontend.md
else
  echo "MISSING ai_guidelines/frontend.md"
fi

echo
echo "===== lightly_studio_view build/test config ====="
if [ -f lightly_studio_view/Makefile ]; then
  awk '{printf "%5d\t%s\n", NR, $0}' lightly_studio_view/Makefile
fi
if [ -f lightly_studio_view/package.json ]; then
  node - <<'JS'
const fs=require('fs');
const p=JSON.parse(fs.readFileSync('lightly_studio_view/package.json','utf8'));
console.log(JSON.stringify({scripts:p.scripts, dependencies:p.dependencies, devDependencies:p.devDependencies}, null, 2));
JS
fi

Repository: lightly-ai/lightly-studio

Length of output: 50383


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "===== MetadataFilterChips tests ====="
awk '{printf "%5d\t%s\n", NR, $0}' lightly_studio_view/src/lib/components/MetadataFilterChips/MetadataFilterChips.test.ts

echo
echo "===== make/package availability ====="
for f in lightly_studio_view/Makefile lightly_studio_view/package.json; do
  echo "--- $f ---"
  if [ -f "$f" ]; then
    awk '{printf "%5d\t%s\n", NR, $0}' "$f"
  else
    echo "MISSING"
  fi
done

echo
echo "===== static-check command file references ====="
rg -n "static-checks|type-check|eslint|tsc|vitest|svelte-check" -g 'Makefile' -g 'package.json' -g '*.md' .

Repository: lightly-ai/lightly-studio

Length of output: 11471


Make MetadataFilterChips branch on categorical chips.

Categorical chips are emitted without range, but this component reads chip.range.min/max unconditionally in the subtitle snippet. Make the chip model discriminated and render categorical subtitles with hook.formatCategoricalValues(chip.values) instead. Add a render/toggle/clear test for categorical selections, then run make static-checks and make test from lightly_studio_view.

🤖 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/components/MetadataFilterChips/useMetadataFilterChips/useMetadataFilterChips.svelte.ts`
around lines 9 - 15, Update the MetadataFilterChip model and MetadataFilterChips
rendering to discriminate categorical chips from numeric chips, ensuring
categorical entries do not access chip.range and instead use
hook.formatCategoricalValues(chip.values) for their subtitle. Add coverage for
rendering, toggling, and clearing categorical selections, then run make
static-checks and make test from lightly_studio_view.

Source: Coding guidelines

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.

1 participant