Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 0 additions & 6 deletions apps/api/src/db/repo/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -198,12 +198,6 @@ export const listRoutesByDeployment = async (deploymentId: string): Promise<Rout
return rows.map(mapRoute);
};

export const listRoutesByDeployment = async (deploymentId: string): Promise<Route[]> => {
const db = await getDb();
const rows = await db.select().from(routes).where(eq(routes.deploymentId, deploymentId)).execute();
return rows.map(mapRoute);
};

export const deleteRoute = async (id: string): Promise<void> => {
const db = await getDb();
await db.delete(routes).where(eq(routes.id, id)).execute();
Expand Down
6 changes: 3 additions & 3 deletions apps/web/src/components/databases/CreateDatabaseDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -230,14 +230,14 @@ export function CreateDatabaseDialog({
</p>
)}

<div className="flex justify-end gap-2 border-t border-border/40 pt-4">
<Button variant="ghost" onClick={() => onOpenChange(false)} className="text-xs text-muted-foreground">
<div className="flex flex-col-reverse sm:flex-row justify-end gap-2 border-t border-border/40 pt-4">
<Button variant="ghost" onClick={() => onOpenChange(false)} className="text-xs text-muted-foreground w-full sm:w-auto">
Cancel
</Button>
<Button
disabled={isCreating || !name.trim() || (!allowAnywhere && !cidrs.trim())}
onClick={create}
className="bg-orange-500 hover:bg-orange-600 text-white font-medium text-xs px-5 shadow-md"
className="bg-orange-500 hover:bg-orange-600 text-white font-medium text-xs px-5 shadow-md w-full sm:w-auto"
>
{isCreating ? "Provisioning..." : "Provision Database"}
</Button>
Expand Down
20 changes: 8 additions & 12 deletions apps/web/src/components/databases/DatabaseCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,7 @@ export function DatabaseCard({ database, project, onChanged, onDelete }: Databas
onChanged();
} catch (err) {
setActionError(err instanceof Error ? err.message : "Action failed");
}
fontFinally: {
} finally {
setIsBusy(false);
}
};
Expand All @@ -62,8 +61,7 @@ export function DatabaseCard({ database, project, onChanged, onDelete }: Databas

return (
<Card className="border-border/60 bg-card/60 backdrop-blur-sm shadow-xl hover:border-orange-500/30 transition-all overflow-hidden flex flex-col justify-between">
<CardContent className="space-y-5 p-6">
{/* Top Header Row */}
<CardContent className="space-y-5 p-4 sm:p-6">
<div className="flex items-start justify-between gap-4">
<div className="space-y-1.5">
<div className="flex items-center gap-2">
Expand All @@ -79,7 +77,7 @@ export function DatabaseCard({ database, project, onChanged, onDelete }: Databas
<Database className="h-4 w-4 text-orange-400" />
{database.name}
</h3>
<p className="text-xs text-muted-foreground flex items-center gap-1.5">
<p className="text-xs text-muted-foreground flex items-center gap-1.5 flex-wrap">
<span>{project ? `Project: ${project.name}` : "Standalone Database"}</span>
<span>·</span>
<span className="font-mono text-zinc-400">{database.databaseName}</span>
Expand All @@ -92,13 +90,12 @@ export function DatabaseCard({ database, project, onChanged, onDelete }: Databas
disabled={isBusy}
aria-label={`Delete ${database.name}`}
onClick={() => onDelete(database)}
className="h-8 w-8 text-muted-foreground hover:text-destructive hover:bg-destructive/10 rounded-lg"
className="h-8 w-8 text-muted-foreground hover:text-destructive hover:bg-destructive/10 rounded-lg shrink-0"
>
<Trash2 className="h-4 w-4" />
</Button>
</div>

{/* Endpoints Grid */}
<div className="grid grid-cols-1 sm:grid-cols-2 gap-3 text-xs">
<div className="rounded-xl border border-border/80 bg-black/40 p-3 space-y-1">
<div className="flex items-center gap-1.5 text-[11px] font-medium text-muted-foreground">
Expand All @@ -125,7 +122,6 @@ export function DatabaseCard({ database, project, onChanged, onDelete }: Databas
</div>
</div>

{/* Storage Meter */}
<div className="space-y-1.5">
<div className="flex justify-between text-xs font-medium">
<span className="text-muted-foreground">Disk Storage Usage</span>
Expand All @@ -152,7 +148,6 @@ export function DatabaseCard({ database, project, onChanged, onDelete }: Databas
</div>
</div>

{/* Connection String Box */}
<div className="rounded-xl border border-border/80 bg-black/50 p-3.5 space-y-2">
<div className="flex items-center justify-between gap-3">
<div className="min-w-0 flex-1">
Expand All @@ -170,6 +165,7 @@ export function DatabaseCard({ database, project, onChanged, onDelete }: Databas
variant="ghost"
size="icon"
onClick={reveal}
aria-label={credentials ? "Hide credentials" : "Reveal credentials"}
className="h-8 w-8 text-muted-foreground hover:text-foreground rounded-lg"
>
{credentials ? <EyeOff className="h-4 w-4" /> : <Eye className="h-4 w-4" />}
Expand All @@ -181,6 +177,7 @@ export function DatabaseCard({ database, project, onChanged, onDelete }: Databas
variant="ghost"
size="sm"
onClick={() => handleCopyConnection(connString)}
aria-label="Copy connection string"
className="h-8 text-xs text-emerald-400 hover:bg-emerald-500/10 gap-1 px-2 rounded-lg"
>
{copiedConnection ? <Check className="h-3.5 w-3.5" /> : <Copy className="h-3.5 w-3.5" />}
Expand All @@ -197,9 +194,8 @@ export function DatabaseCard({ database, project, onChanged, onDelete }: Databas
)}
</div>

{/* Action Row */}
<div className="flex items-center justify-between border-t border-border/40 pt-4">
<div className="flex gap-2">
<div className="flex flex-wrap items-center justify-between gap-2 border-t border-border/40 pt-4">
<div className="flex flex-wrap gap-2">
{database.status === "stopped" ? (
<Button
size="sm"
Expand Down
62 changes: 32 additions & 30 deletions apps/web/src/components/layout/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,37 +10,39 @@ interface HeaderProps {

export function Header({ currentProject, currentProjectId, location, setSidebarOpen }: HeaderProps) {
return (
<header className="h-14 border-b border-[#1a1a1f] bg-[#0c0c0e] flex items-center px-4 sm:px-6 gap-2 text-xs text-zinc-500">
<button
onClick={() => setSidebarOpen(true)}
className="lg:hidden p-1.5 -ml-1 mr-1 rounded-md hover:bg-zinc-800 text-zinc-400 hover:text-zinc-200 transition-colors"
aria-label="Open sidebar"
>
<Menu className="h-4.5 w-4.5" />
</button>
<header className="h-14 border-b border-[#1a1a1f] bg-[#0c0c0e] flex items-center justify-between px-3.5 sm:px-6 gap-2 text-xs text-zinc-500 sticky top-0 z-30">
<div className="flex items-center gap-1.5 sm:gap-2 min-w-0">
<button
onClick={() => setSidebarOpen(true)}
className="lg:hidden p-2 -ml-1 mr-1 rounded-lg hover:bg-zinc-800 text-zinc-400 hover:text-zinc-200 transition-colors"
aria-label="Open sidebar"
>
<Menu className="h-5 w-5" />
</button>

<Link to="/" className="hover:text-zinc-200 transition-colors">
Workspace
</Link>
<ChevronRight className="h-3 w-3 text-zinc-600" />
{currentProject ? (
<>
<Link
to="/project/$projectId"
params={{ projectId: currentProjectId! }}
search={{ tab: "deployments" }}
className="hover:text-zinc-200 transition-colors font-medium text-zinc-300"
>
{currentProject.name}
</Link>
<ChevronRight className="h-3 w-3 text-zinc-600" />
<span className="text-zinc-100 font-bold uppercase tracking-wider text-[10px] bg-zinc-800 px-1.5 py-0.5 rounded">
{new URLSearchParams(location.search).get("tab") || "deployments"}
</span>
</>
) : (
<span className="text-zinc-300 font-medium">Dashboard</span>
)}
<Link to="/" className="hover:text-zinc-200 transition-colors shrink-0">
Workspace
</Link>
<ChevronRight className="h-3 w-3 text-zinc-600 shrink-0" />
{currentProject ? (
<>
<Link
to="/project/$projectId"
params={{ projectId: currentProjectId! }}
search={{ tab: "deployments" }}
className="hover:text-zinc-200 transition-colors font-medium text-zinc-300 truncate max-w-[110px] sm:max-w-[200px]"
>
{currentProject.name}
</Link>
<ChevronRight className="h-3 w-3 text-zinc-600 shrink-0" />
<span className="text-zinc-100 font-bold uppercase tracking-wider text-[9px] sm:text-[10px] bg-zinc-800 px-1.5 py-0.5 rounded shrink-0">
{new URLSearchParams(location.search).get("tab") || "deployments"}
</span>
</>
) : (
<span className="text-zinc-300 font-medium truncate">Dashboard</span>
)}
</div>
</header>
);
}
25 changes: 13 additions & 12 deletions apps/web/src/components/project/alerts/AlertsTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ export function AlertsTab({ projectId }: AlertsTabProps) {
return (
<div className="space-y-6">
{alerts.length === 0 ? (
<div className="flex flex-col items-center justify-center border border-dashed border-border rounded-2xl p-12 text-center bg-card/20 backdrop-blur-sm relative overflow-hidden group min-h-[350px]">
<div className="flex flex-col items-center justify-center border border-dashed border-border rounded-2xl p-6 sm:p-12 text-center bg-card/20 backdrop-blur-sm relative overflow-hidden group min-h-[350px]">
<div className="absolute inset-0 bg-gradient-to-br from-primary/5 via-transparent to-transparent opacity-50 pointer-events-none" />
<div className="relative w-16 h-16 rounded-2xl bg-gradient-to-b from-[#1a1a1f] to-[#121215] border border-border flex items-center justify-center mb-6 shadow-xl group-hover:border-primary/30 transition-colors duration-300">
<div className="absolute inset-0 bg-primary/10 rounded-2xl blur-lg opacity-0 group-hover:opacity-100 transition-opacity duration-300" />
Expand All @@ -98,7 +98,7 @@ export function AlertsTab({ projectId }: AlertsTabProps) {
</div>
) : (
<div className="space-y-4">
<div className="flex items-center justify-between">
<div className="flex flex-col sm:flex-row sm:items-center justify-between gap-3">
<div>
<h2 className="text-lg font-semibold text-foreground">Alert Rules</h2>
<p className="text-sm text-muted-foreground">
Expand All @@ -107,7 +107,7 @@ export function AlertsTab({ projectId }: AlertsTabProps) {
</div>
<Button
onClick={() => setIsOpen(true)}
className="bg-primary hover:bg-primary/90 text-primary-foreground font-semibold flex items-center gap-1.5 px-4 h-9 rounded-xl transition-all shadow-md"
className="bg-primary hover:bg-primary/90 text-primary-foreground font-semibold flex items-center justify-center gap-1.5 px-4 h-9 rounded-xl transition-all shadow-md w-full sm:w-auto"
>
<Plus className="h-4.5 w-4.5" /> Add Rule
</Button>
Expand All @@ -119,15 +119,15 @@ export function AlertsTab({ projectId }: AlertsTabProps) {
return (
<div
key={a.id}
className="flex items-center justify-between p-4 rounded-xl border border-border bg-card/40 hover:bg-card/80 transition-all gap-4 group"
className="flex items-start sm:items-center justify-between p-3.5 sm:p-4 rounded-xl border border-border bg-card/40 hover:bg-card/80 transition-all gap-3 group"
>
<div className="flex items-center gap-4">
<div className="w-10 h-10 rounded-xl bg-primary/10 text-primary flex items-center justify-center shrink-0 border border-primary/15">
<div className="flex items-start sm:items-center gap-3 sm:gap-4 min-w-0">
<div className="w-10 h-10 rounded-xl bg-primary/10 text-primary flex items-center justify-center shrink-0 border border-primary/15 mt-0.5 sm:mt-0">
<Icon className="h-5 w-5" />
</div>
<div>
<div className="min-w-0">
<div className="flex items-center gap-2 flex-wrap">
<span className="font-semibold text-sm capitalize text-foreground">
<span className="font-semibold text-sm capitalize text-foreground truncate">
{a.type.replace("_", " ")}
</span>
<Badge
Expand All @@ -137,16 +137,17 @@ export function AlertsTab({ projectId }: AlertsTabProps) {
{a.channel}
</Badge>
</div>
<p className="text-xs text-muted-foreground mt-1">
Triggers when <span className="capitalize">{a.type.replace("_", " ")}</span> exceeds{" "}
<p className="text-xs text-muted-foreground mt-1 leading-relaxed">
Triggers when{" "}
<span className="capitalize">{a.type.replace("_", " ")}</span> exceeds{" "}
<span className="font-semibold text-foreground">
{a.threshold}
{getUnit(a.type)}
</span>
</p>
</div>
</div>
<div className="flex items-center gap-4">
<div className="flex items-center gap-2 shrink-0">
<button
type="button"
onClick={() => api.toggleAlert(a.id, !a.enabled).then(() => refetch())}
Expand All @@ -165,7 +166,7 @@ export function AlertsTab({ projectId }: AlertsTabProps) {
<Button
variant="ghost"
size="icon"
className="h-8 w-8 text-muted-foreground hover:text-destructive hover:bg-destructive/10 rounded-lg opacity-80 group-hover:opacity-100 transition-all"
className="h-8 w-8 text-muted-foreground hover:text-destructive hover:bg-destructive/10 rounded-lg opacity-100 sm:opacity-80 sm:group-hover:opacity-100 transition-all"
onClick={() => setDeletingAlertId(a.id)}
>
<Trash2 className="h-4 w-4" />
Expand Down
18 changes: 6 additions & 12 deletions apps/web/src/components/project/create/BuildStrategySection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@ export function BuildStrategySection({
<p className="text-xs text-zinc-400 mt-1">Select how Dequel builds and manages your application containers.</p>
</div>

{/* Build Strategy Selection Cards (Railpack vs Docker Compose) */}
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
<button
type="button"
Expand Down Expand Up @@ -118,16 +117,13 @@ export function BuildStrategySection({
</button>
</div>

{/* Railpack Configuration */}
{buildType === "railpack" && (
<div className="space-y-6 pt-4 border-t border-[#1a1a22]">
{/* Framework Preset Select (with SVG logos) */}
<div className="space-y-1.5">
<label className="block text-xs font-semibold text-zinc-300">Application Preset</label>
<FrameworkSelect selectedPresetId={selectedPresetId} onSelectPreset={onSelectPreset} />
</div>

{/* Project Type Card Selection (Web Service vs Static Site) */}
<div className="space-y-2">
<label className="block text-xs font-semibold text-zinc-300">Project Type</label>
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
Expand Down Expand Up @@ -177,10 +173,9 @@ export function BuildStrategySection({
</div>
</div>

{/* Detailed Build Commands */}
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
<div className="space-y-1.5">
<label className="block text-xs font-semibold text-zinc-300 flex items-center gap-1.5">
<label className="text-xs font-semibold text-zinc-300 flex items-center gap-1.5">
<Terminal className="h-3.5 w-3.5 text-orange-400" />
Build Command
</label>
Expand All @@ -193,7 +188,7 @@ export function BuildStrategySection({
</div>

<div className="space-y-1.5">
<label className="block text-xs font-semibold text-zinc-300 flex items-center gap-1.5">
<label className="text-xs font-semibold text-zinc-300 flex items-center gap-1.5">
<FolderCode className="h-3.5 w-3.5 text-emerald-400" />
Output Directory
</label>
Expand All @@ -206,7 +201,7 @@ export function BuildStrategySection({
</div>

<div className="space-y-1.5">
<label className="block text-xs font-semibold text-zinc-300 flex items-center gap-1.5">
<label className="text-xs font-semibold text-zinc-300 flex items-center gap-1.5">
<Sliders className="h-3.5 w-3.5 text-blue-400" />
Install Command
</label>
Expand All @@ -220,7 +215,7 @@ export function BuildStrategySection({

{projectType === "web" && (
<div className="space-y-1.5">
<label className="block text-xs font-semibold text-zinc-300 flex items-center gap-1.5">
<label className="text-xs font-semibold text-zinc-300 flex items-center gap-1.5">
<Play className="h-3.5 w-3.5 text-purple-400" />
Start Command
</label>
Expand Down Expand Up @@ -256,10 +251,9 @@ export function BuildStrategySection({
</div>
)}

{/* Docker Compose Service Gateway Mapping */}
{buildType === "compose" && (
<div className="space-y-4 pt-4 border-t border-[#1a1a22]">
<div className="flex items-center justify-between">
<div className="flex flex-col sm:flex-row sm:items-center justify-between gap-3">
<div>
<h4 className="text-xs font-bold text-zinc-200">Compose Ingress Service Mapping</h4>
<p className="text-[11px] text-zinc-400 mt-0.5">
Expand All @@ -269,7 +263,7 @@ export function BuildStrategySection({
<Button
type="button"
onClick={addComposeServiceRow}
className="bg-[#1c1c24] hover:bg-[#262632] text-orange-400 text-xs border border-[#2e2e3c]"
className="bg-[#1c1c24] hover:bg-[#262632] text-orange-400 text-xs border border-[#2e2e3c] w-full sm:w-auto"
>
<Plus className="h-3.5 w-3.5 mr-1" /> Add Service
</Button>
Expand Down
Loading
Loading