Skip to content

feature(network-visualization): Add button to export HTML from Shiny#176

Merged
tonywu1999 merged 6 commits intodevelfrom
feature-export-html
Mar 5, 2026
Merged

feature(network-visualization): Add button to export HTML from Shiny#176
tonywu1999 merged 6 commits intodevelfrom
feature-export-html

Conversation

@tonywu1999
Copy link
Contributor

@tonywu1999 tonywu1999 commented Mar 5, 2026

Motivation and Context

This PR adds HTML export support to the network visualization module so users can download interactive network visualizations as standalone HTML files in addition to the existing code-download feature. The goal is to allow saving and sharing rendered networks outside the Shiny app.

Solution summary:

  • Introduces an export path that calls exportNetworkToHTML directly to generate a standalone HTML file for the currently rendered network.
  • Adds a unified download UI that shows both "Download HTML" and "Download Code" controls.
  • Adds server-side download handling with validation and user-facing error notifications.

Detailed Changes

  • R/module-visualize-network-server.R

    • Added function export_network_html(render_data, displayLabelType, file):
      • Validates render_data is not NULL (stops with "No network to export. Please ensure network is displayed first." if missing).
      • Calls exportNetworkToHTML(...) with nodes/edges, nodeFontSize=12, displayLabelType, writes to a temp file and copies to the requested download location.
    • Replaced previous widget-based HTML save approach in the server flow with direct exportNetworkToHTML usage for HTML export.
    • Added UI/server wiring for HTML download:
      • UI output network.html.button is rendered and a downloadHandler network_html_code is provided to generate the HTML file (including tryCatch and user notifications on failure).
    • Synced code-generation path to use exportNetworkToHTML(...) where HTML export is emitted.
  • R/module-visualize-network-ui.R

    • Renamed public helper createCodeDownloadBox(ns) → createDownloadBoxes(ns).
    • Updated createDownloadBoxes(ns) to render both network.html.button and network.code.button and changed layout to a right-aligned flexbox:
      • style = "text-align: right; padding: 10px; display: flex; justify-content: flex-end; gap: 10px;"
    • Updated call sites in createNetworkSettingsTab to use createDownloadBoxes(ns).
  • Public API / exports

    • New exported/internal function: export_network_html(render_data, displayLabelType, file).
    • Public helper renamed: createCodeDownloadBox → createDownloadBoxes (same signature).
  • Diff size (per manifest summary): roughly +39/-2 in server file and +5/-3 in UI file (lines changed reported in raw summary).

Unit Tests

  • tests/testthat/test_network_visualization.R
    • Added tests for export_network_html:
      • export_network_html writes HTML file correctly: stubs exportNetworkToHTML to write a simple HTML snippet, calls export_network_html with mock render_data and a temp file, and asserts the file exists, has content, and contains HTML tags.
      • export_network_html errors when render_data is NULL: asserts calling export_network_html(NULL, ...) raises the exact error message "No network to export. Please ensure network is displayed first."
    • Existing tests for data helpers and UI components remain; new tests specifically validate the HTML export control flow and error handling.

Coding Guidelines / Style Violations

  • Inline CSS styling: Several UI elements (including createDownloadBoxes) use inline style attributes (e.g., flexbox and button color styles). These should be moved to the app stylesheet or CSS classes for maintainability and consistent theming.
  • Inline color / style constants: Button color and border values are hard-coded inline instead of using centralized constants or CSS classes.
  • Missing roxygen documentation: The newly added/renamed helper functions (createDownloadBoxes and export_network_html) lack roxygen documentation/comments consistent with other public functions in the codebase; add #' docs for parameters and behavior.

@tonywu1999 tonywu1999 marked this pull request as ready for review March 5, 2026 16:27
@coderabbitai
Copy link

coderabbitai bot commented Mar 5, 2026

📝 Walkthrough

Walkthrough

Replaces widget-based HTML export with a direct call to exportNetworkToHTML, adds a "Download HTML" UI button and server-side downloadHandler (export_network_html), updates the UI helper to createDownloadBoxes, and adds tests for HTML export success and NULL-render error.

Changes

Cohort / File(s) Summary
Network UI Module
R/module-visualize-network-ui.R
Renamed createCodeDownloadBox(ns)createDownloadBoxes(ns); updated layout to flexbox and added uiOutput(ns("network.html.button")) alongside code download UI.
Network Server Module & Tests
R/module-visualize-network-server.R, tests/testthat/test_network_visualization.R
Added export_network_html(render_data, displayLabelType, file) and replaced widget-based HTML export with exportNetworkToHTML; implemented downloadHandler network_html_code with error handling and notifications; added tests for successful export and NULL render_data error.

Sequence Diagram(s)

sequenceDiagram
    participant UI
    participant Server
    participant Exporter as exportNetworkToHTML
    participant FS as FileSystem

    UI->>Server: click "Download HTML"
    Server->>Server: validate render_data
    alt render_data NULL
        Server-->>UI: show error notification
    else render_data present
        Server->>Exporter: exportNetworkToHTML(render_data, displayLabelType, tempFile)
        Exporter->>FS: write temp HTML
        Exporter-->>Server: return tempFile path
        Server->>FS: copy tempFile -> userFile
        Server-->>UI: serve download
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested labels

Review effort 3/5

Poem

🐇 I baked some HTML under moonlight glaze,
Buttons in a row, in tidy flexy ways,
exportNetworkToHTML hums a merry tune,
Files hop out ready, served by afternoon,
A little rabbit cheers—download and praise!

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Title check ✅ Passed The title 'feature(network-visualization): Add button to export HTML from Shiny' accurately describes the main change: adding an HTML export button feature to the network visualization module.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature-export-html

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@R/module-visualize-network-server.R`:
- Around line 627-638: tmp_file is not unique (uses Sys.Date()) and file.copy
result is unchecked; change tmp_file creation to use a unique temp file (e.g.,
tempfile with pattern and .html extension) so concurrent downloads won't
collide, ensure exportNetworkToHTML writes to that tmp_file, then check the
result of file.exists(tmp_file) and the boolean returned by file.copy(tmp_file,
file) and fail fast (stop or throw) with a clear error if either check indicates
the export or copy failed.
- Around line 629-635: The unqualified call to exportNetworkToHTML will fail
because MSstatsBioNet is in Imports and exportNetworkToHTML isn’t imported;
change the call to use the namespace qualifier
MSstatsBioNet::exportNetworkToHTML (update the call where exportNetworkToHTML is
invoked with nodes = render_data$nodes_table, edges = render_data$edges_table,
nodeFontSize = 12, displayLabelType = input$displayLabelType, filename =
tmp_file), and also update the equivalent generated code string earlier (the
codes string around line 544) to use MSstatsBioNet::exportNetworkToHTML so both
runtime and generated code reference the fully qualified function name.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 67cc42bc-4f5f-4538-89e0-0d5158fa6d29

📥 Commits

Reviewing files that changed from the base of the PR and between ee4b299 and 270031f.

📒 Files selected for processing (2)
  • R/module-visualize-network-server.R
  • R/module-visualize-network-ui.R

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (2)
R/module-visualize-network-server.R (2)

236-242: ⚠️ Potential issue | 🔴 Critical

Use MSstatsBioNet::exportNetworkToHTML explicitly at call sites.

The direct call on Line 236 (and generated call on Line 562) should be namespace-qualified to prevent runtime lookup issues when the symbol is not imported into the package namespace.

#!/bin/bash
# Verify whether exportNetworkToHTML is imported and where it is called unqualified.
set -euo pipefail

echo "== NAMESPACE imports for MSstatsBioNet =="
rg -n 'importFrom\(MSstatsBioNet|import\(MSstatsBioNet\)|exportNetworkToHTML' NAMESPACE -C2 || true

echo
echo "== Roxygen importFrom in server module =="
rg -n '@importFrom MSstatsBioNet' R/module-visualize-network-server.R -C1 || true

echo
echo "== Unqualified call sites =="
rg -nP '\bexportNetworkToHTML\s*\(' R/module-visualize-network-server.R -C2 || true
Proposed fix
-  exportNetworkToHTML(
+  MSstatsBioNet::exportNetworkToHTML(
     nodes            = render_data$nodes_table,
     edges            = render_data$edges_table,
     nodeFontSize     = 12,
     displayLabelType = displayLabelType,
     filename         = tmp_file
   )
-    codes <- paste(codes, "exportNetworkToHTML(subnetwork$nodes, subnetwork$edges, displayLabelType=", displayLabelTypeStr, ")\n", sep = "")
+    codes <- paste(codes, "MSstatsBioNet::exportNetworkToHTML(subnetwork$nodes, subnetwork$edges, displayLabelType=", displayLabelTypeStr, ")\n", sep = "")

Also applies to: 562-562

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@R/module-visualize-network-server.R` around lines 236 - 242, The call to
exportNetworkToHTML should be namespace-qualified to avoid runtime lookup
failures; replace unqualified calls like exportNetworkToHTML(...) with
MSstatsBioNet::exportNetworkToHTML(...) at all call sites (e.g., in the block
using render_data$nodes_table and render_data$edges_table and the other
generated call around the symbol noted later), ensuring you update every
occurrence so the function is resolved from the MSstatsBioNet namespace.

234-245: ⚠️ Potential issue | 🟠 Major

Avoid date-based temp filenames and fail fast on copy/export failures.

Line 234 can collide across concurrent downloads, and Line 244 ignores copy failure. This can silently return bad downloads.

Proposed fix
-  tmp_file <- file.path(tempdir(), paste0("network-", Sys.Date(), ".html"))
+  tmp_file <- tempfile(pattern = "network-", fileext = ".html")

   exportNetworkToHTML(
     nodes            = render_data$nodes_table,
     edges            = render_data$edges_table,
     nodeFontSize     = 12,
     displayLabelType = displayLabelType,
     filename         = tmp_file
   )
-  
-  file.copy(tmp_file, file)
+
+  if (!file.exists(tmp_file)) {
+    stop("Failed to generate HTML export file.")
+  }
+  copied <- file.copy(tmp_file, file, overwrite = TRUE)
+  if (!copied) {
+    stop("Failed to prepare HTML download file.")
+  }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@R/module-visualize-network-server.R` around lines 234 - 245, The temp
filename uses a date-based name (tmp_file) which can collide in concurrent
downloads and the code ignores failures from exportNetworkToHTML and file.copy;
replace the date-based tmp_file with a unique tempfile() name, ensure
exportNetworkToHTML errors are propagated or its return is checked, and check
the boolean result of file.copy (or capture exceptions) and stop()/throw an
error on failure so the download fails fast; refer to tmp_file,
exportNetworkToHTML, and file.copy to locate the changes.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@R/module-visualize-network-server.R`:
- Around line 639-644: The downloadHandler content currently swallows errors by
only calling showNotification in the error handler, so failing exports can
produce empty/broken files; update the tryCatch around networkVisualization() /
export_network_html(...) inside the downloadHandler content function to rethrow
the error after calling showNotification (e.g., call stop(e) or rethrow the
original error) so the download is aborted and the error propagates to the
caller; keep showNotification(e$message, type="error") for user feedback and
then rethrow the same error.

---

Duplicate comments:
In `@R/module-visualize-network-server.R`:
- Around line 236-242: The call to exportNetworkToHTML should be
namespace-qualified to avoid runtime lookup failures; replace unqualified calls
like exportNetworkToHTML(...) with MSstatsBioNet::exportNetworkToHTML(...) at
all call sites (e.g., in the block using render_data$nodes_table and
render_data$edges_table and the other generated call around the symbol noted
later), ensuring you update every occurrence so the function is resolved from
the MSstatsBioNet namespace.
- Around line 234-245: The temp filename uses a date-based name (tmp_file) which
can collide in concurrent downloads and the code ignores failures from
exportNetworkToHTML and file.copy; replace the date-based tmp_file with a unique
tempfile() name, ensure exportNetworkToHTML errors are propagated or its return
is checked, and check the boolean result of file.copy (or capture exceptions)
and stop()/throw an error on failure so the download fails fast; refer to
tmp_file, exportNetworkToHTML, and file.copy to locate the changes.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: bd1cee16-c0e0-4c25-862d-0173f5b8ab9d

📥 Commits

Reviewing files that changed from the base of the PR and between 270031f and a909031.

📒 Files selected for processing (2)
  • R/module-visualize-network-server.R
  • tests/testthat/test_network_visualization.R

@tonywu1999 tonywu1999 changed the title Feature export html feature(network-visualization): Add button to export HTML from Shiny Mar 5, 2026
@tonywu1999 tonywu1999 merged commit 520b3e4 into devel Mar 5, 2026
1 check passed
@tonywu1999 tonywu1999 deleted the feature-export-html branch March 5, 2026 19:22
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.

1 participant