Skip to content

[ZEPPELIN-4407] Add copy to clipboard (TSV/CSV) for table results#5261

Merged
tbonelee merged 3 commits into
apache:masterfrom
kkalyan:master
Jun 3, 2026
Merged

[ZEPPELIN-4407] Add copy to clipboard (TSV/CSV) for table results#5261
tbonelee merged 3 commits into
apache:masterfrom
kkalyan:master

Conversation

@kkalyan
Copy link
Copy Markdown
Contributor

@kkalyan kkalyan commented Jun 2, 2026

What is this PR for?

I've seen users downloading CSV and opening in spreadsheet viewer and copying the text.
Adding way to copy CSV/TSV directly. This is orginally implemented by @amakaur #3496 but it was closed due to lack of tests. I'm picking it up now.

Changes

Angular UI (zeppelin-web-angular)

  • result.component — paragraph toolbar dropdown: renamed existing items to "Download as CSV/TSV", added divider, then "Copy as TSV" and "Copy as CSV"
  • table-visualization.component — inner table Export menu: added "Copy all data as TSV/CSV" and "Copy visible data as TSV/CSV" (mirrors the existing "Export visible" scope)

Classic AngularJS UI (zeppelin-web)

  • result-chart-selector.html — same dropdown restructure: Download / divider / Copy
  • result.controller.js — new $scope.copyToClipboard(delimiter) function

Behaviour

  • Header row (column names) is always included in the copied text
  • Cell values containing the delimiter, double-quotes, or newlines are RFC 4180 quoted
  • Uses navigator.clipboard.writeText with a document.execCommand('copy') fallback for older browsers

What type of PR is it?

Feature

What is the Jira issue?

https://issues.apache.org/jira/browse/ZEPPELIN-4407

How should this be tested?

  1. Run a paragraph that outputs a TABLE (e.g. %sh printf "col1\tcol2\na\t1\nb\t2\n")
  2. Click the next to the download button in the paragraph toolbar
  3. Verify the menu shows: Download as CSV, Download as TSV, (divider), Copy as TSV, Copy as CSV
  4. Click Copy as TSV → paste into a spreadsheet app or text editor — expect headers + rows, tab-delimited
  5. Click Copy as CSV → paste → expect headers + rows, comma-delimited
  6. Test with a cell value containing a comma, e.g. "hello, world" → the CSV copy should quote it correctly

Tests

  • Classic UI (Karma/Jasmine): zeppelin-web/src/app/notebook/paragraph/result/result.controller.test.js — 4 new specs covering TSV copy, CSV copy, delimiter quoting, and double-quote escaping
  • Angular UI (Playwright E2E): zeppelin-web-angular/e2e/tests/notebook/paragraph/copy-to-clipboard.spec.ts — 3 new specs (skipped on CI, require a live interpreter)

Questions

  • Does the license file need update? No
  • Is there a breaking change for older versions? No — existing Download as CSV/TSV behaviour is unchanged
  • Does this need documentation? No

screenshots

image image

Kalyan Kanuri added 2 commits June 2, 2026 11:55
Adds "Copy as TSV" and "Copy as CSV" options to the table result export
dropdown in both the Angular (zeppelin-web-angular) and classic AngularJS
(zeppelin-web) UIs.

- Header row (column names) is always included in the copied text
- Cell values containing the delimiter, double-quotes, or newlines are
  RFC 4180 quoted automatically
- Uses navigator.clipboard.writeText with a document.execCommand fallback
  for older browsers
- In the Angular table visualization, "Copy visible data" copies only the
  currently filtered/paginated rows, matching the existing "Export visible"
  behaviour
- Existing "CSV" / "TSV" download items renamed to "Download as CSV/TSV"
  for clarity

Closes apache#3496 (original AngularJS-only implementation by @amakaur)
…s in tests

Karma tests failed because spyOn(navigator.clipboard, 'writeText') was
called twice — once in beforeEach and again inside two test bodies.
Playwright tests failed because grantPermissions ran before the CI skip,
and Firefox/WebKit reject unknown permissions (clipboard-read/clipboard-write).
Copy link
Copy Markdown
Contributor

@tbonelee tbonelee left a comment

Choose a reason for hiding this comment

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

Thanks for the suggestion.
Overall logics looks good to me, and I only left a few feedbacks.
You could also add a test cases which handles double quote delimiter in both zeppelin-web and zeppelin-web-angular

Comment thread zeppelin-web-angular/src/app/pages/workspace/share/result/result.component.ts Outdated
Comment thread zeppelin-web/src/app/notebook/paragraph/result/result.controller.js Outdated
Comment thread zeppelin-web/src/app/notebook/paragraph/result/result.controller.js Outdated
- Extract fallbackCopy function and guard navigator.clipboard existence
  in both result.component.ts and table-visualization.component.ts so
  the fallback works in plain HTTP (non-secure) contexts
- Refactor result.controller.js: extract escape() closure shared by
  headers and cells; fix null/undefined cell value handling
- Add test: header values containing double quotes are RFC 4180 quoted
  (classic UI Karma test + Angular E2E Playwright test)
@tbonelee tbonelee merged commit 15966b5 into apache:master Jun 3, 2026
17 of 19 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants