feat(admin): add bulk delete for packages
All checks were successful
Build and Release / Unit Tests (push) Successful in 3m32s
Build and Release / Create Release (push) Successful in 0s
Build and Release / Integration Tests (PostgreSQL) (push) Successful in 4m50s
Build and Release / Lint (push) Successful in 4m55s
Build and Release / Build Binaries (amd64, linux, linux-latest) (push) Successful in 3m5s
Build and Release / Build Binaries (amd64, darwin, macos) (push) Successful in 5m32s
Build and Release / Build Binaries (amd64, windows, windows-latest) (push) Successful in 8h4m55s
Build and Release / Build Binaries (arm64, darwin, macos) (push) Successful in 5m23s
Build and Release / Build Binary (linux/arm64) (push) Successful in 8m23s
All checks were successful
Build and Release / Unit Tests (push) Successful in 3m32s
Build and Release / Create Release (push) Successful in 0s
Build and Release / Integration Tests (PostgreSQL) (push) Successful in 4m50s
Build and Release / Lint (push) Successful in 4m55s
Build and Release / Build Binaries (amd64, linux, linux-latest) (push) Successful in 3m5s
Build and Release / Build Binaries (amd64, darwin, macos) (push) Successful in 5m32s
Build and Release / Build Binaries (amd64, windows, windows-latest) (push) Successful in 8h4m55s
Build and Release / Build Binaries (arm64, darwin, macos) (push) Successful in 5m23s
Build and Release / Build Binary (linux/arm64) (push) Successful in 8m23s
Adds bulk delete functionality to admin packages page, allowing deletion of multiple packages and all their versions at once. Includes confirmation dialog, success/warning flash messages showing count of deleted packages and versions, and proper error handling. Adds new locale strings for delete action, confirmation prompt, and result messages.
This commit is contained in:
@@ -3329,6 +3329,10 @@
|
||||
"admin.packages.visibility": "Visibility",
|
||||
"admin.packages.visibility.private": "Private",
|
||||
"admin.packages.visibility.public": "Public",
|
||||
"admin.packages.bulk.delete": "Delete Selected",
|
||||
"admin.packages.bulk.delete.confirm": "Are you sure you want to delete the selected packages and all their versions? This action cannot be undone.",
|
||||
"admin.packages.bulk.delete.success": "Deleted %d package(s) with %d version(s)",
|
||||
"admin.packages.bulk.delete.none": "No packages were deleted",
|
||||
"admin.packages.automatch.button": "Find matching repository",
|
||||
"admin.packages.automatch.match": "Match",
|
||||
"admin.packages.automatch.success": "Package linked to matching repository",
|
||||
|
||||
@@ -81,6 +81,57 @@ func Packages(ctx *context.Context) {
|
||||
ctx.HTML(http.StatusOK, tplPackagesList)
|
||||
}
|
||||
|
||||
// BulkDeletePackages deletes all versions of selected packages
|
||||
func BulkDeletePackages(ctx *context.Context) {
|
||||
packageIDs := ctx.FormStrings("ids[]")
|
||||
|
||||
ids := make([]int64, 0, len(packageIDs))
|
||||
for _, idStr := range packageIDs {
|
||||
var id int64
|
||||
if _, err := fmt.Sscanf(idStr, "%d", &id); err == nil && id > 0 {
|
||||
ids = append(ids, id)
|
||||
}
|
||||
}
|
||||
|
||||
if len(ids) == 0 {
|
||||
ctx.Flash.Error(ctx.Tr("admin.packages.bulk.no_selection"))
|
||||
ctx.JSONRedirect(setting.AppSubURL + "/-/admin/packages")
|
||||
return
|
||||
}
|
||||
|
||||
deletedVersions := 0
|
||||
deletedPackages := 0
|
||||
|
||||
for _, packageID := range ids {
|
||||
// Get all versions of this package
|
||||
versions, _, err := packages_model.SearchVersions(ctx, &packages_model.PackageSearchOptions{
|
||||
PackageID: packageID,
|
||||
})
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
packageDeleted := false
|
||||
for _, pv := range versions {
|
||||
if err := packages_service.RemovePackageVersion(ctx, ctx.Doer, pv); err == nil {
|
||||
deletedVersions++
|
||||
packageDeleted = true
|
||||
}
|
||||
}
|
||||
if packageDeleted {
|
||||
deletedPackages++
|
||||
}
|
||||
}
|
||||
|
||||
if deletedPackages > 0 {
|
||||
ctx.Flash.Success(ctx.Tr("admin.packages.bulk.delete.success", deletedPackages, deletedVersions))
|
||||
} else {
|
||||
ctx.Flash.Warning(ctx.Tr("admin.packages.bulk.delete.none"))
|
||||
}
|
||||
|
||||
ctx.JSONRedirect(setting.AppSubURL + "/-/admin/packages")
|
||||
}
|
||||
|
||||
// DeletePackageVersion deletes a package version
|
||||
func DeletePackageVersion(ctx *context.Context) {
|
||||
pv, err := packages_model.GetVersionByID(ctx, ctx.FormInt64("id"))
|
||||
|
||||
@@ -852,6 +852,7 @@ func registerWebRoutes(m *web.Router) {
|
||||
m.Post("/cleanup", admin.CleanupExpiredData)
|
||||
m.Post("/bulk-global", admin.BulkSetGlobal)
|
||||
m.Post("/bulk-private", admin.BulkSetPrivate)
|
||||
m.Post("/bulk-delete", admin.BulkDeletePackages)
|
||||
m.Post("/bulk-automatch", admin.BulkAutoMatch)
|
||||
m.Post("/automatch", admin.SingleAutoMatch)
|
||||
}, packagesEnabled)
|
||||
|
||||
@@ -38,6 +38,8 @@
|
||||
<div class="item" data-action="make-public">{{svg "octicon-eye" 14}} {{ctx.Locale.Tr "admin.packages.bulk.make_public"}}</div>
|
||||
<div class="divider"></div>
|
||||
<div class="item" data-action="automatch">{{svg "octicon-link" 14}} {{ctx.Locale.Tr "admin.packages.bulk.automatch"}}</div>
|
||||
<div class="divider"></div>
|
||||
<div class="item text red" data-action="delete">{{svg "octicon-trash" 14}} {{ctx.Locale.Tr "admin.packages.bulk.delete"}}</div>
|
||||
</div>
|
||||
</div>
|
||||
<span class="tw-text-text-light-2 tw-self-center" id="selected-count"></span>
|
||||
@@ -199,6 +201,12 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
case 'automatch':
|
||||
url = '{{AppSubUrl}}/-/admin/packages/bulk-automatch';
|
||||
break;
|
||||
case 'delete':
|
||||
if (!confirm('{{ctx.Locale.Tr "admin.packages.bulk.delete.confirm"}}')) {
|
||||
return;
|
||||
}
|
||||
url = '{{AppSubUrl}}/-/admin/packages/bulk-delete';
|
||||
break;
|
||||
}
|
||||
|
||||
fetch(url, {
|
||||
|
||||
Reference in New Issue
Block a user