Skip to content

Conversation

@Yogi776
Copy link

@Yogi776 Yogi776 commented Nov 25, 2025

SUMMARY

Adds name property to the GET /api/v1/dashboard/{pk}/filter_state/{key} endpoint response. The name is extracted from the id field in the JSON value, making it easier for frontend code to identify filter states without parsing the JSON value.

Problem:
The frontend needs to identify filter states by their name, but the current API only returns the raw value string. This requires the frontend to parse the JSON string and extract the id field every time, which is inefficient and error-prone.

Solution:
Extend the GET endpoint to return both value and name properties, where name is automatically extracted from the id field in the JSON value. This maintains backward compatibility while providing the convenience of direct access to the filter name.

IMPLEMENTATION DETAILS

Files Changed:

  1. superset/commands/dashboard/filter_state/get.py

    • Added get_with_name() method to GetFilterStateCommand
    • Extracts id field from JSON value and returns both value and name
    • Handles edge cases: invalid JSON, missing id field, or non-JSON values
    • Returns None for name when id is not present (graceful degradation)
  2. superset/dashboards/filter_state/api.py

    • Updated get() method to call get_with_name() instead of get()
    • Updated OpenAPI schema documentation to include name property
    • Maintains all existing error handling and access control
  3. tests/integration_tests/dashboards/filter_state/api_tests.py

    • Added test_get_dashboard_filter_state_with_name() - verifies name extraction when id exists
    • Added test_get_dashboard_filter_state_without_id() - verifies name is None when id missing
    • Updated existing test to verify name property is always present in response

Key Implementation Points:

  • Uses superset.utils.json for JSON parsing (not simplejson directly)
  • Handles JSONDecodeError, AttributeError, and TypeError exceptions gracefully
  • Returns name: null when value doesn't contain an id field (not an error condition)
  • Fully backward compatible - existing code expecting only value continues to work

BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF

N/A - API change only

Before:

{
  "value": "{\"id\":\"NATIVE_FILTER_ID\",\"extraFormData\":{...}}"
}

After:

{
  "value": "{\"id\":\"NATIVE_FILTER_ID\",\"extraFormData\":{...}}",
  "name": "NATIVE_FILTER_ID"
}

TESTING INSTRUCTIONS

Manual Testing:

  1. Create a dashboard with native filters:

    • Navigate to any dashboard in Superset
    • Add a native filter if one doesn't exist
    • Configure the filter (e.g., Value filter, Time Range filter)
  2. Apply a filter:

    • Select a value or set a time range on the dashboard
    • This will trigger a POST request to create/update filter state
  3. Test the GET endpoint:

    • Open Browser Developer Tools (F12) → Network tab
    • Find the POST request to /api/v1/dashboard/{id}/filter_state
    • Copy the key from the response
    • Call GET /api/v1/dashboard/{id}/filter_state/{key}
  4. Verify response:

    • Response should include both value and name properties
    • name should match the id field from the JSON value
    • If value doesn't contain id, name should be null

Browser Console Test:

// On a dashboard page, after applying a filter:
const dashboardId = window.location.href.match(/\/dashboard\/(\d+)/)?.[1];
const key = "your_filter_state_key"; // Get from Network tab

fetch(`/api/v1/dashboard/${dashboardId}/filter_state/${key}`, {
  credentials: 'include'
})
.then(r => r.json())
.then(data => {
  console.log('Full Response:', data);
  console.log('Has value:', 'value' in data); // Should be true
  console.log('Has name:', 'name' in data); // Should be true
  console.log('Name value:', data.name); // Should match id from value
  
  // Verify name matches id
  if (data.value) {
    const valueObj = JSON.parse(data.value);
    if (valueObj.id) {
      console.log('Name matches id:', data.name === valueObj.id); // Should be true
    }
  }
});

Automated Tests:

# Run the filter_state API tests
pytest tests/integration_tests/dashboards/filter_state/api_tests.py -v

# Expected: All tests pass, including:
# - test_get_dashboard_filter_state (verifies name property exists)
# - test_get_dashboard_filter_state_with_name (verifies name extraction)
# - test_get_dashboard_filter_state_without_id (verifies name is None)

Edge Cases Tested:

  • ✅ Filter state with id field → name extracted correctly
  • ✅ Filter state without id field → name is null
  • ✅ Invalid JSON in valuename is null (graceful handling)
  • ✅ Non-JSON valuename is null (graceful handling)
  • ✅ Backward compatibility → existing code still works

ADDITIONAL INFORMATION

Backward Compatibility:

  • ✅ Fully backward compatible
  • ✅ Existing code expecting only value continues to work
  • ✅ New name property is additive, doesn't break existing consumers

Error Handling:

  • Gracefully handles invalid JSON (returns name: null)
  • Gracefully handles missing id field (returns name: null)
  • All existing error cases (404, 403, etc.) remain unchanged

Performance:

  • Minimal overhead: single JSON parse operation
  • No additional database queries
  • No impact on cache operations

- Extract name from filter state value's id field
- Return both value and name in GET response
- Add test cases for name property extraction
- Update OpenAPI schema documentation

Fixes apache#36053
@github-actions github-actions bot added the api Related to the REST API label Nov 25, 2025
@Yogi776 Yogi776 marked this pull request as draft November 25, 2025 09:12
@Yogi776 Yogi776 marked this pull request as ready for review November 25, 2025 09:12
@dosubot dosubot bot added the dashboard Namespace | Anything related to the Dashboard label Nov 25, 2025
Copy link
Contributor

@bito-code-review bito-code-review bot left a comment

Choose a reason for hiding this comment

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

Code Review Agent Run #47ce7a

Actionable Suggestions - 1
  • superset/commands/dashboard/filter_state/get.py - 1
    • Type safety issue in JSON name extraction · Line 58-60
Additional Suggestions - 7
  • tests/integration_tests/dashboards/filter_state/api_tests.py - 3
    • Missing return type annotation function · Line 277-277
      Add return type annotation `-> None` to function `test_get_dashboard_filter_state_with_name`. Similar issues exist at lines 293 and 309.
      Code suggestion
       @@ -277,7 +277,7 @@
        def test_get_dashboard_filter_state_with_name(
            test_client, login_as_admin, dashboard_id: int, admin_id: int
      -) -> None:
      +) -> None:
    • Unused function argument in test · Line 278-278
      Remove unused parameter `login_as_admin` from function signature, or add a comment explaining why it's needed. Similar issue at line 294.
      Code suggestion
       @@ -277,8 +277,8 @@
        def test_get_dashboard_filter_state_with_name(
      -    test_client, login_as_admin, dashboard_id: int, admin_id: int,
      +    test_client, dashboard_id: int, admin_id: int,
        ) -> None:
    • Trailing comma missing in parameters · Line 278-278
      Add trailing comma after `admin_id: int` parameter. Similar issue at line 294.
      Code suggestion
       @@ -277,8 +277,8 @@
        def test_get_dashboard_filter_state_with_name(
            test_client, login_as_admin, dashboard_id: int, admin_id: int,
        ) -> None:
  • superset/commands/dashboard/filter_state/get.py - 4
    • Trailing comma missing in function parameters · Line 46-46
      Add a trailing comma after the `cmd_params: CommandParameters` parameter in the `get_with_name` method signature for consistency.
      Code suggestion
       @@ -45,2 +45,2 @@
      -    def get_with_name(
      -        self, cmd_params: CommandParameters
      +    def get_with_name(
      +        self, cmd_params: CommandParameters,
    • Use PEP 604 union type syntax · Line 47-47
      Use `X | Y` syntax instead of `Optional[dict[str, Optional[str]]]` for the return type annotation. Multiple similar issues exist on lines 36, 47, and 56.
      Code suggestion
       @@ -45,3 +45,3 @@
            def get_with_name(
                self, cmd_params: CommandParameters,
      -    ) -> Optional[dict[str, Optional[str]]]:
      +    ) -> dict[str, str | None] | None:
    • Docstring formatting issues · Line 48-48
      Fix docstring formatting: add a blank line after the summary line and move the summary to the first line of the docstring.
      Code suggestion
       @@ -48,4 +48,5 @@
      -        """
      -        Get filter state value and extract name from the JSON value.
      -        Returns a dict with 'value' and 'name' keys.
      -        """
    • Use PEP 604 union type syntax · Line 56-56
      Use `str | None` instead of `Optional[str]` for the type annotation. Multiple similar issues exist on lines 36, 47, and 56.
      Code suggestion
       @@ -56,1 +56,1 @@
      -        name: Optional[str] = None
      +        name: str | None = None
Review Details
  • Files reviewed - 3 · Commit Range: 56a52fd..56a52fd
    • superset/commands/dashboard/filter_state/get.py
    • superset/dashboards/filter_state/api.py
    • tests/integration_tests/dashboards/filter_state/api_tests.py
  • Files skipped - 0
  • Tools
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful
    • MyPy (Static Code Analysis) - ✔︎ Successful
    • Astral Ruff (Static Code Analysis) - ✔︎ Successful

Bito Usage Guide

Commands

Type the following command in the pull request comment and save the comment.

  • /review - Manually triggers a full AI review.

  • /pause - Pauses automatic reviews on this pull request.

  • /resume - Resumes automatic reviews.

  • /resolve - Marks all Bito-posted review comments as resolved.

  • /abort - Cancels all in-progress reviews.

Refer to the documentation for additional commands.

Configuration

This repository uses Default Agent You can customize the agent settings here or contact your Bito workspace admin at [email protected].

Documentation & Help

AI Code Review powered by Bito Logo

Comment on lines +58 to +60
value_dict = json_utils.loads(value)
# Extract the 'id' field from the JSON value as the name
name = value_dict.get("id")
Copy link
Contributor

Choose a reason for hiding this comment

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

Type safety issue in JSON name extraction

The new get_with_name method extracts the 'id' field from parsed JSON as the 'name', but doesn't ensure it's a string, violating the Optional[str] type hint. This could cause type errors downstream in superset/dashboards/filter_state/api.py where get_with_name is called, potentially leading to runtime failures when processing filter state data. Add a type check to enforce string type safety.

Code suggestion
Check the AI-generated fix before applying
Suggested change
value_dict = json_utils.loads(value)
# Extract the 'id' field from the JSON value as the name
name = value_dict.get("id")
value_dict = json_utils.loads(value)
# Extract the 'id' field from the JSON value as the name
name = value_dict.get("id")
if not isinstance(name, str):
name = None

Code Review Run #47ce7a


Should Bito avoid suggestions like this for future reviews? (Manage Rules)

  • Yes, avoid them

@codecov
Copy link

codecov bot commented Nov 27, 2025

Codecov Report

❌ Patch coverage is 72.00000% with 7 lines in your changes missing coverage. Please review.
✅ Project coverage is 68.12%. Comparing base (186693b) to head (56a52fd).
⚠️ Report is 21 commits behind head on master.

Files with missing lines Patch % Lines
superset/commands/dashboard/filter_state/get.py 66.66% 3 Missing and 1 partial ⚠️
superset/dashboards/filter_state/api.py 76.92% 2 Missing and 1 partial ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##           master   #36262       +/-   ##
===========================================
+ Coverage        0   68.12%   +68.12%     
===========================================
  Files           0      632      +632     
  Lines           0    46488    +46488     
  Branches        0     5039     +5039     
===========================================
+ Hits            0    31671    +31671     
- Misses          0    13553    +13553     
- Partials        0     1264     +1264     
Flag Coverage Δ
hive 43.77% <20.00%> (?)
mysql 67.22% <72.00%> (?)
postgres 67.27% <72.00%> (?)
presto 47.37% <20.00%> (?)
python 68.09% <72.00%> (?)
sqlite 66.89% <72.00%> (?)
unit 100.00% <ø> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

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

Labels

api Related to the REST API dashboard Namespace | Anything related to the Dashboard size/M

Projects

None yet

Development

Successfully merging this pull request may close these issues.

GET /api/v1/dashboard/{pk}/filter_state/{key} does not return "name" property

1 participant