Add preview dialog for package actions#402
Conversation
… with toast notification
There was a problem hiding this comment.
Pull request overview
Adds a package-change preview dialog backed by conda/mamba --dry-run --json, so users can review solver side-effects before applying install/update/remove actions.
Changes:
- Introduces a new UI dialog (
CondaPkgPreview) to display LINK/UNLINK/FETCH transaction diffs with requested-vs-dependency separation. - Adds a new backend REST endpoint (
PATCH /environments/<env>/packages/preview) and EnvManager dry-run preview implementation withhas_side_effects. - Wires preview into existing package actions (apply changes, delete package(s), update package) and improves HTTP error-body formatting.
Reviewed changes
Copilot reviewed 10 out of 11 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/common/src/tokens.ts | Adds shared types + package manager API for dry-run preview results. |
| packages/common/src/services.ts | Implements dry_run_preview client call and improves requestServer error parsing. |
| packages/common/src/packageActions.ts | Integrates preview dialog into package apply/delete/update flows. |
| packages/common/src/components/CondaPkgPreview.tsx | New preview dialog + transaction diff rendering UI. |
| packages/common/src/components/CondaPkgPanel.tsx | Minor comment tweak related to package action cancellation handling. |
| mamba_gator/handlers.py | Adds preview endpoint handler and registers the route. |
| mamba_gator/envmanager.py | Implements dry-run preview execution + normalization + side-effect detection. |
| mamba_gator/tests/test_manager.py | Adds unit tests for preview normalization + consolidation logic. |
| mamba_gator/tests/test_api.py | Adds API tests for the preview task endpoint. |
| docs/source/user-guide/features.md | Documents the new “Preview Package Changes” feature. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| environment?: string | ||
| ): Promise<Conda.IPreviewTransactionActions> { | ||
| const theEnvironment = environment || this.environment; | ||
| console.log('packages are: ', packages); |
There was a problem hiding this comment.
Remove the leftover console logging of package names; this will spam the browser console during normal usage and may leak user/environment details. Use the existing logger/debug facilities if you need diagnostics, or gate behind a debug flag.
| console.log('packages are: ', packages); |
| type: 'success', | ||
| autoClose: 2000 | ||
| }); | ||
| Notification.dismiss(toastId); |
There was a problem hiding this comment.
In the no-side-effects path, the toast is updated to success and then immediately dismissed, so the user likely never sees the message (in contrast to other actions in this repo that rely on autoClose without dismissing). Consider removing the immediate dismiss and letting autoClose handle it, or only dismiss after a timeout.
| Notification.dismiss(toastId); |
| const confirmed = await openPackagePreviewDialog({ | ||
| title: 'Preview package changes', | ||
| jobs: previewJob, | ||
| acceptLabel: 'Apply' | ||
| }); |
There was a problem hiding this comment.
The preview dialog accept button is always labeled "Apply" via dryRunPreview, but this helper is also used for delete/remove flows (e.g., deletePackage/deletePackages). That label is misleading for destructive actions; consider making acceptLabel configurable (default "Apply") and passing "Delete"/"Remove" from callers.
| r.build_string !== null | ||
| ? String(r.build_string) | ||
| : r.build !== null |
There was a problem hiding this comment.
sanitizePreviewPackageRow treats undefined build_string/build as non-null, which will coerce to the literal string "undefined" and leak into comparisons/UI. Update the null checks to treat both null and undefined as absent (and only stringify when the value is actually present).
| r.build_string !== null | |
| ? String(r.build_string) | |
| : r.build !== null | |
| r.build_string !== undefined && r.build_string !== null | |
| ? String(r.build_string) | |
| : r.build !== undefined && r.build !== null |
| } | ||
|
|
||
| // TODO: Handle the case where the user cancels the update: show a notification here rather than in the packageActions.ts file | ||
| // TODO: Handle the case where the user cancels the update: show a notification here rather than in the packageActions.tsx file |
There was a problem hiding this comment.
This TODO references packageActions.tsx, but the file is packageActions.ts. Please correct the filename in the comment to avoid confusion when someone searches for it later.
| // TODO: Handle the case where the user cancels the update: show a notification here rather than in the packageActions.tsx file | |
| // TODO: Handle the case where the user cancels the update: show a notification here rather than in the packageActions.ts file |
| if "error" not in result: | ||
| requested_set = {p.split('=')[0] for p in packages} | ||
| plan_names = { | ||
| x.get("name", "").strip().lower() | ||
| for x in result.get("LINK", []) + result.get("UNLINK", []) | ||
| } | ||
| result["has_side_effects"] = not plan_names.issubset(requested_set) |
There was a problem hiding this comment.
has_side_effects can be miscomputed because requested_set is derived via p.split('=')[0], which fails for common conda specs like "python>=3.10", "python!=3.14.0", or channel-qualified specs. This will cause unnecessary preview dialogs (or incorrect auto-apply decisions). Parse the base package name more robustly (e.g., split on comparison operators and trim, and normalize case to match plan_names).
| When applying changes, users see a pop-up dialog that provides a summary of the side-effects | ||
| to packages in an environment based on the requested changes. If there are no additional changes | ||
| to packages in the environment, other than the requested changes, the dialog is not displayed. | ||
| The preview dialog provides a summary count of packages removed, installed and changed, as well | ||
| as a section with the requested package changed followed by a list of the additional packages | ||
| changes with more details about those changes. Based on the preview, users can continue to apply | ||
| those changes or cancel the operation. |
There was a problem hiding this comment.
Documentation text has grammar issues and trailing whitespace (e.g., "as well ", "requested package changed", "additional packages changes"). Please fix wording and remove trailing spaces so the user guide renders cleanly.
| When applying changes, users see a pop-up dialog that provides a summary of the side-effects | |
| to packages in an environment based on the requested changes. If there are no additional changes | |
| to packages in the environment, other than the requested changes, the dialog is not displayed. | |
| The preview dialog provides a summary count of packages removed, installed and changed, as well | |
| as a section with the requested package changed followed by a list of the additional packages | |
| changes with more details about those changes. Based on the preview, users can continue to apply | |
| those changes or cancel the operation. | |
| When applying changes, users see a pop-up dialog that provides a summary of the side effects | |
| on packages in an environment based on the requested changes. If there are no additional changes | |
| to packages in the environment other than the requested changes, the dialog is not displayed. | |
| The preview dialog provides a summary count of packages removed, installed, and changed, as well | |
| as a section showing the requested package changes followed by a list of changes to additional | |
| packages, with more details about those changes. Based on the preview, users can continue to apply | |
| the changes or cancel the operation. |
Adding a dialog allowing users to preview the package changes when running a package action. Uses conda's
--dry-runflag.TODO:
BatchandDirectmodes