2026-04-22 22:49:43 +02:00
|
|
|
import { useState, useEffect, useRef } from 'react';
|
2026-04-22 22:43:54 +02:00
|
|
|
import { useParams, useLocation } from 'react-router';
|
|
|
|
|
import { useEnvironmentStore } from '../../../api/environment-store';
|
|
|
|
|
import { useEnvironments } from '../../../api/queries/admin/environments';
|
2026-04-22 22:49:43 +02:00
|
|
|
import { useApps, useAppVersions } from '../../../api/queries/admin/apps';
|
2026-04-22 22:43:54 +02:00
|
|
|
import { PageLoader } from '../../../components/PageLoader';
|
2026-04-22 22:49:43 +02:00
|
|
|
import { IdentitySection } from './IdentitySection';
|
|
|
|
|
import { deriveAppName } from './utils/deriveAppName';
|
2026-04-22 22:43:54 +02:00
|
|
|
import styles from './AppDeploymentPage.module.css';
|
|
|
|
|
|
|
|
|
|
export default function AppDeploymentPage() {
|
|
|
|
|
const { appId } = useParams<{ appId?: string }>();
|
|
|
|
|
const location = useLocation();
|
|
|
|
|
const selectedEnv = useEnvironmentStore((s) => s.environment);
|
|
|
|
|
const { data: environments = [], isLoading: envLoading } = useEnvironments();
|
|
|
|
|
const { data: apps = [], isLoading: appsLoading } = useApps(selectedEnv);
|
|
|
|
|
|
|
|
|
|
const isNetNew = location.pathname.endsWith('/apps/new');
|
|
|
|
|
const app = isNetNew ? null : apps.find((a) => a.slug === appId) ?? null;
|
|
|
|
|
|
2026-04-22 22:49:43 +02:00
|
|
|
const env = environments.find((e) => e.slug === selectedEnv);
|
|
|
|
|
const { data: versions = [] } = useAppVersions(selectedEnv, app?.slug);
|
|
|
|
|
const currentVersion = versions.slice().sort((a, b) => b.version - a.version)[0] ?? null;
|
|
|
|
|
|
|
|
|
|
// Form state
|
|
|
|
|
const [name, setName] = useState('');
|
|
|
|
|
const [stagedJar, setStagedJar] = useState<File | null>(null);
|
|
|
|
|
const lastDerivedRef = useRef<string>('');
|
|
|
|
|
|
|
|
|
|
// Initialize name when app loads
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
if (app) setName(app.displayName);
|
|
|
|
|
}, [app]);
|
|
|
|
|
|
|
|
|
|
// Auto-derive from staged JAR (net-new mode only, don't overwrite manual edits)
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
if (!stagedJar || app) return;
|
|
|
|
|
const derived = deriveAppName(stagedJar.name);
|
|
|
|
|
if (!name || name === lastDerivedRef.current) {
|
|
|
|
|
setName(derived);
|
|
|
|
|
lastDerivedRef.current = derived;
|
|
|
|
|
}
|
|
|
|
|
}, [stagedJar, app, name]);
|
|
|
|
|
|
2026-04-22 22:43:54 +02:00
|
|
|
if (envLoading || appsLoading) return <PageLoader />;
|
2026-04-22 22:49:43 +02:00
|
|
|
if (!env) return <div>Select an environment first.</div>;
|
|
|
|
|
|
|
|
|
|
const mode: 'net-new' | 'deployed' = app ? 'deployed' : 'net-new';
|
2026-04-22 22:43:54 +02:00
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<div className={styles.container}>
|
|
|
|
|
<h2>{app ? app.displayName : 'Create Application'}</h2>
|
2026-04-22 22:49:43 +02:00
|
|
|
<IdentitySection
|
|
|
|
|
mode={mode}
|
|
|
|
|
environment={env}
|
|
|
|
|
app={app}
|
|
|
|
|
currentVersion={currentVersion}
|
|
|
|
|
name={name}
|
|
|
|
|
onNameChange={setName}
|
|
|
|
|
stagedJar={stagedJar}
|
|
|
|
|
onStagedJarChange={setStagedJar}
|
|
|
|
|
deploying={false}
|
|
|
|
|
/>
|
2026-04-22 22:43:54 +02:00
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|