-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
fix: resolve incorrect endpoints for database bulk actions (#1626) #1629
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
) Update bulk action endpoints for database services: - Use `/api/trpc/redis.start` and `/api/trpc/redis.stop` for Redis - Use `/api/trpc/postgres.start` and `/api/trpc/postgres.stop` for PostgreSQL - Retain `/api/trpc/compose.start` and `/api/trpc/compose.stop` for Docker Compose services Tested with a project including Gitea, Redis, and PostgreSQL. Bulk start/stop operations now function correctly for all service types. Closes Dokploy#1626
|
Hey @krokodaws please check this too krokodaws#1 I have refactored code to make it simpler. It's a staggered PR so needed to merge krokodaws#1 into #1629 |
| const handleBulkAction = async ( | ||
| action: "start" | "stop" | "move" | "delete", | ||
| extraParams: { targetProjectId?: string } = {}, | ||
| ) => { | ||
| let success = 0; | ||
| setIsBulkActionLoading(true); | ||
| for (const serviceId of selectedServices) { | ||
| try { | ||
| await composeActions.start.mutateAsync({ composeId: serviceId }); | ||
| success++; | ||
| } catch (_error) { | ||
| toast.error(`Error starting service ${serviceId}`); | ||
| } | ||
| } | ||
| if (success > 0) { | ||
| toast.success(`${success} services started successfully`); | ||
| refetch(); | ||
| } | ||
| setIsBulkActionLoading(false); | ||
| setSelectedServices([]); | ||
| setIsDropdownOpen(false); | ||
| }; | ||
|
|
||
| const handleBulkStop = async () => { | ||
| let success = 0; | ||
| setIsBulkActionLoading(true); | ||
| for (const serviceId of selectedServices) { | ||
| try { | ||
| await composeActions.stop.mutateAsync({ composeId: serviceId }); | ||
| success++; | ||
| } catch (_error) { | ||
| toast.error(`Error stopping service ${serviceId}`); | ||
| } | ||
| } | ||
| if (success > 0) { | ||
| toast.success(`${success} services stopped successfully`); | ||
| refetch(); | ||
| } | ||
| setSelectedServices([]); | ||
| setIsDropdownOpen(false); | ||
| setIsBulkActionLoading(false); | ||
| }; | ||
| const service = filteredServices.find((s) => s.id === serviceId); | ||
| if (!service) continue; | ||
|
|
||
| const handleBulkMove = async () => { | ||
| if (!selectedTargetProject) { | ||
| toast.error("Please select a target project"); | ||
| return; | ||
| } | ||
| const actions = | ||
| serviceActionsMap[service.type as keyof typeof serviceActionsMap]; | ||
| const mutation = actions?.[action]; | ||
|
|
||
| if (!mutation) continue; | ||
|
|
||
| let success = 0; | ||
| setIsBulkActionLoading(true); | ||
| for (const serviceId of selectedServices) { | ||
| try { | ||
| const service = filteredServices.find((s) => s.id === serviceId); | ||
| if (!service) continue; | ||
| const payload: Record<string, any> = { | ||
| [`${service.type}Id`]: serviceId, | ||
| }; | ||
|
|
||
| switch (service.type) { | ||
| case "application": | ||
| await applicationActions.move.mutateAsync({ | ||
| applicationId: serviceId, | ||
| targetProjectId: selectedTargetProject, | ||
| }); | ||
| break; | ||
| case "compose": | ||
| await composeActions.move.mutateAsync({ | ||
| composeId: serviceId, | ||
| targetProjectId: selectedTargetProject, | ||
| }); | ||
| break; | ||
| case "postgres": | ||
| await postgresActions.move.mutateAsync({ | ||
| postgresId: serviceId, | ||
| targetProjectId: selectedTargetProject, | ||
| }); | ||
| break; | ||
| case "mysql": | ||
| await mysqlActions.move.mutateAsync({ | ||
| mysqlId: serviceId, | ||
| targetProjectId: selectedTargetProject, | ||
| }); | ||
| break; | ||
| case "mariadb": | ||
| await mariadbActions.move.mutateAsync({ | ||
| mariadbId: serviceId, | ||
| targetProjectId: selectedTargetProject, | ||
| }); | ||
| break; | ||
| case "redis": | ||
| await redisActions.move.mutateAsync({ | ||
| redisId: serviceId, | ||
| targetProjectId: selectedTargetProject, | ||
| }); | ||
| break; | ||
| case "mongo": | ||
| await mongoActions.move.mutateAsync({ | ||
| mongoId: serviceId, | ||
| targetProjectId: selectedTargetProject, | ||
| }); | ||
| break; | ||
| if (action === "move" && extraParams.targetProjectId) { | ||
| payload.targetProjectId = extraParams.targetProjectId; | ||
| } | ||
| success++; | ||
| } catch (error) { | ||
| toast.error( | ||
| `Error moving service ${serviceId}: ${error instanceof Error ? error.message : "Unknown error"}`, | ||
| ); | ||
| } | ||
| } | ||
| if (success > 0) { | ||
| toast.success(`${success} services moved successfully`); | ||
| refetch(); | ||
| } | ||
| setSelectedServices([]); | ||
| setIsDropdownOpen(false); | ||
| setIsMoveDialogOpen(false); | ||
| setIsBulkActionLoading(false); | ||
| }; | ||
|
|
||
| const handleBulkDelete = async () => { | ||
| let success = 0; | ||
| setIsBulkActionLoading(true); | ||
| for (const serviceId of selectedServices) { | ||
| try { | ||
| const service = filteredServices.find((s) => s.id === serviceId); | ||
| if (!service) continue; | ||
|
|
||
| switch (service.type) { | ||
| case "application": | ||
| await applicationActions.delete.mutateAsync({ | ||
| applicationId: serviceId, | ||
| }); | ||
| break; | ||
| case "compose": | ||
| await composeActions.delete.mutateAsync({ | ||
| composeId: serviceId, | ||
| deleteVolumes: false, | ||
| }); | ||
| break; | ||
| case "postgres": | ||
| await postgresActions.delete.mutateAsync({ | ||
| postgresId: serviceId, | ||
| }); | ||
| break; | ||
| case "mysql": | ||
| await mysqlActions.delete.mutateAsync({ | ||
| mysqlId: serviceId, | ||
| }); | ||
| break; | ||
| case "mariadb": | ||
| await mariadbActions.delete.mutateAsync({ | ||
| mariadbId: serviceId, | ||
| }); | ||
| break; | ||
| case "redis": | ||
| await redisActions.delete.mutateAsync({ | ||
| redisId: serviceId, | ||
| }); | ||
| break; | ||
| case "mongo": | ||
| await mongoActions.delete.mutateAsync({ | ||
| mongoId: serviceId, | ||
| }); | ||
| break; | ||
| if (action === "delete" && service.type === "compose") { | ||
| payload.deleteVolumes = false; | ||
| } | ||
|
|
||
| await mutation.mutateAsync(payload); | ||
| success++; | ||
| } catch (error) { | ||
| toast.error( | ||
| `Error deleting service ${serviceId}: ${error instanceof Error ? error.message : "Unknown error"}`, | ||
| ); | ||
| toast.error(`Error during ${action} of service ${serviceId}`); | ||
| } | ||
| } | ||
|
|
||
| if (success > 0) { | ||
| toast.success(`${success} services deleted successfully`); | ||
| toast.success(`${success} services ${action}ed successfully`); | ||
| refetch(); | ||
| } | ||
| setIsBulkActionLoading(false); | ||
| setSelectedServices([]); | ||
| setIsDropdownOpen(false); | ||
| setIsBulkActionLoading(false); | ||
| if (action === "move") setIsMoveDialogOpen(false); | ||
| }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd rather have the way we had it, I feel it's easier to add and modify, than a method that is somewhat complex
Could you simply add the missing mutations to each object in the service?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, I've returned all the changes to their original form.
b38da16 to
eff2657
Compare
Update bulk action endpoints for database services:
/api/trpc/redis.startand/api/trpc/redis.stopfor Redis/api/trpc/postgres.startand/api/trpc/postgres.stopfor PostgreSQL/api/trpc/compose.startand/api/trpc/compose.stopfor Docker Compose servicesTested with a project including Gitea, Redis, and PostgreSQL. Bulk start/stop operations now function correctly for all service types.
Closes #1626