Render GLQL date buckets as date-only labels in tables and lists

What does this MR do and why?

Resolves glql#200 (closed)

In analytics mode, date bucket dimensions like created(monthly) rendered as relative time ("1 month ago") in table and list views, because no presenter matched them. This MR adds a DateBucketPresenter that formats bucketed date strings properly, and routes fields with a granularity parameter to it instead of falling through to the relative-time presenter.

Changes

  • New DateBucketPresenter (app/assets/javascripts/glql/components/presenters/date_bucket.vue) formats bucketed date strings for table and list views.
  • New shared util app/assets/javascripts/glql/utils/date_bucket.js holds bucketDateOf and formatBucketDate, moved out of chart_data.js. dimensionLabelFormatter in chart_data.js now delegates to it.
  • presenter_registry.js: presenterFor takes a parameters option and routes string values with a granularity to DateBucketPresenter, ahead of the field-key, typename, and primitive dispatch.
  • field.vue gets a new parameters prop (default undefined), forwarded to the presenter. table.vue and list.vue pass field.parameters through.
  • presenter_registry.js: dataForField now takes presenterKey and compares the base field key (not the alias) for the title shortcut.

Design decisions

  • Cells always show the year; charts drop it unless the series spans multiple years, since the axis carries that context and a cell doesn't. The work item's weekly example ("13 - 19 Jul") renders as "13 - 19 Jul 2026" here. Open to pushback on this.
  • Routing checks for a string value plus a granularity parameter, not whether the value parses as a bucket date. If a bucket start ever stops parsing, the presenter falls back to showing the raw value in both tables and charts, rather than silently regressing to relative time. A hypothetical non-date field with a granularity still gets regular dispatch for number or object values. WDYT?
  • FieldPresenter forwards parameters to every presenter, but only DateBucketPresenter declares the prop. On other parameterised fields (e.g. durationQuantile with { quantile: 0.5 }), it lands as a harmless parameters="[object Object]" attribute. item already falls through the same way on every data-only presenter today, so guarding parameters alone felt inconsistent - gating both is a possible follow-up if reviewers prefer.

Also fixed: aliasing a bucket field as title (e.g. created(weekly) as "title") was matching the alias instead of the base field key, sending the whole row to LinkPresenter.

Standard-mode timestamps without a granularity (e.g. a work item's created field) still show relative time, unchanged.

Found while working on !254823 (merged). Related earlier decision on chart date formatting: !245952 (merged).

Screenshots or screen recordings

Local GDK data (AI usage events): timestamp(monthly) table, timestamp(weekly) list, timestamp(daily) table.

Before After
glql200_before_table glql200_after_table
glql200_before_list glql200_after_list
glql200_before_daily glql200_after_daily

Standard mode is unchanged (relative time stays):

glql200_after_standard

How to set up and validate locally

On a GDK with ClickHouse and analytics data for a group, embed GLQL blocks on any issue or wiki page. Local GDK ClickHouse usually has no pipeline or merge request rows, so the examples below use AI usage events - any analytics source with a date bucket dimension behaves the same, for example finished(weekly) on pipelines or created(monthly) on merge requests.

display: table
mode: analytics
query: type = AiUsageEvent and group = "gitlab-org" and timestamp > -365d
dimensions: timestamp(monthly)
metrics: totalCount
display: list
mode: analytics
query: type = AiUsageEvent and group = "gitlab-org" and timestamp > -365d
dimensions: timestamp(weekly)
metrics: totalCount

MR acceptance checklist

This checklist encourages us to confirm any changes have been analyzed to reduce risks in quality, performance, reliability, security, and maintainability.

Edited by Daniele Rossetti

Merge request reports

Loading
Loading