@@ -23,7 +23,7 @@ import { resolveOrgIdFromSlug } from "~/models/organization.server";
2323import { ProjectSettingsService } from "~/services/projectSettings.server" ;
2424import { logger } from "~/services/logger.server" ;
2525import { dashboardAction } from "~/services/routeBuilders/dashboardBuilder" ;
26- import { organizationPath , v3ProjectPath } from "~/utils/pathBuilder" ;
26+ import { organizationPath , v3ProjectSettingsGeneralPath } from "~/utils/pathBuilder" ;
2727import { useState } from "react" ;
2828
2929function createSchema (
@@ -60,9 +60,21 @@ function createSchema(
6060 ] ) ;
6161}
6262
63+ type FormAction = "rename" | "delete" ;
64+
65+ export function submissionFor ( lastSubmission : unknown , formAction : FormAction ) {
66+ return lastSubmission &&
67+ typeof lastSubmission === "object" &&
68+ "formAction" in lastSubmission &&
69+ lastSubmission . formAction === formAction
70+ ? lastSubmission
71+ : undefined ;
72+ }
73+
6374const Params = z . object ( {
6475 organizationSlug : z . string ( ) ,
6576 projectParam : z . string ( ) ,
77+ envParam : z . string ( ) ,
6678} ) ;
6779
6880export const action = dashboardAction (
@@ -75,9 +87,16 @@ export const action = dashboardAction(
7587 } ,
7688 async ( { user, ability, request, params } ) => {
7789 const userId = user . id ;
78- const { organizationSlug, projectParam } = params ;
90+ const { organizationSlug, projectParam, envParam } = params ;
91+
92+ const settingsPath = v3ProjectSettingsGeneralPath (
93+ { slug : organizationSlug } ,
94+ { slug : projectParam } ,
95+ { slug : envParam }
96+ ) ;
7997
8098 const formData = await request . formData ( ) ;
99+ const formAction = formData . get ( "action" ) as FormAction ;
81100
82101 const schema = createSchema ( {
83102 getSlugMatch : ( slug ) => {
@@ -87,7 +106,7 @@ export const action = dashboardAction(
87106 const submission = parseWithZod ( formData , { schema } ) ;
88107
89108 if ( submission . status !== "success" ) {
90- return json ( submission . reply ( ) ) ;
109+ return json ( { ... submission . reply ( ) , formAction } ) ;
91110 }
92111
93112 const projectSettingsService = new ProjectSettingsService ( ) ;
@@ -98,7 +117,10 @@ export const action = dashboardAction(
98117 ) ;
99118
100119 if ( membershipResultOrFail . isErr ( ) ) {
101- return json ( { errors : { body : membershipResultOrFail . error . type } } , { status : 404 } ) ;
120+ return json (
121+ { ...submission . reply ( { formErrors : [ "Project not found" ] } ) , formAction } ,
122+ { status : 404 }
123+ ) ;
102124 }
103125
104126 const { projectId } = membershipResultOrFail . value ;
@@ -107,7 +129,7 @@ export const action = dashboardAction(
107129 case "rename" : {
108130 if ( ! ability . can ( "manage" , { type : "project" } ) ) {
109131 throw await redirectWithErrorMessage (
110- v3ProjectPath ( { slug : organizationSlug } , { slug : projectParam } ) ,
132+ settingsPath ,
111133 request ,
112134 "You don't have permission to rename this project"
113135 ) ;
@@ -126,21 +148,24 @@ export const action = dashboardAction(
126148 logger . error ( "Failed to rename project" , {
127149 error : resultOrFail . error ,
128150 } ) ;
129- return json ( { errors : { body : "Failed to rename project" } } , { status : 400 } ) ;
151+ return json (
152+ { ...submission . reply ( { formErrors : [ "Failed to rename project" ] } ) , formAction } ,
153+ { status : 400 }
154+ ) ;
130155 }
131156 }
132157 }
133158
134159 return redirectWithSuccessMessage (
135- v3ProjectPath ( { slug : organizationSlug } , { slug : projectParam } ) ,
160+ settingsPath ,
136161 request ,
137162 `Project renamed to ${ submission . value . projectName } `
138163 ) ;
139164 }
140165 case "delete" : {
141166 if ( ! ability . can ( "manage" , { type : "project" } ) ) {
142167 throw await redirectWithErrorMessage (
143- v3ProjectPath ( { slug : organizationSlug } , { slug : projectParam } ) ,
168+ settingsPath ,
144169 request ,
145170 "You don't have permission to delete this project"
146171 ) ;
@@ -157,7 +182,7 @@ export const action = dashboardAction(
157182 error : resultOrFail . error ,
158183 } ) ;
159184 return redirectWithErrorMessage (
160- v3ProjectPath ( { slug : organizationSlug } , { slug : projectParam } ) ,
185+ settingsPath ,
161186 request ,
162187 `Project ${ projectParam } could not be deleted`
163188 ) ;
@@ -185,7 +210,7 @@ export default function GeneralSettingsPage() {
185210 const [ renameForm , { projectName } ] = useForm ( {
186211 id : "rename-project" ,
187212 // TODO: type this
188- lastResult : lastSubmission as any ,
213+ lastResult : submissionFor ( lastSubmission , "rename" ) as any ,
189214 shouldRevalidate : "onSubmit" ,
190215 onValidate ( { formData } ) {
191216 return parseWithZod ( formData , {
@@ -201,7 +226,7 @@ export default function GeneralSettingsPage() {
201226 const [ deleteForm , { projectSlug } ] = useForm ( {
202227 id : "delete-project" ,
203228 // TODO: type this
204- lastResult : lastSubmission as any ,
229+ lastResult : submissionFor ( lastSubmission , "delete" ) as any ,
205230 shouldValidate : "onInput" ,
206231 shouldRevalidate : "onSubmit" ,
207232 onValidate ( { formData } ) {
@@ -250,6 +275,7 @@ export default function GeneralSettingsPage() {
250275 } }
251276 />
252277 < FormError id = { projectName . errorId } > { projectName . errors } </ FormError >
278+ < FormError > { renameForm . errors } </ FormError >
253279 </ InputGroup >
254280 < FormButtons
255281 confirmButton = {
0 commit comments