feat: toggles for binary labels in report#3296
Conversation
📝 WalkthroughWalkthroughThis pull request introduces new functionality to support dynamic toggle controls in the results reporting component. Key modifications include the addition of a new Changes
Possibly related PRs
📜 Recent review detailsConfiguration used: CodeRabbit UI 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
⏰ Context from checks skipped due to timeout of 90000ms (30)
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (6)
snakemake/report/html_reporter/template/components/abstract_results.js (6)
1-3: Consider renaming or documentingarrayKeyfor clarity
This utility function is straightforward, but calling itarrayKeymay not fully convey its role in creating a unique identifier from label arrays. Consider adding a short docstring or a more descriptive name for easier comprehension.
38-53: Add a unique key for each toggle control
When mapping overtoggleLabels.entries(), each returned element should have a stablekeyprop to avoid React’s "missing key" warnings.return toggleLabels.entries().map(function(entry) { let [name, values] = entry; return e( Toggle, + { key: name, label: name, values: values, callback: function(selected) { ... } } ); });
55-62: Optimize setState usage
Assigningdatafromthis.state.dataagain during every toggle may be redundant ifdatadoes not change. You can omit re-storingdataor store it outside state to reduce unnecessary re-renders.toggleCallback(name, selected) { let data = this.state.data; this.setState(prevState => { let toggles = new Map(prevState.toggles); toggles.set(name, selected); - return { data: data, toggles }; + return { toggles }; }); }
115-192: Consider optimizing the toggle detection loop for large data
Multiplefiltercalls on potentially large arrays can degrade performance. A single pass counting approach can be more efficient. Also consider short-circuiting ifresultsis empty.
200-216: Add unique keys for rendered headers
When mapping overdata.entryLabelsto create<th>elements, each should have akeyprop to avoid React warnings about missing keys.data.entryLabels.map(function (label) { return e( "th", + { key: label, className: "text-left p-1 uppercase" }, label ) })
218-273: Remove or guard the console.log calls
Repeated console logging inrenderEntriescan clutter production console output. Either remove these statements or wrap them in a development-check condition to keep logs out of production.console.log({ - toggleLabels, - entryPath, - entryLabels, });
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
snakemake/report/html_reporter/template/components/abstract_results.js(4 hunks)snakemake/report/html_reporter/template/components/result_view_button.js(0 hunks)snakemake/report/html_reporter/template/components/toggle.js(1 hunks)snakemake/report/html_reporter/template/index.html.jinja2(1 hunks)
💤 Files with no reviewable changes (1)
- snakemake/report/html_reporter/template/components/result_view_button.js
⏰ Context from checks skipped due to timeout of 90000ms (30)
- GitHub Check: testing (10, 3.12)
- GitHub Check: testing (10, 3.11)
- GitHub Check: testing (9, 3.12)
- GitHub Check: testing (9, 3.11)
- GitHub Check: testing (8, 3.12)
- GitHub Check: testing (8, 3.11)
- GitHub Check: testing (7, 3.12)
- GitHub Check: testing (7, 3.11)
- GitHub Check: testing (6, 3.12)
- GitHub Check: testing (6, 3.11)
- GitHub Check: testing (5, 3.12)
- GitHub Check: testing-windows (10)
- GitHub Check: testing (5, 3.11)
- GitHub Check: testing-windows (9)
- GitHub Check: testing (4, 3.12)
- GitHub Check: testing-windows (8)
- GitHub Check: testing (4, 3.11)
- GitHub Check: testing-windows (7)
- GitHub Check: testing (3, 3.12)
- GitHub Check: testing-windows (6)
- GitHub Check: testing (3, 3.11)
- GitHub Check: testing-windows (5)
- GitHub Check: testing (2, 3.12)
- GitHub Check: testing-windows (4)
- GitHub Check: testing (2, 3.11)
- GitHub Check: testing-windows (3)
- GitHub Check: testing (1, 3.12)
- GitHub Check: testing-windows (2)
- GitHub Check: testing (1, 3.11)
- GitHub Check: testing-windows (1)
🔇 Additional comments (4)
snakemake/report/html_reporter/template/components/abstract_results.js (3)
6-10: EnsuregetData()does not introduce side effects or async calls
Initializing state fromgetData()within the constructor is acceptable for synchronous data. If the data is fetched asynchronously or if side effects occur, consider moving data retrieval into a React lifecycle method likecomponentDidMount.
64-79: Overall table rendering logic looks good
The table structure and composition are consistent. Passingdatato helper methods is clear and maintainable.
194-198:isLabelledapproach confirmed
This concise helper is straightforward and appears correct for checking if every result has labels.snakemake/report/html_reporter/template/index.html.jinja2 (1)
82-82: Script inclusion for toggle component looks correct
Includingcomponents/toggle.jsis consistent and ensures the Toggle is available for the report.
snakemake/report/html_reporter/template/components/abstract_results.js
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (6)
snakemake/report/html_reporter/template/components/abstract_view_manager.js (2)
2-21: Remove unnecessarybreakstatements afterreturn.The
breakstatements afterreturnare unreachable and should be removed.Apply this diff to remove unreachable code:
handleSelectedResult(resultPath) { let entry = results[resultPath]; const mimeType = getResultMimeType(resultPath); switch (mimeType) { case "image/svg+xml": case "image/png": case "image/jpeg": return this.handleImg(entry, resultPath); - break; case "text/html": return this.handleHtml(entry, resultPath); - break; case "application/pdf": return this.handlePdf(entry, resultPath); - break; default: return this.handleDefault(entry, resultPath); } }
23-37: Make abstract methods truly abstract using static error messages.The error messages should indicate that these are abstract methods that must be implemented by subclasses.
Apply this diff to improve error messages:
handleImg(entry, resultPath) { - throw new Error("Unimplemented!"); + throw new Error("Abstract method 'handleImg' must be implemented by subclass"); } handleHtml(entry, resultPath) { - throw new Error("Unimplemented!"); + throw new Error("Abstract method 'handleHtml' must be implemented by subclass"); } handlePdf(entry, resultPath) { - throw new Error("Unimplemented!"); + throw new Error("Abstract method 'handlePdf' must be implemented by subclass"); } handleDefault(entry, resultPath) { - throw new Error("Unimplemented!"); + throw new Error("Abstract method 'handleDefault' must be implemented by subclass"); }snakemake/report/html_reporter/template/components/result_view_button.js (1)
10-62: Reduce code duplication in handler methods.The handler methods share similar prop creation logic with slight variations. Consider extracting common logic into a helper method.
Apply this diff to reduce duplication:
+ createViewProps(content, entry, resultPath) { + let app = this.app; + return { + href: "#", + onClick: function() { + app.setView({ + content: content, + contentPath: entry.data_uri, + resultPath: resultPath + }); + } + }; + } + handleImg(entry, resultPath) { - let app = this.app; - let props = { - href: "#", - onClick: function() { - app.setView({ - content: "img", - contentPath: entry.data_uri, - resultPath: resultPath - }); - } - }; + let props = this.createViewProps("img", entry, resultPath); return this.renderButton(props); } handleHtml(entry, resultPath) { - let app = this.app; - let props = { - href: "#", - onClick: function() { - app.setView({ - content: "html", - contentPath: entry.data_uri, - resultPath: resultPath - }); - } - }; + let props = this.createViewProps("html", entry, resultPath); return this.renderButton(props); } handlePdf(entry, resultPath) { - let app = this.app; - let props = { - href: "#", - onClick: function() { - app.setView({ - content: "pdf", - contentPath: entry.data_uri, - resultPath: resultPath - }); - } - }; + let props = this.createViewProps("pdf", entry, resultPath); return this.renderButton(props); }snakemake/report/html_reporter/template/components/toggle.js (2)
11-16: Remove console.log statement.The console.log statement should be removed from production code.
selectValue(selected) { - // swap the value - console.log(selected); this.setState({ value: selected }); this.props.callback(selected); }
78-110: Remove commented out code.The commented out render2 method should be removed as it's not being used.
snakemake/report/html_reporter/template/components/abstract_results.js (1)
92-107: Optimize state updates and improve readability.The toggleCallback method can be optimized for better readability and performance.
toggleCallback(name, selected) { - let data = this.state.data; - let _this = this; - this.setState(function (prevState) { - let toggles = new Map(prevState.toggles); - toggles.set(name, selected); - return { data: data, toggles }; - }, function () { - if (_this.state.data.resultPathsToEntryLabels.has(_this.props.app.state.resultPath)) { - let toggleLabels = Array.from(data.toggleLabels.keys().map((label) => _this.state.toggles.get(label))); - let entryLabels = _this.state.data.resultPathsToEntryLabels.get(_this.props.app.state.resultPath); - let targetPath = _this.state.data.entries.get(arrayKey(entryLabels)).get(arrayKey(toggleLabels)); - _this.toggleViewManager.handleSelectedResult(targetPath); - } - }); + this.setState( + prevState => { + const toggles = new Map(prevState.toggles); + toggles.set(name, selected); + return { toggles }; + }, + () => { + const { data, toggles } = this.state; + const { resultPath } = this.props.app.state; + + if (data.resultPathsToEntryLabels.has(resultPath)) { + const toggleLabels = Array.from(data.toggleLabels.keys().map(label => toggles.get(label))); + const entryLabels = data.resultPathsToEntryLabels.get(resultPath); + const targetPath = data.entries.get(arrayKey(entryLabels)).get(arrayKey(toggleLabels)); + this.toggleViewManager.handleSelectedResult(targetPath); + } + } + ); }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
docs/snakefiles/images/report-toggles.pngis excluded by!**/*.png
📒 Files selected for processing (8)
docs/snakefiles/reporting.rst(2 hunks)snakemake/assets/__init__.py(1 hunks)snakemake/report/html_reporter/template/components/abstract_results.js(4 hunks)snakemake/report/html_reporter/template/components/abstract_view_manager.js(1 hunks)snakemake/report/html_reporter/template/components/common.js(1 hunks)snakemake/report/html_reporter/template/components/result_view_button.js(1 hunks)snakemake/report/html_reporter/template/components/toggle.js(1 hunks)snakemake/report/html_reporter/template/index.html.jinja2(1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
`**/*.py`: Do not try to improve formatting. Do not suggest ...
**/*.py: Do not try to improve formatting.
Do not suggest type annotations for functions that are defined inside of functions or methods.
Do not suggest type annotation of theselfargument of methods.
Do not suggest type annotation of theclsargument of classmethods.
Do not suggest return type annotation if a function or method does not contain areturnstatement.
snakemake/assets/__init__.py
🔇 Additional comments (6)
snakemake/report/html_reporter/template/components/result_view_button.js (1)
73-81: LGTM! Clean React component implementation.The
ResultViewButtoncomponent follows React best practices:
- Good separation of concerns by delegating to
ButtonViewManager- Proper prop types validation
- Clean and focused render method
snakemake/report/html_reporter/template/index.html.jinja2 (1)
82-83: LGTM! Proper script inclusion.The new scripts are:
- Added in the correct order (before dependent components)
- Follow the same template pattern as other script includes
snakemake/report/html_reporter/template/components/toggle.js (1)
42-42: Use htmlFor instead of for attribute.In React, the label attribute should be
htmlForinstead offor.- {for: valueId(0), className: `${labelClasses} rounded-l`}, + {htmlFor: valueId(0), className: `${labelClasses} rounded-l`}, - {for: valueId(1), className: `${labelClasses} rounded-r`}, + {htmlFor: valueId(1), className: `${labelClasses} rounded-r`},Also applies to: 59-59
snakemake/assets/__init__.py (1)
66-66:Details
❓ Verification inconclusive
Verify Tailwind CSS and plugin versions.
The update includes:
- Tailwind CSS version: 3.4.16
- Forms plugin version: 0.5.9
Let's verify these versions are stable and compatible.
Also applies to: 69-69
🌐 Web query:
What is the latest version of Tailwind CSS and its forms plugin?💡 Result:
Tailwind CSS v4.0 is its latest major release as of February 2025[1][4]. This version introduces significant performance improvements (full builds up to 5x faster, incremental builds 100x faster), modern CSS features like cascade layers and container queries[1][4], and a shift to CSS-first configuration instead of JavaScript[3][4].
For forms styling:
- The @tailwindcss/forms plugin’s latest npm release is v0.5.10[2].
- In Tailwind CSS v4.x projects:
- Plugins are now imported directly into your main CSS file using
@pluginsyntax[3].- Example usage:
This replaces traditional JavaScript-based configuration[3].@import "tailwindcss"; @plugin "@tailwindcss/forms";Key changes impacting forms:
- Automatic content detection removes manual template configuration[1][3]
- Dynamic variants/data attributes allow utilities like
data-checked:*without custom config[1][4]form-input,form-checkbox, etc., classes remain supported viastrategy: 'class'[2][8]For new projects:
npm install tailwindcss@latestCitations:
- 1: https://github.com/tailwindlabs/tailwindcss/releases
- 2: https://www.npmjs.com/package/@tailwindcss/forms/v/0.3.4
- 3: https://dev.to/sirneij/tailwindcss-v40-upgrading-from-v3-with-some-plugins-572f
- 4: https://tailwindcss.com/blog/tailwindcss-v4
- 5: https://tailwindcss.com/docs/upgrading-to-v2
- 6: https://github.com/tailwindlabs/tailwindcss/blob/main/CHANGELOG.md
- 7: https://www.youtube.com/watch?v=E0ToV_7qj20
- 8: https://github.com/tailwindlabs/tailwindcss-forms
- 9: https://www.npmjs.com/package/eslint-plugin-tailwindcss
- 10: https://www.youtube.com/watch?v=sHnG8tIYMB4
Tailwind CSS and Plugin Version Compatibility Check
The current CDN URL in
snakemake/assets/__init__.py(lines 66 and 69) uses version placeholders that are tied to an older release—specifically, Tailwind CSS is presently set to 3.4.16 and the forms plugin to 0.5.9. However, as of February 2025, Tailwind CSS v4.0 is available and the latest release of the @tailwindcss/forms plugin is v0.5.10. Additionally, Tailwind CSS v4.0 now favors a CSS-first configuration for plugins (using@pluginimports in your CSS) over the older JavaScript configuration via URL query parameters.Please verify whether:
- You intend to lock the project to Tailwind CSS 3.4.16 and forms plugin 0.5.9, or if an upgrade to Tailwind CSS v4.0 (and correspondingly updating the forms plugin to 0.5.10) is desired.
- The current CDN-based plugin configuration still meets your project requirements or if switching to the new CSS-based plugin import is needed.
snakemake/report/html_reporter/template/components/abstract_results.js (1)
5-38: LGTM! Well-structured view manager.The ToggleViewManager class is well-organized with clear separation of concerns for different content types.
docs/snakefiles/reporting.rst (1)
99-131: LGTM! Clear and comprehensive documentation.The documentation effectively explains:
- The purpose and benefits of using labels
- How to implement toggles for binary labels
- Visual example with the toggle switch image
The changes are well-structured and provide clear guidance for users.
| function getResultMimeType(resultPath) { | ||
| return results[resultPath].mime_type |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Add error handling for missing paths and mime types.
The function should handle cases where resultPath is not found in results or mime_type is undefined.
Apply this diff to add error handling:
function getResultMimeType(resultPath) {
- return results[resultPath].mime_type
+ if (!(resultPath in results)) {
+ throw new Error(`Result path '${resultPath}' not found`);
+ }
+ const result = results[resultPath];
+ if (!result.mime_type) {
+ throw new Error(`No mime_type found for result '${resultPath}'`);
+ }
+ return result.mime_type;
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| function getResultMimeType(resultPath) { | |
| return results[resultPath].mime_type | |
| function getResultMimeType(resultPath) { | |
| if (!(resultPath in results)) { | |
| throw new Error(`Result path '${resultPath}' not found`); | |
| } | |
| const result = results[resultPath]; | |
| if (!result.mime_type) { | |
| throw new Error(`No mime_type found for result '${resultPath}'`); | |
| } | |
| return result.mime_type; | |
| } |
| class Toggle extends React.Component { | ||
| constructor(props) { | ||
| super(props); | ||
| this.state = { value: this.props.values[0] }; | ||
| this.selectValue = this.selectValue.bind(this); | ||
|
|
||
| } |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Add PropTypes validation and handle potential empty values.
The component should validate its props and handle cases where values array might be empty.
Add PropTypes validation:
Toggle.propTypes = {
label: PropTypes.string.isRequired,
values: PropTypes.arrayOf(PropTypes.string).isRequired,
callback: PropTypes.func.isRequired,
};Add defensive check in constructor:
constructor(props) {
super(props);
+ if (!props.values || props.values.length === 0) {
+ throw new Error('Toggle component requires non-empty values array');
+ }
this.state = { value: this.props.values[0] };
this.selectValue = this.selectValue.bind(this);
}| AbstractResults.propTypes = { | ||
| app: PropTypes.object.isRequired, | ||
| }; | ||
|
|
There was a problem hiding this comment.
Move PropTypes outside of render method.
PropTypes should be defined at the class level, not inside the render method.
- renderEntries(data) {
- AbstractResults.propTypes = {
- app: PropTypes.object.isRequired,
- };
+ static propTypes = {
+ app: PropTypes.object.isRequired,
+ };
+
+ renderEntries(data) {📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| AbstractResults.propTypes = { | |
| app: PropTypes.object.isRequired, | |
| }; | |
| class AbstractResults extends React.Component { | |
| static propTypes = { | |
| app: PropTypes.object.isRequired, | |
| }; | |
| renderEntries(data) { | |
| // ... rest of the renderEntries implementation | |
| } | |
| // ... other methods and component code | |
| } |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
snakemake/report/html_reporter/template/components/abstract_view_manager.js (2)
1-1: Enforce abstract class behavior.Since this is an abstract class, consider adding a constructor that prevents direct instantiation:
class AbstractViewManager { + constructor() { + if (this.constructor === AbstractViewManager) { + throw new Error('Abstract class "AbstractViewManager" cannot be instantiated directly.'); + } + }
20-34: Add JSDoc documentation and improve error messages.The handler methods need documentation to guide implementers and more descriptive error messages.
+ /** + * Handles image type results (svg, png, jpeg) + * @param {Object} entry - The result entry + * @param {string} resultPath - Path to the result + * @returns {void} + * @abstract + */ handleImg(entry, resultPath) { - throw new Error("Unimplemented!"); + throw new Error("AbstractViewManager.handleImg() must be implemented by subclass"); } + /** + * Handles HTML type results + * @param {Object} entry - The result entry + * @param {string} resultPath - Path to the result + * @returns {void} + * @abstract + */ handleHtml(entry, resultPath) { - throw new Error("Unimplemented!"); + throw new Error("AbstractViewManager.handleHtml() must be implemented by subclass"); } + /** + * Handles PDF type results + * @param {Object} entry - The result entry + * @param {string} resultPath - Path to the result + * @returns {void} + * @abstract + */ handlePdf(entry, resultPath) { - throw new Error("Unimplemented!"); + throw new Error("AbstractViewManager.handlePdf() must be implemented by subclass"); } + /** + * Handles results with unsupported MIME types + * @param {Object} entry - The result entry + * @param {string} resultPath - Path to the result + * @returns {void} + * @abstract + */ handleDefault(entry, resultPath) { - throw new Error("Unimplemented!"); + throw new Error("AbstractViewManager.handleDefault() must be implemented by subclass"); }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
snakemake/report/html_reporter/template/components/abstract_view_manager.js(1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (5)
- GitHub Check: testing-windows (10)
- GitHub Check: testing-windows (9)
- GitHub Check: testing-windows (8)
- GitHub Check: testing-windows (7)
- GitHub Check: testing-windows (3)
snakemake/report/html_reporter/template/components/abstract_view_manager.js
Show resolved
Hide resolved
|
🤖 I have created a release *beep* *boop* --- ## [8.29.0](v8.28.0...v8.29.0) (2025-02-27) ### Features * provide mechanism to link between report items (snakemake.report_href, see docs) ([#3224](#3224)) ([a024e60](a024e60)) * toggles for binary labels in report ([#3296](#3296)) ([7690998](7690998)) ### Bug Fixes * add missing [@conda](https://github.com/conda) annotations ([#3298](#3298)) ([0b541cc](0b541cc)) * properly handle remote storage when waiting for pipes ([#3317](#3317)) ([9f7e092](9f7e092)) * provide proper error messages if output file preparation (pipe, mkdir) fails ([#3309](#3309)) ([77ef176](77ef176)) * record file extension (e.g. .tsv) in between workflow cache records in order to avoid that files of the wrong format are erroneously returned by the cache. This will lead to some cache misses. But avoiding errors induced by the previous behavior of ignoring file extensions when seeking for cache records is more important. ([#3314](#3314)) ([4912f00](4912f00)) * sort results lexicographically by labels in their order of appearance ([#3293](#3293)) ([a19a0ac](a19a0ac)) ### Documentation * update best practices ([7270eb3](7270eb3)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
<!--Add a description of your PR here--> ### QC <!-- Make sure that you can tick the boxes below. --> * [x] The PR contains a test case for the changes or the changes are already covered by an existing test case. * [x] The documentation (`docs/`) is updated to reflect the changes or this is not necessary (e.g. if the change does neither modify the language nor the behavior or functionalities of Snakemake). <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Introduced interactive toggle switches that let users dynamically filter and adjust result displays. - Added a new `Toggle` component for selecting between values using radio buttons. - Enhanced result display management with the `ToggleViewManager` and `ButtonViewManager` classes. - Integrated new JavaScript components into the report's HTML template for improved functionality. - **Bug Fixes** - Updated asset specifications for `tailwindcss` to ensure correct versioning and URL retrieval. - **Documentation** - Enhanced reporting documentation with recommendations for using labels and showcasing toggle switch functionality. - **Refactor** - Optimized the result view button behavior for a more intuitive and consistent user experience. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
🤖 I have created a release *beep* *boop* --- ## [8.29.0](snakemake/snakemake@v8.28.0...v8.29.0) (2025-02-27) ### Features * provide mechanism to link between report items (snakemake.report_href, see docs) ([snakemake#3224](snakemake#3224)) ([a024e60](snakemake@a024e60)) * toggles for binary labels in report ([snakemake#3296](snakemake#3296)) ([7690998](snakemake@7690998)) ### Bug Fixes * add missing [@conda](https://github.com/conda) annotations ([snakemake#3298](snakemake#3298)) ([0b541cc](snakemake@0b541cc)) * properly handle remote storage when waiting for pipes ([snakemake#3317](snakemake#3317)) ([9f7e092](snakemake@9f7e092)) * provide proper error messages if output file preparation (pipe, mkdir) fails ([snakemake#3309](snakemake#3309)) ([77ef176](snakemake@77ef176)) * record file extension (e.g. .tsv) in between workflow cache records in order to avoid that files of the wrong format are erroneously returned by the cache. This will lead to some cache misses. But avoiding errors induced by the previous behavior of ignoring file extensions when seeking for cache records is more important. ([snakemake#3314](snakemake#3314)) ([4912f00](snakemake@4912f00)) * sort results lexicographically by labels in their order of appearance ([snakemake#3293](snakemake#3293)) ([a19a0ac](snakemake@a19a0ac)) ### Documentation * update best practices ([7270eb3](snakemake@7270eb3)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>



QC
docs/) is updated to reflect the changes or this is not necessary (e.g. if the change does neither modify the language nor the behavior or functionalities of Snakemake).Summary by CodeRabbit
New Features
Togglecomponent for selecting between values using radio buttons.ToggleViewManagerandButtonViewManagerclasses.Bug Fixes
tailwindcssto ensure correct versioning and URL retrieval.Documentation
Refactor