Skip to content

Commit 4518ea2

Browse files
authored
Merge pull request #3010 from Dokploy/Improve-project-view-by-showing-last-deploy-rather-than-created
feat: add last deployment date to services and update sorting logic
2 parents 62474c1 + d549aa6 commit 4518ea2

File tree

2 files changed

+108
-25
lines changed

2 files changed

+108
-25
lines changed

apps/dokploy/pages/dashboard/project/[projectId]/environment/[environmentId].tsx

Lines changed: 98 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ export type Services = {
115115
id: string;
116116
createdAt: string;
117117
status?: "idle" | "running" | "done" | "error";
118+
lastDeployDate?: Date | null;
118119
};
119120

120121
type Project = Awaited<ReturnType<typeof findProjectById>>;
@@ -128,16 +129,34 @@ export const extractServicesFromEnvironment = (
128129
const allServices: Services[] = [];
129130

130131
const applications: Services[] =
131-
environment.applications?.map((item) => ({
132-
appName: item.appName,
133-
name: item.name,
134-
type: "application",
135-
id: item.applicationId,
136-
createdAt: item.createdAt,
137-
status: item.applicationStatus,
138-
description: item.description,
139-
serverId: item.serverId,
140-
})) || [];
132+
environment.applications?.map((item) => {
133+
// Get the most recent deployment date
134+
let lastDeployDate: Date | null = null;
135+
const deployments = (item as any).deployments;
136+
if (deployments && deployments.length > 0) {
137+
for (const deployment of deployments) {
138+
const deployDate = new Date(
139+
deployment.finishedAt ||
140+
deployment.startedAt ||
141+
deployment.createdAt,
142+
);
143+
if (!lastDeployDate || deployDate > lastDeployDate) {
144+
lastDeployDate = deployDate;
145+
}
146+
}
147+
}
148+
return {
149+
appName: item.appName,
150+
name: item.name,
151+
type: "application",
152+
id: item.applicationId,
153+
createdAt: item.createdAt,
154+
status: item.applicationStatus,
155+
description: item.description,
156+
serverId: item.serverId,
157+
lastDeployDate,
158+
};
159+
}) || [];
141160

142161
const mariadb: Services[] =
143162
environment.mariadb?.map((item) => ({
@@ -200,16 +219,34 @@ export const extractServicesFromEnvironment = (
200219
})) || [];
201220

202221
const compose: Services[] =
203-
environment.compose?.map((item) => ({
204-
appName: item.appName,
205-
name: item.name,
206-
type: "compose",
207-
id: item.composeId,
208-
createdAt: item.createdAt,
209-
status: item.composeStatus,
210-
description: item.description,
211-
serverId: item.serverId,
212-
})) || [];
222+
environment.compose?.map((item) => {
223+
// Get the most recent deployment date
224+
let lastDeployDate: Date | null = null;
225+
const deployments = (item as any).deployments;
226+
if (deployments && deployments.length > 0) {
227+
for (const deployment of deployments) {
228+
const deployDate = new Date(
229+
deployment.finishedAt ||
230+
deployment.startedAt ||
231+
deployment.createdAt,
232+
);
233+
if (!lastDeployDate || deployDate > lastDeployDate) {
234+
lastDeployDate = deployDate;
235+
}
236+
}
237+
}
238+
return {
239+
appName: item.appName,
240+
name: item.name,
241+
type: "compose",
242+
id: item.composeId,
243+
createdAt: item.createdAt,
244+
status: item.composeStatus,
245+
description: item.description,
246+
serverId: item.serverId,
247+
lastDeployDate,
248+
};
249+
}) || [];
213250

214251
allServices.push(
215252
...applications,
@@ -237,9 +274,9 @@ const EnvironmentPage = (
237274
const { data: auth } = api.user.get.useQuery();
238275
const [sortBy, setSortBy] = useState<string>(() => {
239276
if (typeof window !== "undefined") {
240-
return localStorage.getItem("servicesSort") || "createdAt-desc";
277+
return localStorage.getItem("servicesSort") || "lastDeploy-desc";
241278
}
242-
return "createdAt-desc";
279+
return "lastDeploy-desc";
243280
});
244281

245282
useEffect(() => {
@@ -261,10 +298,45 @@ const EnvironmentPage = (
261298
comparison =
262299
new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime();
263300
break;
301+
case "lastDeploy": {
302+
const aLastDeploy = a.lastDeployDate;
303+
const bLastDeploy = b.lastDeployDate;
304+
305+
if (direction === "desc") {
306+
// For "desc" (newest first): services with deployments first, then those without
307+
if (!aLastDeploy && !bLastDeploy) {
308+
comparison = 0;
309+
} else if (!aLastDeploy) {
310+
comparison = 1; // a (no deploy) goes after b (has deploy)
311+
} else if (!bLastDeploy) {
312+
comparison = -1; // a (has deploy) goes before b (no deploy)
313+
} else {
314+
// Both have deployments: newest first (negative if a is newer)
315+
comparison = bLastDeploy.getTime() - aLastDeploy.getTime();
316+
}
317+
} else {
318+
// For "asc" (oldest first): services with deployments first, then those without
319+
if (!aLastDeploy && !bLastDeploy) {
320+
comparison = 0;
321+
} else if (!aLastDeploy) {
322+
comparison = 1; // a (no deploy) goes after b (has deploy)
323+
} else if (!bLastDeploy) {
324+
comparison = -1; // a (has deploy) goes before b (no deploy)
325+
} else {
326+
// Both have deployments: oldest first
327+
comparison = aLastDeploy.getTime() - bLastDeploy.getTime();
328+
}
329+
}
330+
break;
331+
}
264332
default:
265333
comparison = 0;
266334
}
267-
return direction === "asc" ? comparison : -comparison;
335+
// For other fields, apply direction normally
336+
if (field !== "lastDeploy") {
337+
return direction === "asc" ? comparison : -comparison;
338+
}
339+
return comparison;
268340
});
269341
};
270342

@@ -1217,6 +1289,9 @@ const EnvironmentPage = (
12171289
<SelectValue placeholder="Sort by..." />
12181290
</SelectTrigger>
12191291
<SelectContent>
1292+
<SelectItem value="lastDeploy-desc">
1293+
Recently deployed
1294+
</SelectItem>
12201295
<SelectItem value="createdAt-desc">
12211296
Newest first
12221297
</SelectItem>

packages/server/src/services/environment.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,21 @@ export const findEnvironmentById = async (environmentId: string) => {
3434
const environment = await db.query.environments.findFirst({
3535
where: eq(environments.environmentId, environmentId),
3636
with: {
37-
applications: true,
37+
applications: {
38+
with: {
39+
deployments: true,
40+
},
41+
},
3842
mariadb: true,
3943
mongo: true,
4044
mysql: true,
4145
postgres: true,
4246
redis: true,
43-
compose: true,
47+
compose: {
48+
with: {
49+
deployments: true,
50+
},
51+
},
4452
project: true,
4553
},
4654
});

0 commit comments

Comments
 (0)