Reorder deploy wizard: env vars on step 1, app storage on step 3.

Move Environment Variables to Basic Info and Application Data Storage to Resources so users configure them earlier and later in the flow.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
keyhan
2026-05-15 19:30:30 +03:30
parent 055e7a7c8d
commit 3a4fffcec4
+121 -119
View File
@@ -1153,6 +1153,74 @@ export default function DeployPage() {
)} )}
</div> </div>
)} )}
{/* Environment Variables */}
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">Environment Variables</label>
<div className="flex flex-col sm:flex-row gap-2 mb-3">
<input
className="input-field flex-1"
placeholder="KEY"
value={envKey}
onChange={(e) => setEnvKey(e.target.value)}
/>
<input
className="input-field flex-1"
placeholder="value"
value={envVal}
onChange={(e) => setEnvVal(e.target.value)}
/>
<button type="button" onClick={addEnvVar} className="btn-secondary shrink-0">Add</button>
</div>
<div className="mb-3">
{envFile ? (
<div className="flex items-center justify-between p-3 bg-green-50 border border-green-200 rounded-xl">
<div className="flex items-center space-x-2 min-w-0">
<CheckCircle className="w-4 h-4 text-green-600 shrink-0" />
<span className="text-sm text-green-800 truncate">{envFile.name}</span>
</div>
<button
type="button"
onClick={() => {
setEnvFile(null);
if (envFileInputRef.current) envFileInputRef.current.value = '';
}}
className="text-sm text-red-500 hover:text-red-700 font-medium shrink-0 ml-2"
>
Clear
</button>
</div>
) : (
<button
type="button"
onClick={() => envFileInputRef.current?.click()}
className="w-full flex items-center justify-center gap-2 p-3 border-2 border-dashed border-gray-300 rounded-xl text-sm text-gray-600 hover:border-primary-400 hover:text-primary-600 transition-colors"
>
<Upload className="w-4 h-4" />
Upload .env file
</button>
)}
<input
ref={envFileInputRef}
type="file"
accept=".env,.env.local,.env.production,.env.example"
className="hidden"
onChange={(e) => {
const file = e.target.files?.[0];
if (file) handleEnvFileSelect(file);
if (envFileInputRef.current) envFileInputRef.current.value = '';
}}
/>
</div>
{Object.entries(form.envVars || {}).map(([key, value]) => (
<div key={key} className="flex items-center justify-between bg-gray-50 rounded-lg px-3 py-2 mb-2">
<span className="text-sm font-mono">
<strong>{key}</strong> = {value}
</span>
<button onClick={() => removeEnvVar(key)} className="text-red-500 text-sm">Remove</button>
</div>
))}
</div>
</div> </div>
)} )}
@@ -1929,68 +1997,6 @@ export default function DeployPage() {
</div> </div>
</div> </div>
{/* App Storage Size (all app types) */}
<div className="bg-green-50 rounded-xl p-5 border border-green-200">
<div className="flex items-center gap-2 mb-3">
<FolderUp className="w-5 h-5 text-green-600" />
<h3 className="font-semibold text-gray-900">
{form.runtime === 'wordpress' ? 'Upload Storage (wp-content)'
: form.runtime === 'laravel' ? 'Storage Directory'
: 'Application Data Storage'}
</h3>
</div>
<p className="text-sm text-gray-600 mb-4">
{form.runtime === 'wordpress'
? 'This space is used for uploads, plugins, themes, and other WordPress files.'
: form.runtime === 'laravel'
? 'This space is used for uploads, logs, cache, and other Laravel storage files.'
: 'This space is used for persistent application data, uploads, and files.'}
</p>
<div className="flex items-center gap-3">
<div className="flex items-center border border-gray-300 rounded-lg overflow-hidden bg-white">
<button
type="button"
onClick={() => {
const current = parseInt(form.appStorageSize || '2', 10);
if (current > 1) setForm({ ...form, appStorageSize: String(current - 1) });
}}
disabled={parseInt(form.appStorageSize || '2', 10) <= 1}
className="px-3 py-2 bg-gray-100 hover:bg-gray-200 text-gray-700 font-bold disabled:opacity-30 disabled:cursor-not-allowed transition-colors"
>
</button>
<input
type="number"
min={1}
max={100}
value={form.appStorageSize || '2'}
onChange={(e) => {
const val = Math.max(1, Math.min(100, parseInt(e.target.value, 10) || 2));
setForm({ ...form, appStorageSize: String(val) });
}}
className="w-16 text-center py-2 border-x border-gray-300 text-sm font-semibold focus:outline-none"
/>
<button
type="button"
onClick={() => {
const current = parseInt(form.appStorageSize || '2', 10);
if (current < 100) setForm({ ...form, appStorageSize: String(current + 1) });
}}
disabled={parseInt(form.appStorageSize || '2', 10) >= 100}
className="px-3 py-2 bg-gray-100 hover:bg-gray-200 text-gray-700 font-bold disabled:opacity-30 disabled:cursor-not-allowed transition-colors"
>
+
</button>
</div>
<span className="text-sm font-medium text-gray-700">GB</span>
{wpContentFile && form.runtime === 'wordpress' && (
<span className="text-xs text-green-600">
Suggested based on wp-content ({(wpContentFile.size / (1024 * 1024 * 1024)).toFixed(2)} GB)
</span>
)}
</div>
<p className="mt-2 text-xs text-gray-500">Minimum 1GB Recommended: 2GB or more</p>
</div>
</div> </div>
)} )}
@@ -2287,73 +2293,69 @@ export default function DeployPage() {
</div> </div>
)} )}
{/* Environment Variables */} {/* App Storage Size (all app types) */}
<div> <div className="bg-green-50 rounded-xl p-5 border border-green-200">
<label className="block text-sm font-medium text-gray-700 mb-2">Environment Variables</label> <div className="flex items-center gap-2 mb-3">
<div className="flex flex-col sm:flex-row gap-2 mb-3"> <FolderUp className="w-5 h-5 text-green-600" />
<input <h3 className="font-semibold text-gray-900">
className="input-field flex-1" {form.runtime === 'wordpress' ? 'Upload Storage (wp-content)'
placeholder="KEY" : form.runtime === 'laravel' ? 'Storage Directory'
value={envKey} : 'Application Data Storage'}
onChange={(e) => setEnvKey(e.target.value)} </h3>
/>
<input
className="input-field flex-1"
placeholder="value"
value={envVal}
onChange={(e) => setEnvVal(e.target.value)}
/>
<button type="button" onClick={addEnvVar} className="btn-secondary shrink-0">Add</button>
</div> </div>
<div className="mb-3"> <p className="text-sm text-gray-600 mb-4">
{envFile ? ( {form.runtime === 'wordpress'
<div className="flex items-center justify-between p-3 bg-green-50 border border-green-200 rounded-xl"> ? 'This space is used for uploads, plugins, themes, and other WordPress files.'
<div className="flex items-center space-x-2 min-w-0"> : form.runtime === 'laravel'
<CheckCircle className="w-4 h-4 text-green-600 shrink-0" /> ? 'This space is used for uploads, logs, cache, and other Laravel storage files.'
<span className="text-sm text-green-800 truncate">{envFile.name}</span> : 'This space is used for persistent application data, uploads, and files.'}
</div> </p>
<div className="flex items-center gap-3">
<div className="flex items-center border border-gray-300 rounded-lg overflow-hidden bg-white">
<button
type="button"
onClick={() => {
const current = parseInt(form.appStorageSize || '2', 10);
if (current > 1) setForm({ ...form, appStorageSize: String(current - 1) });
}}
disabled={parseInt(form.appStorageSize || '2', 10) <= 1}
className="px-3 py-2 bg-gray-100 hover:bg-gray-200 text-gray-700 font-bold disabled:opacity-30 disabled:cursor-not-allowed transition-colors"
>
</button>
<input
type="number"
min={1}
max={100}
value={form.appStorageSize || '2'}
onChange={(e) => {
const val = Math.max(1, Math.min(100, parseInt(e.target.value, 10) || 2));
setForm({ ...form, appStorageSize: String(val) });
}}
className="w-16 text-center py-2 border-x border-gray-300 text-sm font-semibold focus:outline-none"
/>
<button <button
type="button" type="button"
onClick={() => { onClick={() => {
setEnvFile(null); const current = parseInt(form.appStorageSize || '2', 10);
if (envFileInputRef.current) envFileInputRef.current.value = ''; if (current < 100) setForm({ ...form, appStorageSize: String(current + 1) });
}} }}
className="text-sm text-red-500 hover:text-red-700 font-medium shrink-0 ml-2" disabled={parseInt(form.appStorageSize || '2', 10) >= 100}
className="px-3 py-2 bg-gray-100 hover:bg-gray-200 text-gray-700 font-bold disabled:opacity-30 disabled:cursor-not-allowed transition-colors"
> >
Clear +
</button> </button>
</div> </div>
) : ( <span className="text-sm font-medium text-gray-700">GB</span>
<button {wpContentFile && form.runtime === 'wordpress' && (
type="button" <span className="text-xs text-green-600">
onClick={() => envFileInputRef.current?.click()} Suggested based on wp-content ({(wpContentFile.size / (1024 * 1024 * 1024)).toFixed(2)} GB)
className="w-full flex items-center justify-center gap-2 p-3 border-2 border-dashed border-gray-300 rounded-xl text-sm text-gray-600 hover:border-primary-400 hover:text-primary-600 transition-colors" </span>
> )}
<Upload className="w-4 h-4" />
Upload .env file
</button>
)}
<input
ref={envFileInputRef}
type="file"
accept=".env,.env.local,.env.production,.env.example"
className="hidden"
onChange={(e) => {
const file = e.target.files?.[0];
if (file) handleEnvFileSelect(file);
if (envFileInputRef.current) envFileInputRef.current.value = '';
}}
/>
</div>
{Object.entries(form.envVars || {}).map(([key, value]) => (
<div key={key} className="flex items-center justify-between bg-gray-50 rounded-lg px-3 py-2 mb-2">
<span className="text-sm font-mono">
<strong>{key}</strong> = {value}
</span>
<button onClick={() => removeEnvVar(key)} className="text-red-500 text-sm">Remove</button>
</div> </div>
))} <p className="mt-2 text-xs text-gray-500">Minimum 1GB Recommended: 2GB or more</p>
</div> </div>
</div> </div>
)} )}