andy-clapson commented on issue #26651:
URL: https://github.com/apache/superset/issues/26651#issuecomment-5716016069
@rusackas have a peek - any/all feedback good here. A bit verbose likely...
## Motivation
Opening the time filter on a chart with no time range set shows this:
```
Edit time range
Range type [No filter v]
--------------------------------
Actual time range
No filter
[CANCEL] [APPLY]
```
The only control is a dropdown. To pick a date you first have to know that
`Range type` is a mode selector, and that dates live behind `Last`,
`Previous`,
`Current`, `Custom` or `Advanced`.
It is the most common complaint from dashboard users. *"The number one
complaint I
get on my sites, by far"* (@rscarborough1996). *"Our users just want a
simple date
picker and their eyes glaze over"* (@treygilliland). Two teams have already
built
their own replacements (@luutomas / @JanZuska, @amaannawab923).
The thread already agrees on the fix. @webobite, @luutomas, @JanZuska,
@TasmiaZerin1128 and @yousoph's mockups all landed on the same thing: a
calendar
with preset shortcuts.
We assumed something must make that hard, and checked. Three assumptions, all
wrong:
- An antd `RangePicker` won't fit. It fits. The input is 282px, and the
calendar
panel portals to `document.body` so the popover doesn't bound it.
- The calendar panel gets clipped. antd positions it inside the viewport.
- Clicking a date dismisses the popover stack. It doesn't.
A working version is 207 added lines, no new dependencies, no migration. This
stalled for two years because nobody built it, not because it was hard.
## Proposed Change
### Part 1: a Calendar range type
Add `Calendar` to the existing control: quick range shortcuts plus an antd
`RangePicker`. Show it by default when a chart has no time filter.
Per @michael-s-molina and @geido, this uses the antd component rather than a
custom
picker. Superset is on `antd ^6.6.1`, so the upgrade that blocked this has
landed.
Kept small on purpose:
- Quick ranges emit values that already exist, covering the three families
@rusackas asked to keep represented: `Last day`/`Last week`/`Last month`
for
rolling windows, `previous calendar month` for the previous period, and
`Current month`/`Current year` for the current one. No new strings.
Note `Current month` spans the whole calendar month (`DATETRUNC(today,
MONTH)` to
the start of next month), so it is not month-to-date. The grammar has no
to-date form, and adding one would mean new strings.
- The picker emits the same `since : until` the parser already handles.
`GET /api/v1/time_range/` stays the only validator.
- Existing frames are untouched.
Out of scope, none of it needed to fix the default:
- Any change to the grammar or to stored values.
- Bound inclusivity. It is `since <= col < until` (`get_time_filter` in
`superset/models/helpers.py`), already shown in the `Actual time range`
readout.
- First day of week, weekend definitions, month and day naming. These come
from the
antd component's i18n.
- Fiscal calendars and week numbering. The grammar has no fiscal concept, so
that
is backend work and a separate proposal.
- Reorganising frames into tabs.
### Part 2: the extension path
@rusackas asked for this as an Extension contribution point. That is the
right end
state. One correction to the rationale, because it changes what gets built:
the
thread has not diverged on the default. @webobite, @luutomas, @JanZuska,
@TasmiaZerin1128 and @yousoph all drew the same shape, a calendar with preset
shortcuts, differing mainly in preset count and in whether the modes are
tabs or a
dropdown. Where deployments actually
differ is fiscal calendars, week numbering and domain-specific period logic,
and
core cannot ship every variant of those. That is where a contribution point
earns
its keep, and it is a stronger case than flexibility in general.
Most of the seam already exists:
- Every frame already implements `FrameComponentProps` (`value: string`,
`onChange: (timeRange: string) => void`), and the popover passes all
frames the
same props.
- Values already round-trip through `customTimeRangeEncode`/`Decode`,
exported from
`@superset-ui/core`.
- `guessFrame` maps a stored string to the frame that can edit it, falling
back to
`Advanced` when nothing matches, so an unclaimed value degrades to raw text
instead of stranding the user.
Missing: `FRAME_OPTIONS` is a `const` array rather than registry-derived, and
`guessFrame` is a hard-coded chain with no way for a contributed frame to
claim a
string.
Part 1 hits that second gap directly. A calendar-emitted range and a
hand-written
one are the same string, so any rule broad enough to reopen the picker's own
output
also claims pre-existing values. Frame ownership is already ambiguous in
core, and the
only lever available today is hand-tuning the claim, with no way for the
frames
themselves to declare what they can edit.
So a contribution point needs a claim mechanism, not just a render interface.
Roughly, and illustrative rather than offered for vote:
```ts
interface TimeRangeFrame {
id: string;
name: string;
canDecode(value: string): boolean;
Component: ComponentType<FrameComponentProps>;
}
```
The design question that mechanism raises is precedence. If contributed
frames are
checked before core ones, an extension can capture `Last week`. If they are
checked
after, a contributed frame can never replace `Custom`, which is what someone
replacing the picker actually wants. Answering that from a real
implementation is
worth more than answering it on paper.
Deliverables here: make `FRAME_OPTIONS` registry-derived, build one
reference frame
against it, and document the seam. The public contribution point follows in
its own
SIP once that reference frame has exercised the claim mechanism.
`Contributions` in
`@apache-superset/core` only declares a `sqllab` scope today, so publishing
one
needs new host architecture regardless.
## New or Changed Public Interfaces
A new `Calendar` option in the time range control. No grammar change, no
change to
stored values, no new REST surface. Part 2 adds no public API.
## New dependencies
None.
## Migration Plan and Compatibility
No data migration. Emitted values are unchanged.
Saved charts holding an absolute date range will open on `Calendar` rather
than
`Custom`/`Advanced`. The stored value is untouched. As above, this follows
from a
calendar-emitted range and a hand-written one being the same string. Ranges
carrying
a time component keep their time: the picker shows time fields when the
value has
one, so nothing is truncated.
Unfiltered charts open on `Calendar` instead of the empty `No filter` pane.
`No filter` is still selectable. `DEFAULT_TIME_FILTER` already controls the
default
value and is unaffected.
## Rejected Alternatives
- A custom picker. Maintenance and upgrade cost of diverging from antd.
- A time slider (Power BI style). Not precise enough. The Number range
filter can be
improved separately.
- A seventh frame alongside the existing six, as originally proposed in
2024. That
adds another choice to a control whose problem is too many choices. This
proposal
adds an option but also makes it the default.
- Reorganising into tabs, per @yousoph's mockups, which group the frames as
Absolute, Relative and Advanced. Probably the right end state and the
grouping
question is already answered, but it is a much larger change than fixing
the
default and is better proposed on its own.
- Using antd's built-in `presets` prop for the quick ranges. A preset's
value is a
concrete date tuple (`ValueDate<RangeValueType>` in rc-picker), so
selecting one
emits absolute dates. `Last week` would be saved frozen rather than as an
expression that re-resolves per query, and a saved dashboard would keep
showing
the same seven days. Superset's relative grammar cannot round-trip through
that
model, which is why the quick ranges sit outside the picker rather than
inside it.
This is the specific point where the component has to be augmented.
- Specifying a contribution point now. Scoped to the frontend it cannot
serve the
cases that actually differ between deployments (fiscal calendars, week
numbering),
because those need grammar support that does not exist.
## Open questions for [DISCUSS]
1. **Should the quick ranges be operator-configurable?** Proposed: yes. The
shipped
community implementations carry around nineteen presets, which is too
many for
most deployments and too few for some, and no fixed list will suit
everyone. A
config key following `DEFAULT_TIME_FILTER` (declared in
`superset/config.py`,
exposed through `FRONTEND_CONF_KEYS` in `superset/views/base.py`) would
take a
list of time-range strings:
```python
QUICK_TIME_RANGES = [
"Last day", "Last week", "Last month",
"previous calendar month", "Current month", "Current year",
]
```
Values only, with labels looked up from the existing option lists and
falling
back to the string itself. An empty list hides the row. This also gives
deployments a route to period shapes core does not ship, such as a genuine
month-to-date via `DATETRUNC(DATETIME('today'), MONTH) : now`, without
adding
grammar. Note the row is a single joined control and fits about six
entries at
the popover's 600px width, so longer lists need a different layout.
2. Does the default view need time-of-day precision, or does that stay in the
advanced frames?
3. Is the `ControlPopover` defect below a prerequisite, or tracked
separately?
4. Explore has no shared time range across temporal columns, so N columns
means N
ranges that can disagree. In scope or separate?
5. Continue the existing dev@ `[DISCUSS]` thread, or reopen?
## Appendix: defects found while measuring
Both pre-date this proposal and reproduce on unmodified `master`. Suggest
filing
separately.
- `ControlPopover.calculatePlacement` has a dead zone. A trigger with
`xRatio` and
`yRatio` both between 0.35 and 0.65 falls back to placement `left`, which
gets
flip-only overflow adjustment and cannot shift back into the viewport. So
whether
an oversized popover recovers depends on which row its trigger sits in and
on
window height. Predicted from source, confirmed in the DOM at two viewport
sizes.
- The antd 5 to 6 upgrade renamed `.ant-popover-inner` to
`.ant-popover-container`
and changed its padding from `12px` to `0 12px 12px`, losing 4px above the
popover
title across control popovers.
<img width="644" height="591" alt="Image"
src="https://github.com/user-attachments/assets/53ed4684-3de0-47a6-8ca6-2e61741a286f"
/>
<img width="633" height="602" alt="Image"
src="https://github.com/user-attachments/assets/8c30ce33-d7f9-4440-a453-4a2b63c46b2e"
/>
<img width="623" height="418" alt="Image"
src="https://github.com/user-attachments/assets/02b78cd3-2462-4848-8624-41b4f8c8854c"
/>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]