Visitar URL original
fix(dashboard): honour DASHBOARD_AUTO_REFRESH_INTERVALS in the refresh dropdown by kokhlo · Pull Request #44982 · apache/superset · GitHub
Skip to content

fix(dashboard): honour DASHBOARD_AUTO_REFRESH_INTERVALS in the refresh dropdown - #44982

Merged
EnxDev merged 8 commits into
apache:masterfrom
kokhlo:fix/44981-auto-refresh-intervals-from-config
Oct 12, 2026
Merged

EnxDev merged 8 commits into
apache:masterfrom
kokhlo:fix/44981-auto-refresh-intervals-from-config

Conversation

@kokhlo

@kokhlo kokhlo commented Oct 5, 2026

Copy link
Copy Markdown
Contributor

Summary

DASHBOARD_AUTO_REFRESH_INTERVALS reaches the browser but is never read by the frontend: the refresh-interval selector builds its radio list from a module-level constant, REFRESH_FREQUENCY_OPTIONS in superset-frontend/src/dashboard/components/RefreshFrequency/RefreshFrequencySelect.tsx. On master only DASHBOARD_AUTO_REFRESH_MODE survived the auto-refresh rework (#37459); in 6.0.0 Header/index.jsx still looked the configured pairs up to label an interval, so this is a consumption gap, not a payload gap.

This makes the selector derive its options from the bootstrapped config, which restores the 6.0.x behaviour:

  • getRefreshFrequencyOptions turns the configured [seconds, label] pairs into options and appends the Custom entry, which is a UI affordance rather than an interval. Configured labels are rendered verbatim — the deployment authored them, so running them through t() would rewrite operator wording (a German 10 Minuten stays 10 Minuten).
  • The value list is now data rather than a hard-coded slice, so a configured interval that is absent from the built-in list (e.g. 600) is offered and persisted like any preset.
  • isPresetValue/getCustomValue take the resolved list, so a dashboard whose stored refresh_frequency is missing from the configuration still renders — the frequency falls through to the Custom input with its current value instead of silently resetting to "Don't refresh".

Why the fallback branch

The option list degrades to the previous built-in constant whenever the config is absent or not a well-formed list of [number, string] pairs — an empty array, a bare string, entries with a missing/blank label, or a negative or non-numeric value. That keeps embedded and partially bootstrapped payloads rendering exactly as they do today instead of an empty selector. A Custom entry already present in the configuration is not duplicated.

Testing

cd superset-frontend
npx jest src/dashboard/components/RefreshFrequency src/dashboard/components/RefreshIntervalModal.test.tsx src/dashboard/components/PropertiesModal

84 passed / 10 suites. The same new tests against pristine origin/master (7a2913e) fail 7/17, so the interval list and the malformed-entry handling are pinned by the suite rather than asserted against current behaviour. RefreshFrequencySelect is shared with PropertiesModal's RefreshSection, whose suites are included in that run. npx oxlint --config oxlint.json is clean on the touched paths (the set-state-in-effect warning on that file is present on master too), and tsc -p . reports nothing for these files (the run fails on unbuilt plugin project references, unrelated to this change).

Fixes #44981

@bito-code-review

bito-code-review Bot commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

Code Review Agent Run #1550e1

Actionable Suggestions - 0
Additional Suggestions - 4
  • superset-frontend/src/dashboard/components/RefreshFrequency/RefreshFrequencySelect.tsx - 2
    • Duplicate option values · Line 111-111
      `getRefreshFrequencyOptions` validates shape, sign, and label but not uniqueness: two configured entries with the same seconds (e.g. `[60, "1 minute"]` twice) both reach `presets.map`, rendering duplicate React keys and two simultaneously-checked radios. The shipped default in `superset/config.py` is unique, but deployment overrides are unvalidated. Skip values already collected.
    • Conflicting presets naming · Line 115-115
      The local `presets` in `getRefreshFrequencyOptions` (line 115) includes the Custom entry on the fallback path, while the component's `presets` (line 168) excludes it — the same name denotes two different shapes in one file, and `isPresetValue` treats Custom as a non-preset. Rename the line-115 local (e.g. `baseOptions`) to avoid confusion.
  • superset-frontend/src/dashboard/components/RefreshIntervalModal.test.tsx - 1
    • New tests missing required docstrings · Line 153-153
      Both newly added tests (`the interval list comes from the configured DASHBOARD_AUTO_REFRESH_INTERVALS`, `a saved frequency missing from the configured list still renders and survives a save`) have no docstring. BITO.md adaptive rule 12148 requires every newly added test function to carry a docstring documenting purpose and expected outcome. Add a concise one-liner to each.
  • superset-frontend/src/dashboard/components/RefreshFrequency/RefreshFrequencySelect.test.tsx - 1
    • Formatter style violation · Line 25-25
      The diff converts single to double quotes, but the enforced formatter mandates `singleQuote: true` (`superset-frontend/.oxfmtrc.json`) via the `oxfmt-frontend` pre-commit hook (`scripts/oxfmt.sh` runs `npx oxfmt --write`), which AGENTS.md requires before pushing. 1968 src files use single-quote imports vs 12 double; oxfmt will rewrite these lines (and the `(option)` arrow parens at line 101) back. Run oxfmt on this file.
Review Details
  • Files reviewed - 4 · Commit Range: 544761d..544761d
    • superset-frontend/src/dashboard/components/RefreshFrequency/RefreshFrequencySelect.test.tsx
    • superset-frontend/src/dashboard/components/RefreshFrequency/RefreshFrequencySelect.tsx
    • superset-frontend/src/dashboard/components/RefreshFrequency/index.ts
    • superset-frontend/src/dashboard/components/RefreshIntervalModal.test.tsx
  • Files skipped - 0
  • Tools
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful
    • Eslint (Linter) - ✔︎ Successful

Bito Usage Guide

Commands

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

  • /review - Manually triggers an incremental AI Review.

  • /review full - 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 Superset You can customize the agent settings here or contact your Bito workspace admin at evan@preset.io.

Documentation & Help

AI Code Review powered by Bito Logo

return;
}
const [value, label] = interval;
const seconds = Number(value);

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.

Suggestion: Number(value) turns null and an empty string into zero, so malformed configuration appears as a no-refresh option and selecting it disables refresh.

Assessment: 🟠 Major · 🔁 Occurrence: Rarely · 🏷️ Type error

Use CodeAnt Skill Fix in Cursor Fix in VSCode Claude

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** superset-frontend/src/dashboard/components/RefreshFrequency/RefreshFrequencySelect.tsx
**Line:** 102:102
**Comment:**
	*Type Error: <code>Number(value)</code> turns <code>null</code> and an empty string into zero, so malformed configuration appears as a no-refresh option and selecting it disables refresh.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
👍 | 👎

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.

✅ CodeAnt verified this suggestion was addressed in subsequent commits and marked this thread resolved as of 2ea4d18.

The parser now accepts only numeric values or non-empty strings before converting them, so null and empty strings are rejected instead of becoming a zero-second option.

If that's not right, unresolve this thread and CodeAnt will leave it open.

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.

✅ CodeAnt verified this suggestion was addressed in subsequent commits and marked this thread resolved as of 5ac5a76.

Added toIntervalSeconds, which accepts only numbers and non-empty strings before conversion. Null, empty strings, and other malformed values become NaN and are filtered out.

If that's not right, unresolve this thread and CodeAnt will leave it open.

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.

✅ CodeAnt verified this suggestion was addressed in subsequent commits and marked this thread resolved as of c88a927.

Added toIntervalSeconds, which accepts only numbers or non-empty strings before conversion. null and empty strings now become NaN and are filtered out instead of appearing as a zero-second option.

If that's not right, unresolve this thread and CodeAnt will leave it open.

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.

✅ CodeAnt verified this suggestion was addressed in subsequent commits and marked this thread resolved as of 1f6ec28.

Added toIntervalSeconds, which accepts only numbers or non-empty strings before conversion. null and empty strings now become NaN and are filtered out instead of appearing as a zero-second option.

If that's not right, unresolve this thread and CodeAnt will leave it open.

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.

✅ CodeAnt verified this suggestion was addressed in subsequent commits and marked this thread resolved as of 33dfe7d.

Added toIntervalSeconds, which accepts only numbers or non-empty strings before conversion. null and empty strings now become NaN and are filtered out instead of appearing as a zero-second option.

If that's not right, unresolve this thread and CodeAnt will leave it open.

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.

✅ CodeAnt verified this suggestion was addressed in subsequent commits and marked this thread resolved as of 7090b0e.

Added toIntervalSeconds, which accepts only numbers or non-empty strings before conversion. null and empty strings now become NaN and are filtered out instead of appearing as a zero-second option.

If that's not right, unresolve this thread and CodeAnt will leave it open.

@bito-code-review

Copy link
Copy Markdown
Contributor

The flagged issue is correct. Using Number(value) on null or an empty string results in 0, which can incorrectly cause the UI to treat malformed configuration as a valid "Don't refresh" option.

To resolve this, you should validate the input more strictly before converting it to a number. The current PR already implements a robust fix in getRefreshFrequencyOptions by checking Number.isFinite(seconds) and ensuring the label is a non-empty string.

If you are referring to the handleRadioChange function specifically, you can improve the conversion there as well:

  const handleRadioChange = (event: RadioChangeEvent) => {
    const rawValue = event.target.value;
    const selectedValue = rawValue === '' || rawValue === null ? NaN : Number(rawValue);
    
    if (Number.isNaN(selectedValue)) {
      return;
    }
    // ... rest of the logic

I have checked the PR and there are no other pending review comments in the provided context. Would you like me to review any other parts of the PR?

superset-frontend/src/dashboard/components/RefreshFrequency/RefreshFrequencySelect.tsx

const handleRadioChange = (event: RadioChangeEvent) => {
    const rawValue = event.target.value;
    const selectedValue = rawValue === '' || rawValue === null ? NaN : Number(rawValue);
    
    if (Number.isNaN(selectedValue)) {
      return;
    }
    // ... rest of the logic

@kokhlo

kokhlo commented Oct 5, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for the review — taking the first two, pushing a follow-up commit.

Duplicate option values — fixed: getRefreshFrequencyOptions now tracks collected intervals in a Set and skips an entry whose seconds were already seen, so a deployment repeating [60, "1 minute"] cannot produce duplicate React keys or two simultaneously-checked radios. The first occurrence wins, and '600' (string spelling the same interval) is treated as the same value rather than a new one. Covered by keeps the first of two entries sharing an interval.

Conflicting presets naming — fixed: the local inside getRefreshFrequencyOptions is now baseOptions; presets remains the component-level name for the list with Custom filtered out, which is the only place isPresetValue consumes.

On the coercion point, the loose conversion was a real hole and the follow-up closes it: Number(null), Number('') and Number([]) are all 0, and 0 is the legitimate "Don't refresh" interval, so those values used to pass validation as a real option. The value is now only converted when it is a number or a non-blank string; anything else becomes NaN and the entry is dropped. Pinned by rejects values that coerce to a real interval.

Docstrings on new tests — not taking this one. BITO.md is not in the repository, and no test function in this tree carries a docstring (checked RefreshIntervalModal.test.tsx, Header/HeadlessAutoRefresh.test.tsx and the sibling suites under src/dashboard/components): the file-level ASF header is the convention. Adding per-test prose only to this PR would make it inconsistent with everything around it. Happy to add them if the maintainers actually want that convention introduced.

@bito-code-review

bito-code-review Bot commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

Code Review Agent Run #e58187

Actionable Suggestions - 0
Review Details
  • Files reviewed - 4 · Commit Range: 544761d..5ac5a76
    • superset-frontend/src/dashboard/components/RefreshFrequency/RefreshFrequencySelect.test.tsx
    • superset-frontend/src/dashboard/components/RefreshFrequency/RefreshFrequencySelect.tsx
    • superset-frontend/src/dashboard/components/RefreshFrequency/index.ts
    • superset-frontend/src/dashboard/components/RefreshIntervalModal.test.tsx
  • Files skipped - 0
  • Tools
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful
    • Eslint (Linter) - ✔︎ Successful

Bito Usage Guide

Commands

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

  • /review - Manually triggers an incremental AI Review.

  • /review full - 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 Superset You can customize the agent settings here or contact your Bito workspace admin at evan@preset.io.

Documentation & Help

AI Code Review powered by Bito Logo

@EnxDev EnxDev 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.

Read through this one. Reading the intervals from config and falling back on a missing or bad payload both look right, and keeping a stored frequency that isn't in the config is handled well.

One thing to fix before merge: configured labels skip t(), so non-English deployments lose their translated interval names on the default config. Details inline, plus two smaller notes on the tests.

Configured interval labels ship in English from config.py and both the
6.0 and 2022 selectors rendered them through t(), so wrap them the same
way; t() passes unknown strings through unchanged, keeping custom
wording verbatim. Since negative intervals never survive validation,
the configured path cannot carry the Custom entry — drop the unreachable
hasCustom branch and pin that with the reworked tests. Mock t() in the
test suite so the translation path is observable without a language
pack.
@codeant-ai-for-open-source

codeant-ai-for-open-source Bot commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

CodeAnt PR Risk: Low Risk

  • The PR appears safe to merge; configured intervals are validated, deduplicated, and covered by focused tests.
  • Tests also cover bootstrapped configuration, saved values missing from the configured list, and Custom selections that collide with presets.

Assessed commit: 7090b0ebff84

@netlify

netlify Bot commented Oct 6, 2026 •

Copy link
Copy Markdown

✅ Deploy Preview for superset-docs-preview ready!

Name Link
🔨 Latest commit 33dfe7d
🔍 Latest deploy log https://app.netlify.com/projects/superset-docs-preview/deploys/6acb44951134a4000844eabd
😎 Deploy Preview https://deploy-preview-44982--superset-docs-preview.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

}: RefreshFrequencySelectProps) => {
const configuredIntervals = useSelector(
(state: RootState) =>
state.dashboardInfo?.common?.conf?.DASHBOARD_AUTO_REFRESH_INTERVALS,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The interval list is only read from state.dashboardInfo, but PropertiesModal (and so this select) also mounts from the Dashboard List and Home pages (DashboardList/index.tsx), where no dashboard has been hydrated. There dashboardInfo?.common?.conf is undefined, so a deployment that sets DASHBOARD_AUTO_REFRESH_INTERVALS to [[0, "Don't refresh"], [600, "10 minutes"]] still sees the hardcoded 10 seconds/30 seconds/... presets when editing a dashboard from those pages, and the issue stays unfixed on that path. Should this fall back to the bootstrapped state.common.conf when dashboardInfo has no config?

@kokhlo

kokhlo commented Oct 10, 2026

Copy link
Copy Markdown
Contributor Author

Good catch — fixed in 1f6ec28: the selector now falls back to the bootstrapped state.common.conf.DASHBOARD_AUTO_REFRESH_INTERVALS when dashboardInfo has no config, so the select renders the configured list on the Dashboard List / Home paths too (PropertiesModal mounts it from DashboardList/index.tsx with only the bootstrapped store). Added two regression tests: one rendering with only state.common hydrated, one asserting the hydrated dashboard config still wins when both exist. Both fail without the fallback.

@codecov

codecov Bot commented Oct 11, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 98.30508% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 82.90%. Comparing base (e229ea4) to head (7090b0e).

Files with missing lines Patch % Lines
...onents/RefreshFrequency/RefreshFrequencySelect.tsx 98.30% 1 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##           master   #44982   +/-   ##
=======================================
  Coverage   82.90%   82.90%           
=======================================
  Files        3018     3018           
  Lines      193288   193334   +46     
  Branches    45018    45052   +34     
=======================================
+ Hits       160236   160277   +41     
- Misses      30014    30019    +5     
  Partials     3038     3038           
Flag Coverage Δ
javascript 78.63% <98.30%> (+0.03%) ⬆️

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

☔ View full report in Codecov by Harness.
📢 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.

@EnxDev
EnxDev merged commit ea06872 into apache:master Oct 12, 2026
79 checks passed
villebro pushed a commit that referenced this pull request Oct 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Dashboard auto-refresh dropdown ignores DASHBOARD_AUTO_REFRESH_INTERVALS (6.1.0 and master)

4 participants