mirror of
https://github.com/Dokploy/dokploy
synced 2025-06-26 18:27:59 +00:00
Refactor ShowSchedulesLogs and ShowSchedules components
- Updated the ShowSchedulesLogs component to replace the trigger prop with children for better flexibility in rendering. - Enhanced the display logic in ShowSchedulesLogs to show a message when no logs are found, improving user feedback. - Added a Play icon to the ShowSchedules component for the manual run action, along with a tooltip for better user guidance. - Refactored the delete schedule button to provide success notifications upon deletion, enhancing user experience.
This commit is contained in:
@@ -13,17 +13,18 @@ import {
|
|||||||
import type { RouterOutputs } from "@/utils/api";
|
import type { RouterOutputs } from "@/utils/api";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { ShowDeployment } from "../deployments/show-deployment";
|
import { ShowDeployment } from "../deployments/show-deployment";
|
||||||
|
import { ClipboardList } from "lucide-react";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
deployments: RouterOutputs["deployment"]["all"];
|
deployments: RouterOutputs["deployment"]["all"];
|
||||||
serverId?: string;
|
serverId?: string;
|
||||||
trigger?: React.ReactNode;
|
children?: React.ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ShowSchedulesLogs = ({
|
export const ShowSchedulesLogs = ({
|
||||||
deployments,
|
deployments,
|
||||||
serverId,
|
serverId,
|
||||||
trigger,
|
children,
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
const [activeLog, setActiveLog] = useState<
|
const [activeLog, setActiveLog] = useState<
|
||||||
RouterOutputs["deployment"]["all"][number] | null
|
RouterOutputs["deployment"]["all"][number] | null
|
||||||
@@ -32,8 +33,8 @@ export const ShowSchedulesLogs = ({
|
|||||||
return (
|
return (
|
||||||
<Dialog open={isOpen} onOpenChange={setIsOpen}>
|
<Dialog open={isOpen} onOpenChange={setIsOpen}>
|
||||||
<DialogTrigger asChild>
|
<DialogTrigger asChild>
|
||||||
{trigger ? (
|
{children ? (
|
||||||
trigger
|
children
|
||||||
) : (
|
) : (
|
||||||
<Button className="sm:w-auto w-full" size="sm" variant="outline">
|
<Button className="sm:w-auto w-full" size="sm" variant="outline">
|
||||||
View Logs
|
View Logs
|
||||||
@@ -47,45 +48,53 @@ export const ShowSchedulesLogs = ({
|
|||||||
See all the logs for this schedule
|
See all the logs for this schedule
|
||||||
</DialogDescription>
|
</DialogDescription>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
<div className="grid gap-4">
|
{deployments.length > 0 ? (
|
||||||
{deployments?.map((deployment, index) => (
|
<div className="grid gap-4">
|
||||||
<div
|
{deployments.map((deployment, index) => (
|
||||||
key={deployment.deploymentId}
|
<div
|
||||||
className="flex items-center justify-between rounded-lg border p-4 gap-2"
|
key={deployment.deploymentId}
|
||||||
>
|
className="flex items-center justify-between rounded-lg border p-4 gap-2"
|
||||||
<div className="flex flex-col">
|
>
|
||||||
<span className="flex items-center gap-4 font-medium capitalize text-foreground">
|
<div className="flex flex-col">
|
||||||
{index + 1} {deployment.status}
|
<span className="flex items-center gap-4 font-medium capitalize text-foreground">
|
||||||
<StatusTooltip
|
{index + 1} {deployment.status}
|
||||||
status={deployment?.status}
|
<StatusTooltip
|
||||||
className="size-2.5"
|
status={deployment?.status}
|
||||||
/>
|
className="size-2.5"
|
||||||
</span>
|
/>
|
||||||
<span className="text-sm text-muted-foreground">
|
|
||||||
{deployment.title}
|
|
||||||
</span>
|
|
||||||
{deployment.description && (
|
|
||||||
<span className="break-all text-sm text-muted-foreground">
|
|
||||||
{deployment.description}
|
|
||||||
</span>
|
</span>
|
||||||
)}
|
<span className="text-sm text-muted-foreground">
|
||||||
</div>
|
{deployment.title}
|
||||||
<div className="flex flex-col items-end gap-2">
|
</span>
|
||||||
<div className="text-sm capitalize text-muted-foreground">
|
{deployment.description && (
|
||||||
<DateTooltip date={deployment.createdAt} />
|
<span className="break-all text-sm text-muted-foreground">
|
||||||
|
{deployment.description}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
<div className="flex flex-col items-end gap-2">
|
||||||
|
<div className="text-sm capitalize text-muted-foreground">
|
||||||
|
<DateTooltip date={deployment.createdAt} />
|
||||||
|
</div>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setActiveLog(deployment);
|
setActiveLog(deployment);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
View
|
View
|
||||||
</Button>
|
</Button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
))}
|
||||||
))}
|
</div>
|
||||||
</div>
|
) : (
|
||||||
|
<div className="flex flex-col items-center justify-center py-12 text-muted-foreground">
|
||||||
|
<ClipboardList className="size-12 mb-4" />
|
||||||
|
<p className="text-lg font-medium">No logs found</p>
|
||||||
|
<p className="text-sm">This schedule hasn't been executed yet</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
<ShowDeployment
|
<ShowDeployment
|
||||||
serverId={serverId || ""}
|
serverId={serverId || ""}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import {
|
|||||||
} from "@/components/ui/table";
|
} from "@/components/ui/table";
|
||||||
import { api } from "@/utils/api";
|
import { api } from "@/utils/api";
|
||||||
import { HandleSchedules } from "./handle-schedules";
|
import { HandleSchedules } from "./handle-schedules";
|
||||||
import { Clock, Terminal, Trash2 } from "lucide-react";
|
import { Clock, Play, Terminal, Trash2 } from "lucide-react";
|
||||||
import {
|
import {
|
||||||
Card,
|
Card,
|
||||||
CardContent,
|
CardContent,
|
||||||
@@ -20,6 +20,12 @@ import {
|
|||||||
import { Badge } from "@/components/ui/badge";
|
import { Badge } from "@/components/ui/badge";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
import { ShowSchedulesLogs } from "./show-schedules-logs";
|
import { ShowSchedulesLogs } from "./show-schedules-logs";
|
||||||
|
import {
|
||||||
|
Tooltip,
|
||||||
|
TooltipContent,
|
||||||
|
TooltipProvider,
|
||||||
|
TooltipTrigger,
|
||||||
|
} from "@/components/ui/tooltip";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
applicationId: string;
|
applicationId: string;
|
||||||
@@ -29,20 +35,21 @@ export const ShowSchedules = ({ applicationId }: Props) => {
|
|||||||
const { data: schedules } = api.schedule.list.useQuery({
|
const { data: schedules } = api.schedule.list.useQuery({
|
||||||
applicationId,
|
applicationId,
|
||||||
});
|
});
|
||||||
|
const utils = api.useUtils();
|
||||||
|
|
||||||
const { mutate: deleteSchedule } = api.schedule.delete.useMutation({
|
const { mutateAsync: deleteSchedule, isLoading: isDeleting } =
|
||||||
onSuccess: () => {
|
api.schedule.delete.useMutation({
|
||||||
utils.schedule.list.invalidate({ applicationId });
|
onSuccess: () => {
|
||||||
},
|
utils.schedule.list.invalidate({ applicationId });
|
||||||
});
|
},
|
||||||
|
});
|
||||||
|
|
||||||
const { mutateAsync: runManually } = api.schedule.runManually.useMutation({
|
const { mutateAsync: runManually, isLoading } =
|
||||||
onSuccess: () => {
|
api.schedule.runManually.useMutation({
|
||||||
utils.schedule.list.invalidate({ applicationId });
|
onSuccess: () => {
|
||||||
},
|
utils.schedule.list.invalidate({ applicationId });
|
||||||
});
|
},
|
||||||
|
});
|
||||||
const utils = api.useContext();
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card className="border px-4 shadow-none bg-transparent">
|
<Card className="border px-4 shadow-none bg-transparent">
|
||||||
@@ -114,27 +121,40 @@ export const ShowSchedules = ({ applicationId }: Props) => {
|
|||||||
deployments={deployments || []}
|
deployments={deployments || []}
|
||||||
serverId={application.serverId || undefined}
|
serverId={application.serverId || undefined}
|
||||||
/>
|
/>
|
||||||
<Button
|
|
||||||
variant="ghost"
|
<TooltipProvider delayDuration={0}>
|
||||||
size="sm"
|
<Tooltip>
|
||||||
onClick={async () => {
|
<TooltipTrigger asChild>
|
||||||
await runManually({
|
<Button
|
||||||
scheduleId: schedule.scheduleId,
|
type="button"
|
||||||
})
|
variant="ghost"
|
||||||
.then(() => {
|
isLoading={isLoading}
|
||||||
toast.success("Schedule run successfully");
|
onClick={async () => {
|
||||||
})
|
await runManually({
|
||||||
.catch((error) => {
|
scheduleId: schedule.scheduleId,
|
||||||
toast.error(
|
})
|
||||||
error instanceof Error
|
.then(() => {
|
||||||
? error.message
|
toast.success(
|
||||||
: "Error running schedule",
|
"Schedule run successfully",
|
||||||
);
|
);
|
||||||
});
|
})
|
||||||
}}
|
.catch((error) => {
|
||||||
>
|
toast.error(
|
||||||
Run Manual Schedule
|
error instanceof Error
|
||||||
</Button>
|
? error.message
|
||||||
|
: "Error running schedule",
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Play className="size-4" />
|
||||||
|
</Button>
|
||||||
|
</TooltipTrigger>
|
||||||
|
<TooltipContent>
|
||||||
|
Run Manual Schedule
|
||||||
|
</TooltipContent>
|
||||||
|
</Tooltip>
|
||||||
|
</TooltipProvider>
|
||||||
|
|
||||||
<HandleSchedules
|
<HandleSchedules
|
||||||
scheduleId={schedule.scheduleId}
|
scheduleId={schedule.scheduleId}
|
||||||
@@ -145,11 +165,24 @@ export const ShowSchedules = ({ applicationId }: Props) => {
|
|||||||
variant="ghost"
|
variant="ghost"
|
||||||
size="sm"
|
size="sm"
|
||||||
className="text-destructive hover:text-destructive"
|
className="text-destructive hover:text-destructive"
|
||||||
onClick={() =>
|
isLoading={isDeleting}
|
||||||
deleteSchedule({
|
onClick={async () => {
|
||||||
|
await deleteSchedule({
|
||||||
scheduleId: schedule.scheduleId,
|
scheduleId: schedule.scheduleId,
|
||||||
})
|
})
|
||||||
}
|
.then(() => {
|
||||||
|
toast.success(
|
||||||
|
"Schedule deleted successfully",
|
||||||
|
);
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
toast.error(
|
||||||
|
error instanceof Error
|
||||||
|
? error.message
|
||||||
|
: "Error deleting schedule",
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<Trash2 className="w-4 h-4" />
|
<Trash2 className="w-4 h-4" />
|
||||||
<span className="sr-only">Delete</span>
|
<span className="sr-only">Delete</span>
|
||||||
|
|||||||
Reference in New Issue
Block a user