Skip to content

Commit 451e826

Browse files
committed
feat: Implement active deployment polling and prioritized selection on the project details page, refine UI styling, and add an API .gitignore.
1 parent 201029f commit 451e826

5 files changed

Lines changed: 140 additions & 29 deletions

File tree

‎apps/api/.gitignore‎

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# Dependencies
2+
node_modules/
3+
.pnp/
4+
.pnp.js
5+
6+
# Build outputs
7+
dist/
8+
build/
9+
*.tsbuildinfo
10+
11+
# Database
12+
*.db
13+
*.db-journal
14+
*.db-wal
15+
*.db-shm
16+
apps/api/data/
17+
18+
# Environment files
19+
.env
20+
.env.local
21+
.env.*.local
22+
23+
# Logs
24+
logs/
25+
*.log
26+
npm-debug.log*
27+
28+
# IDE
29+
.idea/
30+
.vscode/
31+
*.swp
32+
*.swo
33+
.DS_Store
34+
35+
# Docker
36+
.builds/
37+
38+
# Testing
39+
coverage/
40+
41+
# OS
42+
Thumbs.db
43+
44+
# Certbot/SSL
45+
certbot/

‎apps/api/data/deployhub.db-shm‎

0 Bytes
Binary file not shown.

‎apps/api/data/deployhub.db-wal‎

60.4 KB
Binary file not shown.

‎apps/web/src/pages/ProjectDetails.css‎

Lines changed: 73 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
.project-details {
22
animation: fadeIn 0.3s ease;
3-
max-width: 1400px;
3+
max-width: 1200px;
44
margin: 0 auto;
55
min-height: calc(100vh - 120px);
6+
padding-right: 1rem;
67
}
78

89
.project-loading,
@@ -24,92 +25,136 @@
2425
animation: spin 1s linear infinite;
2526
}
2627

27-
/* Header */
28+
/* Header - Clean & Aligned */
2829
.project-header {
2930
display: flex;
30-
align-items: flex-start;
31+
align-items: center;
3132
justify-content: space-between;
32-
gap: 1.5rem;
33-
margin-bottom: 1.5rem;
34-
padding-bottom: 1.25rem;
33+
gap: 1rem;
34+
margin-bottom: 1.25rem;
35+
padding-bottom: 1rem;
3536
border-bottom: 1px solid var(--color-border);
3637
}
3738

3839
.project-header-left {
3940
display: flex;
4041
flex-direction: column;
41-
gap: 0.35rem;
42+
gap: 0.25rem;
4243
flex: 1;
4344
min-width: 0;
4445
}
4546

4647
.back-link {
4748
display: inline-flex;
4849
align-items: center;
49-
gap: 0.35rem;
50-
color: var(--color-text-secondary);
51-
font-size: 0.8rem;
52-
margin-bottom: 0.35rem;
50+
gap: 0.25rem;
51+
color: var(--color-text-muted);
52+
font-size: 0.75rem;
53+
margin-bottom: 0.25rem;
5354
transition: all 0.15s ease;
5455
}
5556

5657
.back-link:hover {
5758
color: var(--color-primary);
58-
transform: translateX(-3px);
5959
}
6060

6161
.project-header h1 {
62-
font-size: 1.75rem;
63-
font-weight: 700;
62+
font-size: 1.5rem;
63+
font-weight: 600;
6464
color: var(--color-text);
65+
line-height: 1.2;
6566
}
6667

6768
.project-meta {
6869
display: flex;
69-
gap: 0.75rem;
70+
gap: 0.5rem;
7071
flex-wrap: wrap;
7172
align-items: center;
73+
margin-top: 0.25rem;
7274
}
7375

7476
.meta-item {
7577
display: flex;
7678
align-items: center;
77-
gap: 0.35rem;
79+
gap: 0.25rem;
7880
color: var(--color-text-muted);
79-
font-size: 0.8rem;
81+
font-size: 0.75rem;
8082
}
8183

8284
.meta-item.buildpack {
8385
background: rgba(168, 85, 247, 0.1);
8486
color: var(--color-primary);
85-
padding: 0.2rem 0.6rem;
87+
padding: 0.15rem 0.5rem;
8688
border-radius: 4px;
87-
font-size: 0.75rem;
89+
font-size: 0.7rem;
8890
font-weight: 500;
8991
}
9092

91-
/* Sleek Action Buttons */
93+
/* Sleek Action Buttons - Production Quality */
9294
.project-actions {
9395
display: flex;
94-
gap: 0.5rem;
96+
align-items: center;
97+
gap: 0.375rem;
9598
flex-shrink: 0;
9699
}
97100

98101
.project-actions .btn {
99-
padding: 0.5rem 0.875rem;
100-
font-size: 0.8rem;
102+
height: 32px;
103+
padding: 0 0.75rem;
104+
font-size: 0.75rem;
105+
font-weight: 500;
101106
border-radius: 6px;
107+
display: inline-flex;
108+
align-items: center;
109+
justify-content: center;
110+
gap: 0.35rem;
111+
white-space: nowrap;
112+
transition: all 0.15s ease;
113+
}
114+
115+
.project-actions .btn svg {
116+
width: 14px;
117+
height: 14px;
118+
}
119+
120+
.project-actions .btn-secondary {
121+
background: var(--color-bg-elevated);
122+
border: 1px solid var(--color-border);
123+
color: var(--color-text-secondary);
124+
}
125+
126+
.project-actions .btn-secondary:hover {
127+
background: var(--color-bg-hover);
128+
color: var(--color-text);
129+
}
130+
131+
.project-actions .btn-secondary.active {
132+
background: rgba(168, 85, 247, 0.1);
133+
border-color: rgba(168, 85, 247, 0.3);
134+
color: var(--color-primary);
135+
}
136+
137+
.project-actions .btn-primary {
138+
background: linear-gradient(135deg, #a855f7, #7c3aed);
139+
border: none;
140+
color: white;
141+
}
142+
143+
.project-actions .btn-primary:hover {
144+
background: linear-gradient(135deg, #9333ea, #6d28d9);
145+
transform: translateY(-1px);
102146
}
103147

104148
.project-actions .btn-icon {
105-
width: 34px;
106-
height: 34px;
149+
width: 32px;
150+
height: 32px;
107151
padding: 0;
108152
}
109153

110-
.project-actions .btn.active {
111-
background: var(--color-primary);
112-
color: white;
154+
.project-actions .btn-icon:hover {
155+
background: rgba(239, 68, 68, 0.1);
156+
border-color: rgba(239, 68, 68, 0.3);
157+
color: #ef4444;
113158
}
114159

115160
/* Environment Variables Panel - Compact */

‎apps/web/src/pages/ProjectDetails.tsx‎

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,14 @@ export default function ProjectDetails() {
9797
const data = await projects.get(id!);
9898
setProject(data);
9999
if (data.deployments.length > 0) {
100-
setSelectedDeployment(data.deployments[0]);
100+
// Prioritize building/deploying deployment, otherwise select the first one
101+
const activeDeployment = data.deployments.find(
102+
(d: Deployment) => d.status === 'building' || d.status === 'deploying'
103+
);
104+
const runningDeployment = data.deployments.find(
105+
(d: Deployment) => d.status === 'running'
106+
);
107+
setSelectedDeployment(activeDeployment || runningDeployment || data.deployments[0]);
101108
}
102109
} catch (err: any) {
103110
setError(err.message);
@@ -106,6 +113,20 @@ export default function ProjectDetails() {
106113
}
107114
};
108115

116+
// Poll for updates when there's an active deployment
117+
useEffect(() => {
118+
const hasActiveDeployment = project?.deployments.some(
119+
(d: Deployment) => d.status === 'building' || d.status === 'deploying'
120+
);
121+
122+
if (hasActiveDeployment) {
123+
const interval = setInterval(() => {
124+
loadProject();
125+
}, 3000);
126+
return () => clearInterval(interval);
127+
}
128+
}, [project]);
129+
109130
const loadLogs = async (deploymentId: string) => {
110131
try {
111132
const data = await deployments.getLogs(deploymentId);

0 commit comments

Comments
 (0)