Fix GLQL copy contents for chart, list, and stat display types
What does this MR do and why?
Fixes the GLQL "Copy contents" action for three display types where the copied text was incorrect or missing context.
Closes #604220 (closed)
Tables
Left unchanged. Uses HTML to respect UI sorting.
Charts (lineChart/columnChart/barChart/areaChart/barList/heatMap/divergingBarChart)
The copy action was scraping the DOM, but ECharts renders SVG/canvas with no semantic HTML. ProseMirror concatenated axis labels, tick values, and legend text in DOM order, producing garbled output like **CountLanguage**10K20K30K....
Fix: For chart display types, the copy path now builds clipboard content directly from the structured data (data.nodes + fields) using existing chart_data.js helpers. Produces an HTML table for text/html and a GFM markdown table for text/plain.
barChart, areaChart, barList, heatMap, and divergingBarChart were added on master after this MR was opened and share the same copy bug, so they're included now. Every display type is classified as either DOM copy or data copy, and a spec fails when a new type is added without a decision. Copied headers and values also handle parameterised and aliased fields, so created(weekly) copies as "Created (weekly)" and aliased metrics still pick the right value formatter. Date buckets always include the year, and values are copied as literal text (Count <threshold> stays Count <threshold>).
Lists (list/orderedList)
The template only rendered field values via FieldPresenter, never the field labels. Metric values appeared without context (e.g., 1,234 instead of Total count: 1,234).
Fix: Metric field labels are now rendered before their values in list items.
Stat
The label was rendered by the CrudComponent wrapper, but copyAsGFM() copies $refs.resolver.$el which is inside that wrapper. The label was architecturally outside the copy boundary.
Fix: When the block sets no title, the copied text is prefixed with the metric label. Nothing changes visually, so the wrapper heading isn't duplicated.
Screencast
How to set up and validate locally
- Navigate to a page with GLQL blocks (e.g., an issue description with embedded GLQL views)
- Test with
display: columnChartanddisplay: barChart- click "Copy contents", paste into a text editor, verify a readable markdown table - Test with
display: lineChartanddisplay: areaChart- same verification - Test with
display: list- verify metric labels appear (e.g., "Total count: 1,234") - Test with
display: stat- verify the metric label is included in copied text - Test with
display: table- verify no regression (should work as before)
MR acceptance checklist
- Tests added for new functionality
- All tests pass locally (
yarn jest spec/frontend/glql/- 627/627 pass) - Linting passes
- Security review: HTML escaping added for clipboard content values