mirror of
https://github.com/andwati/dokploy.git
synced 2026-11-11 14:35:17 +00:00
feat: add last deployment date to services and update sorting logic
- Introduced `lastDeployDate` property to track the most recent deployment for applications and compose services. - Updated the `extractServicesFromEnvironment` function to calculate and include the last deployment date. - Modified sorting logic to allow sorting by last deployment date, enhancing the user experience on the environment dashboard. - Adjusted local storage default sort preference to prioritize last deployment date.
This commit is contained in:
@@ -115,6 +115,7 @@ export type Services = {
|
|||||||
id: string;
|
id: string;
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
status?: "idle" | "running" | "done" | "error";
|
status?: "idle" | "running" | "done" | "error";
|
||||||
|
lastDeployDate?: Date | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
type Project = Awaited<ReturnType<typeof findProjectById>>;
|
type Project = Awaited<ReturnType<typeof findProjectById>>;
|
||||||
@@ -128,16 +129,34 @@ export const extractServicesFromEnvironment = (
|
|||||||
const allServices: Services[] = [];
|
const allServices: Services[] = [];
|
||||||
|
|
||||||
const applications: Services[] =
|
const applications: Services[] =
|
||||||
environment.applications?.map((item) => ({
|
environment.applications?.map((item) => {
|
||||||
appName: item.appName,
|
// Get the most recent deployment date
|
||||||
name: item.name,
|
let lastDeployDate: Date | null = null;
|
||||||
type: "application",
|
const deployments = (item as any).deployments;
|
||||||
id: item.applicationId,
|
if (deployments && deployments.length > 0) {
|
||||||
createdAt: item.createdAt,
|
for (const deployment of deployments) {
|
||||||
status: item.applicationStatus,
|
const deployDate = new Date(
|
||||||
description: item.description,
|
deployment.finishedAt ||
|
||||||
serverId: item.serverId,
|
deployment.startedAt ||
|
||||||
})) || [];
|
deployment.createdAt,
|
||||||
|
);
|
||||||
|
if (!lastDeployDate || deployDate > lastDeployDate) {
|
||||||
|
lastDeployDate = deployDate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
appName: item.appName,
|
||||||
|
name: item.name,
|
||||||
|
type: "application",
|
||||||
|
id: item.applicationId,
|
||||||
|
createdAt: item.createdAt,
|
||||||
|
status: item.applicationStatus,
|
||||||
|
description: item.description,
|
||||||
|
serverId: item.serverId,
|
||||||
|
lastDeployDate,
|
||||||
|
};
|
||||||
|
}) || [];
|
||||||
|
|
||||||
const mariadb: Services[] =
|
const mariadb: Services[] =
|
||||||
environment.mariadb?.map((item) => ({
|
environment.mariadb?.map((item) => ({
|
||||||
@@ -200,16 +219,34 @@ export const extractServicesFromEnvironment = (
|
|||||||
})) || [];
|
})) || [];
|
||||||
|
|
||||||
const compose: Services[] =
|
const compose: Services[] =
|
||||||
environment.compose?.map((item) => ({
|
environment.compose?.map((item) => {
|
||||||
appName: item.appName,
|
// Get the most recent deployment date
|
||||||
name: item.name,
|
let lastDeployDate: Date | null = null;
|
||||||
type: "compose",
|
const deployments = (item as any).deployments;
|
||||||
id: item.composeId,
|
if (deployments && deployments.length > 0) {
|
||||||
createdAt: item.createdAt,
|
for (const deployment of deployments) {
|
||||||
status: item.composeStatus,
|
const deployDate = new Date(
|
||||||
description: item.description,
|
deployment.finishedAt ||
|
||||||
serverId: item.serverId,
|
deployment.startedAt ||
|
||||||
})) || [];
|
deployment.createdAt,
|
||||||
|
);
|
||||||
|
if (!lastDeployDate || deployDate > lastDeployDate) {
|
||||||
|
lastDeployDate = deployDate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
appName: item.appName,
|
||||||
|
name: item.name,
|
||||||
|
type: "compose",
|
||||||
|
id: item.composeId,
|
||||||
|
createdAt: item.createdAt,
|
||||||
|
status: item.composeStatus,
|
||||||
|
description: item.description,
|
||||||
|
serverId: item.serverId,
|
||||||
|
lastDeployDate,
|
||||||
|
};
|
||||||
|
}) || [];
|
||||||
|
|
||||||
allServices.push(
|
allServices.push(
|
||||||
...applications,
|
...applications,
|
||||||
@@ -237,9 +274,9 @@ const EnvironmentPage = (
|
|||||||
const { data: auth } = api.user.get.useQuery();
|
const { data: auth } = api.user.get.useQuery();
|
||||||
const [sortBy, setSortBy] = useState<string>(() => {
|
const [sortBy, setSortBy] = useState<string>(() => {
|
||||||
if (typeof window !== "undefined") {
|
if (typeof window !== "undefined") {
|
||||||
return localStorage.getItem("servicesSort") || "createdAt-desc";
|
return localStorage.getItem("servicesSort") || "lastDeploy-desc";
|
||||||
}
|
}
|
||||||
return "createdAt-desc";
|
return "lastDeploy-desc";
|
||||||
});
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -261,10 +298,45 @@ const EnvironmentPage = (
|
|||||||
comparison =
|
comparison =
|
||||||
new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime();
|
new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime();
|
||||||
break;
|
break;
|
||||||
|
case "lastDeploy": {
|
||||||
|
const aLastDeploy = a.lastDeployDate;
|
||||||
|
const bLastDeploy = b.lastDeployDate;
|
||||||
|
|
||||||
|
if (direction === "desc") {
|
||||||
|
// For "desc" (newest first): services with deployments first, then those without
|
||||||
|
if (!aLastDeploy && !bLastDeploy) {
|
||||||
|
comparison = 0;
|
||||||
|
} else if (!aLastDeploy) {
|
||||||
|
comparison = 1; // a (no deploy) goes after b (has deploy)
|
||||||
|
} else if (!bLastDeploy) {
|
||||||
|
comparison = -1; // a (has deploy) goes before b (no deploy)
|
||||||
|
} else {
|
||||||
|
// Both have deployments: newest first (negative if a is newer)
|
||||||
|
comparison = bLastDeploy.getTime() - aLastDeploy.getTime();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// For "asc" (oldest first): services with deployments first, then those without
|
||||||
|
if (!aLastDeploy && !bLastDeploy) {
|
||||||
|
comparison = 0;
|
||||||
|
} else if (!aLastDeploy) {
|
||||||
|
comparison = 1; // a (no deploy) goes after b (has deploy)
|
||||||
|
} else if (!bLastDeploy) {
|
||||||
|
comparison = -1; // a (has deploy) goes before b (no deploy)
|
||||||
|
} else {
|
||||||
|
// Both have deployments: oldest first
|
||||||
|
comparison = aLastDeploy.getTime() - bLastDeploy.getTime();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
comparison = 0;
|
comparison = 0;
|
||||||
}
|
}
|
||||||
return direction === "asc" ? comparison : -comparison;
|
// For other fields, apply direction normally
|
||||||
|
if (field !== "lastDeploy") {
|
||||||
|
return direction === "asc" ? comparison : -comparison;
|
||||||
|
}
|
||||||
|
return comparison;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1217,6 +1289,9 @@ const EnvironmentPage = (
|
|||||||
<SelectValue placeholder="Sort by..." />
|
<SelectValue placeholder="Sort by..." />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
|
<SelectItem value="lastDeploy-desc">
|
||||||
|
Recently deployed
|
||||||
|
</SelectItem>
|
||||||
<SelectItem value="createdAt-desc">
|
<SelectItem value="createdAt-desc">
|
||||||
Newest first
|
Newest first
|
||||||
</SelectItem>
|
</SelectItem>
|
||||||
|
|||||||
@@ -34,13 +34,21 @@ export const findEnvironmentById = async (environmentId: string) => {
|
|||||||
const environment = await db.query.environments.findFirst({
|
const environment = await db.query.environments.findFirst({
|
||||||
where: eq(environments.environmentId, environmentId),
|
where: eq(environments.environmentId, environmentId),
|
||||||
with: {
|
with: {
|
||||||
applications: true,
|
applications: {
|
||||||
|
with: {
|
||||||
|
deployments: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
mariadb: true,
|
mariadb: true,
|
||||||
mongo: true,
|
mongo: true,
|
||||||
mysql: true,
|
mysql: true,
|
||||||
postgres: true,
|
postgres: true,
|
||||||
redis: true,
|
redis: true,
|
||||||
compose: true,
|
compose: {
|
||||||
|
with: {
|
||||||
|
deployments: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
project: true,
|
project: true,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user