Skip to content

Bootstrap upgrade#3264

Merged
ewels merged 111 commits intomainfrom
bootstrap-upgrade
Oct 22, 2025
Merged

Bootstrap upgrade#3264
ewels merged 111 commits intomainfrom
bootstrap-upgrade

Conversation

@ewels
Copy link
Member

@ewels ewels commented Jul 5, 2025

WIP: Updating report front-end

  • Use Vite (with npm) to build + compile CSS / JS
  • Upgrade Bootstrap to latest
  • Try to remove unnecessary JS libraries
  • Add support for report colour themes

Initial attempt in this PR, but still quite a lot left to do. After an initial burst of speed, I'm expecting this PR to take a while.

To-do

I'll try to add to this list as I think of things. From roughly easy to difficult:

  • Fix "scroll to top" button
  • Finish replacing all Glyphicons with material design icons
  • Put the default theme, called "default-old" or something, as escape hatch if there are problems
  • Fix plot Export buttons
  • Check / fix all toolbox functionality
  • Fix styling in toolbar
  • Dark mode Seqera logo (toolbox, footer)
  • Fix mobile left-side nav
  • Fix table-hide expansion (button to show all instead of scroll)
  • Make the main (left) side nav a Bootstrap offcanvas as well?
  • Make plotly themes switch with the report theme switch
  • Heat map legend tick icons need dark mode
  • Conditional formatting colours - make semitransparent?
  • Grouped table samples: chevron
  • Check full-report with all modules to look for for bad hardcoded colours
  • Remove as much custom CSS as possible, use Bootstrap styles
  • Fix up "original" template now that some HTML outside the template changed
  • Clean up AI slop
  • Review all JS
  • Update CSP.txt
  • Bugtest the crap out of it
  • Decide if it should be non-default for a release or two

wontfix - push to another day

  • Include plotly / jQuery etc. into npm build step (instead of keeping in source code)
  • Investigate removing jQuery UI with native JS?
  • Look into removing compiled JS / CSS from source but including it in the PyPI / Conda distros
    • Use nodejs-wheel as an optional dependency to build at run time if dist files aren't found?
  • Consider rewriting JS to drop jQuery
  • Consider setting up a suite of playwright tests for CI

ewels added 28 commits July 3, 2025 14:26
…lute pre-commit

See twbs/bootstrap#40962 - can hopefully remove these again in a future version of Bootstrap
…accessible

The JavaScript bundler (Vite) encapsulates variables in module scope, making them inaccessible to external scripts like module-specific JavaScript files (e.g., multiqc_fastqc.js). This caused 'callAfterDecompressed is not defined' errors.

Fixed by explicitly assigning these variables to the window object:
- window.callAfterDecompressed (used by module JS files to register callbacks)
- window.notEmptyObj (utility function used across modules)
- window.mqc_plots (global plot data accessed by multiple files)

This ensures backward compatibility with module JavaScript files that expect these as global variables.
@ewels ewels linked an issue Jul 5, 2025 that may be closed by this pull request
ewels added 19 commits October 21, 2025 01:15
Resolved merge conflicts in:
- multiqc/modules/fastqc/fastqc.py: Combined status_checks logic from main with bootstrap's series_label
- multiqc/plots/plot.py: Added _get_series_label function from main
- multiqc/plots/violin.py: Used bootstrap's icon and tooltip syntax for warning messages
- multiqc/templates/default/src/js/ai-helpers.js: Combined reasoning model functions from main with bootstrap's window scope
- multiqc/templates/default/src/js/plots/box.js: Combined BoxPlot class with sorting event listeners
- multiqc/templates/default/toolbox.html: Kept bootstrap's modular template includes structure
@ewels ewels marked this pull request as ready for review October 22, 2025 09:22
@ewels ewels removed the WIP Work in progress label Oct 22, 2025
@ewels
Copy link
Member Author

ewels commented Oct 22, 2025

@multiqc-bot fix linting

@ewels ewels merged commit 22d2199 into main Oct 22, 2025
14 checks passed
@ewels ewels deleted the bootstrap-upgrade branch October 22, 2025 17:51
@claude
Copy link

claude bot commented Oct 22, 2025

PR Review: Bootstrap Upgrade

I've completed a comprehensive review of this PR. Overall, this is a high-quality modernization effort with good architectural decisions.

Strengths

Code Quality & Best Practices:

  • Excellent documentation for new features (status bars, Material Design Icons)
  • Proper use of type hints throughout
  • Modern Python 3.9+ standards with f-strings
  • Clean separation with status bar logic in private methods

Architecture:

  • Vite integration is solid for modern JS/CSS bundling
  • Material Design Icons properly shared via template functions
  • Configuration flexibility for status bars (global/per-module/section)
  • Backwards compatible with opt-in features

Security Concerns

CRITICAL: Potential XSS vulnerability (multiqc/base_module.py:574-611)

The _generate_status_bar_html method generates HTML with unescaped user data:

Issues:

  1. self.anchor and section_anchor are not HTML-escaped before injection
  2. Template renders with {{ s['status_bar_html'] }} which disables Jinja2 autoescape

Risk: Malicious input in anchors could lead to XSS.

Recommendation: Use html.escape() on all anchor values before injecting into HTML.

Potential Bugs

  1. Pre-commit hook (scripts/build-assets.sh): No error handling if cd or npm run build fails
  2. Material icon caching: Unbounded cache growth (minor, should be fine in practice)

Performance

Positive:

  • SVG icon caching is excellent
  • JSON serialization is efficient
  • O(1) complexity for progress bar generation

Test Coverage

Concerns:

  • No new tests for status bar functionality
  • No tests for _generate_status_bar_html() XSS protection
  • No tests for Material Design Icons utility

Recommendation: Add unit tests for base_module.py:518-611

Recommendations Summary

Must Fix (Security):

  1. Escape HTML in _generate_status_bar_html() to prevent XSS
  2. Consider enabling Jinja2 autoescape globally

Should Fix:
3. Add error handling to scripts/build-assets.sh
4. Add unit tests for new functionality

Nice to Have:
5. Use Jinja2 templates for HTML generation instead of f-strings
6. Document security model for HTML injection

Conclusion

This is a well-architected PR that successfully modernizes the MultiQC frontend. Code quality is high and documentation is excellent. Main concern is the potential XSS vulnerability which should be addressed before merging.

Overall Rating: 4/5 stars - Would be 5/5 with XSS fix and better test coverage.

Great work on this modernization effort!

@ewels ewels added this to the v1.32 milestone Oct 25, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Update template to latest Bootstrap (with dark mode)

3 participants