Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

style(preview-deployment): better preview deployment card #938

Merged
merged 6 commits into from
Dec 23, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Next Next commit
style: better preview deployment card
  • Loading branch information
190km committed Dec 18, 2024
commit 3858205e520c44a24c912f58565c50b009d45d9f
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
import { StatusTooltip } from "@/components/shared/status-tooltip";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Separator } from "@/components/ui/separator";
import { Clock, GitBranch, GitPullRequest, Pencil } from "lucide-react";
import Link from "next/link";
import { ShowModalLogs } from "../../settings/web-server/show-modal-logs";
import { DialogAction } from "@/components/shared/dialog-action";
import { ShowPreviewBuilds } from "./show-preview-builds";
import { RouterOutputs } from "@/utils/api";
import { AddPreviewDomain } from "./add-preview-domain";
import { DateTooltip } from "@/components/shared/date-tooltip";

interface PreviewDeploymentCardProps {
appName: string;
serverId: string;
onDeploymentDelete: (deploymentId: string) => void;
deploymentId: string;
deploymentUrl: string;
deployments: RouterOutputs["deployment"]["all"];

domainId: string;
domainHost: string;

pullRequestTitle: string;
pullRequestUrl: string;
status: "running" | "error" | "done" | "idle" | undefined | null;
branch: string;
date: string;
isLoading: boolean;
}

export function PreviewDeploymentCard({
appName,
serverId,

onDeploymentDelete,
deploymentId,
deployments,

domainId,
domainHost,

pullRequestTitle,
pullRequestUrl,
isLoading,
status,
branch,
date,
}: PreviewDeploymentCardProps) {
return (
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel is better to just pass the deploymentId and the serverId, and then inside the component use this hook

const { data: previewDeployment } = api.previewDeployment.one.useQuery({ previewDeploymentId: previewDeploymentId, });
In this way we avoid passing too many props, and thus isolate the component in a more elegant way.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think we must left onDeploymentDelete because we need the to refetch deployments when deleting one & isLoading on deleting.

Copy link
Contributor

@Siumauricio Siumauricio Dec 21, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can also abstract and put the handleDeletePreviewDeployment inside the preview-deployment-card.tsx

in this case we reduce the props we need to pass, we remove the isLoading and the onDeploymentDelete prop

<div className="w-full border rounded-xl">
<div className="p-6 flex flex-row items-center justify-between">
<span className="text-lg font-bold">{pullRequestTitle}</span>
<Badge variant="outline" className="text-sm font-medium gap-x-2">
<StatusTooltip status={status} className="size-2.5" />
{status
?.replace("running", "Running")
.replace("done", "Done")
.replace("error", "Error")
.replace("idle", "Idle") || "Idle"}
</Badge>
</div>
<div className="p-6 pt-0 space-y-4">
<div className="flex sm:flex-row flex-col items-center gap-2">
<div className="gap-2 flex w-full sm:flex-row flex-col items-center justify-between rounded-lg border p-2">
<Link href={`http://${domainHost}`} target="_blank" className="text-sm text-blue-500/95 hover:underline">
{domainHost}
</Link>
</div>
<AddPreviewDomain
previewDeploymentId={deploymentId}
domainId={domainId}
>
<Button className="sm:w-auto w-full" size="sm" variant="outline">
<Pencil className="mr-2 size-4" />
Edit
</Button>
</AddPreviewDomain>
</div>
<div className="flex sm:flex-row text-sm flex-col items-center justify-between">
<div className="flex items-center space-x-2">
<GitBranch className="h-5 w-5 text-gray-400" />
<span>Branch:</span>
<Badge className="p-2" variant={"blank"}>
{" "}
{branch}
</Badge>
</div>
<div className="flex items-center space-x-2">
<Clock className="h-5 w-5 text-gray-400" />
<span>Deployed: </span>
<Badge className="p-2" variant={"blank"}>
<DateTooltip date={date} />
</Badge>
</div>
</div>
<Separator />
<div className="rounded-lg bg-muted p-4">
<h3 className="mb-2 text-sm font-medium">Pull Request</h3>
<div className="flex items-center space-x-2 text-sm text-muted-foreground">
<GitPullRequest className="h-5 w-5 text-gray-400" />
<Link
className="hover:text-blue-500/95 hover:underline"
target="_blank"
href={pullRequestUrl}
>
{pullRequestTitle}
</Link>
</div>
</div>
</div>
<div className="justify-center flex-wrap p-6 pt-0">
<div className="flex flex-wrap justify-end gap-2">
<ShowPreviewBuilds deployments={deployments} serverId={serverId} />

<ShowModalLogs appName={appName} serverId={serverId}>
<Button className="sm:w-auto w-full" variant="outline" size="sm">
View Logs
</Button>
</ShowModalLogs>

<DialogAction
title="Delete Preview"
description="Are you sure you want to delete this preview?"
onClick={() => onDeploymentDelete(deploymentId)}
>
<Button
className="sm:w-auto w-full"
variant="destructive"
isLoading={isLoading}
size="sm"
>
Delete Preview
</Button>
</DialogAction>
</div>
</div>
</div>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export const ShowPreviewBuilds = ({ deployments, serverId }: Props) => {
return (
<Dialog open={isOpen} onOpenChange={setIsOpen}>
<DialogTrigger asChild>
<Button variant="outline">View Builds</Button>
<Button className="sm:w-auto w-full" size="sm" variant="outline">View Builds</Button>
</DialogTrigger>
<DialogContent className="max-h-screen overflow-y-auto sm:max-w-5xl">
<DialogHeader>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,26 +8,18 @@ import {
CardHeader,
CardTitle,
} from "@/components/ui/card";
import { Switch } from "@/components/ui/switch";
import { api } from "@/utils/api";
import { Pencil, RocketIcon } from "lucide-react";
import React, { useEffect, useState } from "react";
import { RocketIcon } from "lucide-react";
import React, { useState } from "react";
import { toast } from "sonner";
import { ShowDeployment } from "../deployments/show-deployment";
import Link from "next/link";
import { ShowModalLogs } from "../../settings/web-server/show-modal-logs";
import { DialogAction } from "@/components/shared/dialog-action";
import { AddPreviewDomain } from "./add-preview-domain";
import { GithubIcon } from "@/components/icons/data-tools-icons";
import { PreviewDeploymentCard } from "./preview-deployment-card";
import { ShowPreviewSettings } from "./show-preview-settings";
import { ShowPreviewBuilds } from "./show-preview-builds";

interface Props {
applicationId: string;
}

export const ShowPreviewDeployments = ({ applicationId }: Props) => {
const [activeLog, setActiveLog] = useState<string | null>(null);
const { data } = api.application.one.useQuery({ applicationId });

const { mutateAsync: deletePreviewDeployment, isLoading } =
Expand All @@ -39,6 +31,21 @@ export const ShowPreviewDeployments = ({ applicationId }: Props) => {
enabled: !!applicationId,
},
);


const handleDeletePreviewDeployment = async (previewDeploymentId: string) => {
deletePreviewDeployment({
previewDeploymentId: previewDeploymentId,
})
.then(() => {
refetchPreviewDeployments();
toast.success("Preview deployment deleted");
})
.catch((error) => {
toast.error(error.message);
});
};

// const [url, setUrl] = React.useState("");
// useEffect(() => {
// setUrl(document.location.origin);
Expand Down Expand Up @@ -77,125 +84,43 @@ export const ShowPreviewDeployments = ({ applicationId }: Props) => {
{previewDeployments?.map((previewDeployment) => {
const { deployments, domain } = previewDeployment;

return (
<div
key={previewDeployment?.previewDeploymentId}
className="flex flex-col justify-between rounded-lg border p-4 gap-2"
>
<div className="flex justify-between gap-2 max-sm:flex-wrap">
<div className="flex flex-col gap-2">
{deployments?.length === 0 ? (
<div>
<span className="text-sm text-muted-foreground">
No deployments found
</span>
</div>
) : (
<div className="flex items-center gap-2">
<span className="flex items-center gap-4 font-medium capitalize text-foreground">
{previewDeployment?.pullRequestTitle}
</span>
<StatusTooltip
status={previewDeployment.previewStatus}
className="size-2.5"
/>
</div>
)}
<div className="flex flex-col gap-1">
{previewDeployment?.pullRequestTitle && (
<div className="flex items-center gap-2">
<span className="break-all text-sm text-muted-foreground w-fit">
Title: {previewDeployment?.pullRequestTitle}
</span>
</div>
)}

{previewDeployment?.pullRequestURL && (
<div className="flex items-center gap-2">
<GithubIcon />
<Link
target="_blank"
href={previewDeployment?.pullRequestURL}
className="break-all text-sm text-muted-foreground w-fit hover:underline hover:text-foreground"
>
Pull Request URL
</Link>
</div>
)}
</div>
<div className="flex flex-col ">
<span>Domain </span>
<div className="flex flex-row items-center gap-4">
<Link
target="_blank"
href={`http://${domain?.host}`}
className="text-sm text-muted-foreground w-fit hover:underline hover:text-foreground"
>
{domain?.host}
</Link>
<AddPreviewDomain
previewDeploymentId={
previewDeployment.previewDeploymentId
}
domainId={domain?.domainId}
>
<Button variant="outline" size="sm">
<Pencil className="size-4 text-muted-foreground" />
</Button>
</AddPreviewDomain>
</div>
</div>
</div>

<div className="flex flex-col sm:items-end gap-2 max-sm:w-full">
{previewDeployment?.createdAt && (
<div className="text-sm capitalize text-muted-foreground">
<DateTooltip
date={previewDeployment?.createdAt}
/>
</div>
)}
<ShowPreviewBuilds
deployments={previewDeployment?.deployments || []}
serverId={data?.serverId || ""}
/>

<ShowModalLogs
appName={previewDeployment.appName}
serverId={data?.serverId || ""}
>
<Button variant="outline">View Logs</Button>
</ShowModalLogs>

<DialogAction
title="Delete Preview"
description="Are you sure you want to delete this preview?"
onClick={() => {
deletePreviewDeployment({
previewDeploymentId:
previewDeployment.previewDeploymentId,
})
.then(() => {
refetchPreviewDeployments();
toast.success("Preview deployment deleted");
})
.catch((error) => {
toast.error(error.message);
});
}}
>
<Button variant="destructive" isLoading={isLoading}>
Delete Preview
</Button>
</DialogAction>
</div>
</div>
</div>
);
})}
</div>
)}
</>
return (
<div className="flex justify-between gap-2 w-full">
<div className="flex w-full flex-col gap-2">
{deployments?.length === 0 ? (
<div>
<span className="text-sm text-muted-foreground">
No deployments found
</span>
</div>
) : (
<PreviewDeploymentCard
key={previewDeployment?.previewDeploymentId}
appName={previewDeployment.appName}
serverId={data?.serverId || ""}
onDeploymentDelete={handleDeletePreviewDeployment}
deploymentId={previewDeployment.previewDeploymentId}
deploymentUrl={`http://${domain?.host}`}
deployments={previewDeployment?.deployments || []}
domainId={domain?.domainId}
domainHost={domain?.host}
pullRequestTitle={
previewDeployment?.pullRequestTitle
}
pullRequestUrl={previewDeployment?.pullRequestURL}
status={previewDeployment.previewStatus}
branch={previewDeployment?.branch}
date={previewDeployment?.createdAt}
isLoading={isLoading}
/>
)}
</div>
</div>
);
})}
</div>
)}
</>
) : (
<div className="flex w-full flex-col items-center justify-center gap-3 pt-10">
<RocketIcon className="size-8 text-muted-foreground" />
Expand Down
Loading