Skip to content

docs: a filter on another semantic view can source a facet (CUB-4903) - #11966

Merged
mngr merged 1 commit into
masterfrom
docs/cub-4903
Sep 23, 2026
Merged

mngr merged 1 commit into
masterfrom
docs/cub-4903

Conversation

@mngr

@mngr mngr commented Sep 23, 2026 •

Copy link
Copy Markdown
Collaborator

This page depends on cubedevinc/cubejs-enterprise#15310 (CUB-4903) and must not merge before it — until that PR ships, a filter on another semantic view is still greyed out in the facet source picker.

The condition list this page points at is master's and is rewritten by #11936 (CUB-4769), which documents the widening that #15310's own base, cubedevinc/cubejs-enterprise#15177, ships. Either docs PR may merge first — they touch different sentences of the same section — but while #11936 is unmerged that list still reads as the pre-#15177 one, on both sides of a view boundary alike.

What changed

docs/explore-analyze/dashboards/widgets/controls.mdx, Faceted filters:

  • The lead sentence no longer restricts faceting to filters on one semantic view, and points at the new subsection for the cross-view case.
  • The condition list is stated once, for siblings on either semantic view. The cross-view distinction is the extra matching step, not a narrower condition set: the matching-dimension picker only offers dimensions of the same data type as the source's dimension (isCrossViewBindingUsable), so a source can only ever be matched onto its own builder column and carries exactly the conditions its own member type supports.
  • The source-picker paragraph drops "or one targeting a different semantic view" from the grey-out reasons, quotes the tooltip's new wording, says a cross-view filter is selectable and adds a row for matching it, and qualifies All as listening to same-view siblings.
  • Turning Facet off now also clears the dimensions you matched sources to.
  • New #### Sources on another semantic view: the Based on row and the Matching dimension picker, the pre-selection ranks and when they decline to answer, which dimensions are selectable, Save/Cancel and withdrawal, and a <Warning> for the picked-but-unmatched source that narrows nothing.

No new page, so docs.json is unchanged; this adds no widget, container or control type, so the Product Taxonomy in docs-mintlify/CLAUDE.md is unchanged too.

Verified against the code and the running product

Code (feature branch mentor/cub-4903-cross-view-filter-faceting):

  • A cross-view source is selectable, and the only grey-out left is a condition no member type can express — isFacetSourceSelectable / isFacetOperatorExpressible in facet-scope-utils.ts.
  • An unmatched cross-view source emits nothing: useFacetScope's toFilter returns null without a mapping, and facetSourceScopeState calls it 'unbound', not an error.
  • A matched source is emitted against <this view>.<matched member> — generateCubeFilter's memberPath argument — so the values query never names the source's view.
  • The pre-selection ranks and their fail-closed cases (0 or >1 alias candidates, a candidate of another data type) are suggestFacetSourceMember in facet-source-binding.ts.
  • Nothing persists before Save: the sidebar holds facetDimensionMappings in local state and writes it only in its save effect, as undefined when empty.
  • Turning Facet off, changing the filter's semantic view, and unchecking a source each clear the map (handleToggleFacet, handleSemanticViewChange, handleFacetSourceSelectionChange).
  • The published/embedded dashboard reads the same map: useFacetBindingContext(widget.config?.facetDimensionMappings, …) in modules/embed/pages/PublishedDashboard/Widgets/FilterWidget.tsx.

Running product (staging-mngr-2, pw__shared fixture; full log in the issue's evidence as handoff-r2-walk.log):

  • Source picker rows: Customer signup (another view) selectable, Custom SQL rule greyed with the tooltip "This filter's condition cannot narrow a value list".
  • The binding row reads Based on Customers Created at / Matching dimension for "Customer signup" / Created at; in the member picker only Created at is selectable, Status, City, Age and State are greyed.
  • Picked but unmatched: the row shows "Until you pick a matching dimension, this source does not narrow the list.", the saved config has facetDimensionMappings = undefined, and with the source set to an empty window the value list still lists all 4 statuses.
  • Matched: the empty window empties the list, 2016-01-01→2016-03-31 leaves 2 of 4, and the values query's filter leaves are orders.created_at only — it never names customers.
  • Unchecking and saving removes the key and restores the list; re-checking re-opens the row seeded on Created at. Cancel leaves the picker back at All with 0 binding rows.
  • Published dashboard with ?f_customers.created_at={"type":"between","value":["2016-01-01","2016-03-31"]} narrows the faceted filter to the same 2 values.

Feature PR: https://github.com/cubedevinc/cubejs-enterprise/pull/15310
Linear: https://linear.app/cube-d3/issue/CUB-4903/cross-view-filter-faceting

@mngr
mngr requested a review from keydunov as a code owner September 23, 2026 07:13
@mintlify

mintlify Bot commented Sep 23, 2026 •

Copy link
Copy Markdown
Contributor

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated
cubed3 🟢 Ready View Preview Sep 23, 2026, 7:19 AM

💡 Tip: Enable Automations to automatically generate PRs for you.

@github-actions github-actions Bot added docs Issues that require a documentation improvement pr:community Contribution from Cube.js community members. labels Sep 23, 2026
@claude

claude Bot commented Sep 23, 2026 •

Copy link
Copy Markdown
Contributor

Claude finished @mngr's task in 2m 9s —— View job


Review complete — 0 high, 1 medium, 2 low, all posted inline

Details
  • Read the diff and the full changed file
  • Check docs conventions (docs-mintlify/CLAUDE.md)
  • Verify cross-references and anchors
  • Handle prior review threads
  • Post findings

Findings

# Severity Location Concern
1 Medium controls.mdx:100 "On the same semantic view," in front of the condition list drops the only statement of which conditions a cross-view source may carry, and leaves line 107's "those other conditions" back-referencing a list that no longer covers the siblings it describes. The gate is view-independent.
2 Low controls.mdx:139 "Nothing is stored until you Save, and clearing a match or unchecking the source drops it from the dashboard" contradicts itself — the drop lands on Save, per the PR's own evidence ("Unchecking and saving removes the key").
3 Low controls.mdx:137 Three pre-selection ranks, two fail-closed cases and the selectability rule in one paragraph; the page uses a table for comparable ranked material. Also flags "the query behind it never names the source's view" as an implementation detail with no action behind it.

Checks that came back clean

  • Both new anchor links resolve: #sources-on-another-semantic-view matches the new #### heading, #sharing-the-current-selection matches the existing ## one.
  • No other page describes faceted filter sources — the only other facet hit in docs-mintlify is charts/configuration/small-multiples.mdx:10, an unrelated chart-faceting screenshot TODO.
  • docs.json correctly unchanged (no new page), and the Product Taxonomy in docs-mintlify/CLAUDE.md correctly unchanged (no new control type).
  • Heading levels, <Warning> usage, root-relative/in-page link style and second-person tone all match the page and the repo conventions.

Not verifiable here

The behavioural claims are checked against cubedevinc/cubejs-enterprise#15310, which this repo has no access to — the pre-selection ranks, the grey-out rule and the unmatched-source behaviour are taken from the PR description rather than read from code. Finding 1 rests on the description's own account of isFacetOperatorExpressible being condition-only; if the cross-view path applies a narrower condition set, the fix direction changes but the gap does not.

Merge gating is as the description states: this documents behaviour that ships with the enterprise PR, so it should not land first.

Review threads

The listing returned 0 unresolved threads on this PR, so none of mine to resolve and none re-affirmed. All three findings posted as new inline comments.

· branch [`docs/cub-4903`](https://github.com/cube-js/cube/tree/docs/cub-4903)

Comment thread docs-mintlify/docs/explore-analyze/dashboards/widgets/controls.mdx Outdated
Comment thread docs-mintlify/docs/explore-analyze/dashboards/widgets/controls.mdx
Comment thread docs-mintlify/docs/explore-analyze/dashboards/widgets/controls.mdx
@claude

claude Bot commented Sep 23, 2026 •

Copy link
Copy Markdown
Contributor

Claude finished @mngr's task in 2m 8s —— View job


Docs review: no blockers — 0 high, 0 medium, 2 low (both posted inline), 1 nit noted

Full review
  • Read the PR diff
  • Read the full page for consistency with surrounding sections
  • Check anchors, cross-references, Mintlify conventions
  • Check prior review threads
  • Post findings

Findings

1. docs-mintlify/docs/explore-analyze/dashboards/widgets/controls.mdx:96 — matching alone doesn't make a cross-view source apply (low, posted inline)

The lead sentence says a sibling on another semantic view "narrows it once you [match it to a dimension of this one]", but line 107 scopes the default All to "every sibling on its own semantic view". A cross-view source has to be explicitly picked and matched; a reader who leaves the picker at All and reads only line 96 will expect the match to be enough.

2. controls.mdx:139 — Save-gating reads as contradicted inside its own sentence (low, posted inline)

"Nothing is stored until you Save, and clearing a match or unchecking the source drops it from the dashboard" — the second clause reads as an immediate drop. Per the PR's own evidence the key only leaves the config on save ("Unchecking and saving removes the key"), and Cancel puts the picker back at All.

3. controls.mdx:137 — nit, not posted inline. "one the dashboard already maps that control to for a chart" is the Controls mapping concept and could link to it; and the paragraph says "data type" twice where the page elsewhere says dimension type (### Operators by dimension type). Both optional — the paragraph is already link-dense.

Checked and clean

  • Anchors: #sources-on-another-semantic-view resolves to the new H4; #sharing-the-current-selection resolves to the H2 at line 402. No duplicate heading slug, so no explicit {#...} override needed (unlike the three User attribute default headings on this page).
  • docs.json correctly untouched — no new page.
  • H4 under H3 matches the existing #### User attribute default nesting; <Warning> usage matches the callout at line 124.
  • Terminology matches docs-mintlify/CLAUDE.md: "semantic view", second person, no legacy names.
  • The two new <Warning> / prose statements about an unmatched source overlapping the existing "source with nothing to scope by" warning at line 124 read as distinct cases (date condition vs. unbound cross-view source), so the "say it once" rule isn't breached.
  • No code changes, so nothing to build, lint or test; the docs site was not run.

Review threads

The listing returned 0 of my own threads (0 threads on the PR at all), so none to resolve and none re-affirmed. Findings 1 and 2 were posted as new inline threads; finding 3 was skipped as below the inline bar, not as a duplicate.

Note on merge order

The PR body flags the dependency on cubedevinc/cubejs-enterprise#15310 — this page describes a cross-view source as selectable, which is false until that ships. Nothing here changes that; it stays a merge-order constraint for a human.

· branch [`docs/cub-4903`](https://github.com/cube-js/cube/tree/docs/cub-4903)

Comment thread docs-mintlify/docs/explore-analyze/dashboards/widgets/controls.mdx
Comment thread docs-mintlify/docs/explore-analyze/dashboards/widgets/controls.mdx
@claude

claude Bot commented Sep 23, 2026 •

Copy link
Copy Markdown
Contributor

Claude finished @mngr's task in 2m 41s —— View job


Docs-only change, technically sound — 1 medium posted inline, 2 low noted, no correctness or security surface

Review details
  • Gather context (diff vs origin/master, full page, linked PRs)
  • Review the changed prose against page conventions and the described behaviour
  • Handle my own prior review threads (resolve stale / dedupe)
  • Post findings and final summary

Scope

One file, docs-mintlify/docs/explore-analyze/dashboards/widgets/controls.mdx. No code, no schema, no query planning — nothing to review for security, performance, test coverage or comment hygiene. The diff against master is smaller than the PR body describes, because #11936 (CUB-4769) has landed since: the condition list is already the widened one, and this PR only inserts "on its own semantic view or another" into it rather than rewriting it.

Checks that came back clean:

  • Anchor #sources-on-another-semantic-view matches the new #### Sources on another semantic view heading; #sharing-the-current-selection and #parent resolve on the page.
  • Heading depth (#### under ### Faceted filters) matches the page's existing nesting.
  • **Matching dimension for "*the source's title*"** nests emphasis inside strong — valid MDX.
  • No other page in docs-mintlify describes faceting, so nothing else went stale with the same-view restriction; the custom row in the URL-parameter table at controls.mdx:430 still reads correctly.
  • The behaviour claims are internally consistent: All is scoped to same-view siblings, so a cross-view source only ever arrives by an explicit pick, which is exactly the state the new <Warning> covers.
  • Removing "because its dimension was re-pointed at another semantic view say" was required — that example is now false.

Findings

Medium — controls.mdx:138, posted inline. "one of the same data type as the source's dimension, whose type can express the source's condition": the second clause is a property of the source, not of the candidate, so it never discriminates between candidates — either every dimension of that type is selectable or none is. The "none" branch is the real gap: a cross-view source is selectable on isFacetOperatorExpressible (any member type) but matchable only on isFacetingAvailable(condition, own type), so a condition its own dimension type cannot express — reachable by hand-written URL parameter, the same way custom is — makes the picker come back empty while the new <Warning> says "match it, or uncheck it". Suggestion attached; if the two gates can never disagree in practice, the clause is vacuous and should be dropped instead.

Low, not posted inline (you've stated only medium and high are fixed here, and these are exactly the editorial churn you called out):

  • controls.mdx:103 — "as the warning below sets out" now has two <Warning> blocks below it in the same section, both about a source that narrows nothing.
  • controls.mdx:106 — "A filter you picked that later stops qualifying" lost its only example along with the now-false cross-view one, so nothing tells the reader what makes a picked source stop qualifying.

Review threads

The unresolved-thread listing for this PR came back empty (single page, hasNextPage: false) — no prior threads, so none resolved and none re-affirmed. The author's four review comments are their own threads, already resolved or settled on their side; I left them alone.

Merge gate

Unchanged by this review: this page still must not merge before cubedevinc/cubejs-enterprise#15310, or the cross-view source it documents is greyed out in the shipped product.

· branch [`docs/cub-4903`](https://github.com/cube-js/cube/tree/docs/cub-4903)

@mngr
mngr merged commit aee61f4 into master Sep 23, 2026
16 checks passed
@mngr
mngr deleted the docs/cub-4903 branch September 23, 2026 17:14

A filter on one semantic view can narrow a faceted filter on another, once you say which dimension of the faceted filter's own view the source stands for. Pick it in the source picker like any other sibling and a row appears under the picker: **Based on** names the source's own view and dimension, and the picker beneath it — **Matching dimension for "*the source's title*"** — takes a dimension of *this* filter's view. The value list is scoped through that dimension, so the query behind it never names the source's view. The match is part of the dashboard, so it applies on a published dashboard and in an embed too, including when the source's value arrives in a [URL parameter](#sharing-the-current-selection).

The match is pre-selected for you when the answer is unambiguous: a dimension of this view the model declares as the same underlying column, then one the dashboard already maps that control to for a chart, then one matching by name and type. Several equally good candidates count as no answer, as does one of a different data type, and the row then opens unmatched. Only the dimensions the scope can use are selectable: one of the same data type as the source's dimension, whose type can express the source's condition.

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.

"whose type can express the source's condition" is a property of the source, not of the candidate, so it never rules a candidate in or out — and where it fails, the picker has nothing to offer at all and the Warning's advice cannot be followed.

The two clauses aren't independent. The first pins the candidate to the same data type as the source's dimension; given that, "whose type can express the source's condition" is just "the source's own dimension type can express its condition" — the same for every candidate. So either all dimensions of this view of that type are selectable or none are, and a reader who reads it as a per-candidate test will look for a candidate that passes both.

The "none are" branch is the gap. Per your own note on this PR, a cross-view source that is still unmatched is gated on isFacetOperatorExpressible(condition) — any member type can express it — while a match is gated on isFacetingAvailable(condition, matched member's data type), and the matched type is forced equal to the source's. A source whose condition some type can express but its own cannot is therefore selectable and unmatchable: the row opens, the member picker greys everything, and the new <Warning> tells the reader to "match it, or uncheck it" when only the second is possible. The page already establishes the reachable shape of such a filter — a condition its dimension type has no operator menu entry for, arriving by hand-written URL parameter, exactly as custom does two paragraphs up.

Two ways out, whichever matches the branch:

  • If that state is reachable, say the picker can come back empty and that unchecking is then the only move — otherwise the Warning reads as offering a choice the UI does not.
  • If isFacetOperatorExpressible and isFacetingAvailable(condition, own type) can never disagree for a filter the product can produce, then the second clause is genuinely vacuous and costs the sentence its readability for nothing; drop it and let the data-type rule stand alone.
Suggested change
The match is pre-selected for you when the answer is unambiguous: a dimension of this view the model declares as the same underlying column, then one the dashboard already maps that control to for a chart, then one matching by name and type. Several equally good candidates count as no answer, as does one of a different data type, and the row then opens unmatched. Only the dimensions the scope can use are selectable: one of the same data type as the source's dimension, whose type can express the source's condition.
The match is pre-selected for you when the answer is unambiguous: a dimension of this view the model declares as the same underlying column, then one the dashboard already maps that control to for a chart, then one matching by name and type. Several equally good candidates count as no answer, as does one of a different data type, and the row then opens unmatched. Only dimensions of the same data type as the source's dimension are selectable, and only where that type can express the source's condition at all — a condition it cannot, which only a [URL parameter](#sharing-the-current-selection) can set, leaves the picker with nothing to offer and unchecking the source as the only move.

This branch was successfully deployed

1 active deployment
staging - docs-mintlify — 52cc322b Deployed Sep 23, 2026 by mintlify[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docs Issues that require a documentation improvement pr:community Contribution from Cube.js community members.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant