Skip to content

Commit

Permalink
add to other tables
Browse files Browse the repository at this point in the history
  • Loading branch information
adityachoudhari26 committed Mar 3, 2025
1 parent 5e2e2a4 commit 7e1ba73
Show file tree
Hide file tree
Showing 10 changed files with 322 additions and 115 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { useParams, useRouter } from "next/navigation";
import {
IconCircleFilled,
IconFilter,
IconFolder,
IconGraph,
IconHistory,
IconLoader2,
Expand Down Expand Up @@ -42,15 +43,20 @@ import { ReleaseStatus } from "@ctrlplane/validators/releases";
import { ReleaseConditionBadge } from "~/app/[workspaceSlug]/(appv2)/_components/release/condition/ReleaseConditionBadge";
import { ReleaseConditionDialog } from "~/app/[workspaceSlug]/(appv2)/_components/release/condition/ReleaseConditionDialog";
import { useReleaseFilter } from "~/app/[workspaceSlug]/(appv2)/_components/release/condition/useReleaseFilter";
import { DeploymentDirectoryCell } from "~/app/[workspaceSlug]/(appv2)/(deploy)/_components/deployments/DeploymentDirectoryCell";
import { urls } from "~/app/urls";
import { api } from "~/trpc/react";
import { JobHistoryPopover } from "./JobHistoryPopover";
import { ReleaseDistributionGraphPopover } from "./ReleaseDistributionPopover";
import { LazyReleaseEnvironmentCell } from "./ReleaseEnvironmentCell";

type Environment = RouterOutputs["environment"]["bySystemId"][number];
type Deployment = NonNullable<RouterOutputs["deployment"]["bySlug"]>;

type EnvHeaderProps = { environment: Environment; deployment: Deployment };
type EnvHeaderProps = {
environment: schema.Environment;
deployment: Deployment;
workspace: schema.Workspace;
};

const StatusIcon: React.FC<{ status: ReleaseStatusType }> = ({ status }) => {
if (status === ReleaseStatus.Ready)
Expand All @@ -77,12 +83,11 @@ const StatusIcon: React.FC<{ status: ReleaseStatusType }> = ({ status }) => {
);
};

const EnvHeader: React.FC<EnvHeaderProps> = ({ environment, deployment }) => {
const { workspaceSlug } = useParams<{ workspaceSlug: string }>();
const { data: workspace, isLoading: isWorkspaceLoading } =
api.workspace.bySlug.useQuery(workspaceSlug);
const workspaceId = workspace?.id ?? "";

const EnvHeader: React.FC<EnvHeaderProps> = ({
environment,
deployment,
workspace,
}) => {
const { resourceFilter: envResourceFilter } = environment;
const { resourceFilter: deploymentResourceFilter } = deployment;

Expand All @@ -92,15 +97,12 @@ const EnvHeader: React.FC<EnvHeaderProps> = ({ environment, deployment }) => {
conditions: [envResourceFilter, deploymentResourceFilter].filter(isPresent),
};

const { data: resourcesResult, isLoading: isResourcesLoading } =
api.resource.byWorkspaceId.list.useQuery(
{ workspaceId, filter, limit: 0 },
{ enabled: workspaceId !== "" && envResourceFilter != null },
);

const total = resourcesResult?.total ?? 0;
const { data, isLoading } = api.resource.byWorkspaceId.list.useQuery(
{ workspaceId: workspace.id, filter, limit: 0 },
{ enabled: envResourceFilter != null },
);

const isLoading = isWorkspaceLoading || isResourcesLoading;
const total = data?.total ?? 0;

return (
<TableHead className="border-l pl-4">
Expand All @@ -120,23 +122,72 @@ const EnvHeader: React.FC<EnvHeaderProps> = ({ environment, deployment }) => {
);
};

type DirectoryHeaderProps = {
directory: { path: string; environments: schema.Environment[] };
workspace: schema.Workspace;
};

const DirectoryHeader: React.FC<DirectoryHeaderProps> = ({
directory,
workspace,
}) => {
const resourceFilters = directory.environments
.map((env) => env.resourceFilter)
.filter(isPresent);
const filter: ResourceCondition | undefined =
resourceFilters.length > 0
? {
type: FilterType.Comparison,
operator: ComparisonOperator.Or,
conditions: resourceFilters,
}
: undefined;

const { data, isLoading } = api.resource.byWorkspaceId.list.useQuery(
{ workspaceId: workspace.id, filter, limit: 0 },
{ enabled: filter != null },
);

const total = data?.total ?? 0;

return (
<TableHead className="w-[220px] border-l p-2" key={directory.path}>
<div className="flex w-fit items-center gap-2 px-2 py-1 text-white">
<span className="max-w-32 truncate">{directory.path}</span>

<Badge variant="outline" className="rounded-full text-muted-foreground">
{isLoading && (
<IconLoader2 className="h-3 w-3 animate-spin text-muted-foreground" />
)}
{!isLoading && total}
</Badge>

<Badge variant="outline" className="rounded-full text-muted-foreground">
<IconFolder className="h-4 w-4" strokeWidth={1.5} />
</Badge>
</div>
</TableHead>
);
};

type DeploymentPageContentProps = {
workspace: schema.Workspace;
deployment: Deployment;
environments: Environment[];
environments: schema.Environment[];
directories: { path: string; environments: schema.Environment[] }[];
releaseChannel: schema.ReleaseChannel | null;
};

export const DeploymentPageContent: React.FC<DeploymentPageContentProps> = ({
workspace,
deployment,
environments,
directories,
releaseChannel,
}) => {
const { filter, setFilter } = useReleaseFilter();

const { workspaceSlug, systemSlug } = useParams<{
workspaceSlug: string;
systemSlug: string;
}>();
const { systemSlug } = useParams<{ systemSlug: string }>();

const releases = api.release.list.useQuery(
{ deploymentId: deployment.id, filter: filter ?? undefined, limit: 30 },
Expand All @@ -148,6 +199,11 @@ export const DeploymentPageContent: React.FC<DeploymentPageContentProps> = ({
const loading = releases.isLoading;
const router = useRouter();

const releaseUrl = urls
.workspace(workspace.slug)
.system(systemSlug)
.deployment(deployment.slug).release;

return (
<div className="flex flex-col">
<div className="flex items-center gap-4 border-b border-neutral-800 p-1 px-2 text-sm">
Expand Down Expand Up @@ -234,6 +290,14 @@ export const DeploymentPageContent: React.FC<DeploymentPageContentProps> = ({
key={env.id}
environment={env}
deployment={deployment}
workspace={workspace}
/>
))}
{directories.map((dir) => (
<DirectoryHeader
key={dir.path}
directory={dir}
workspace={workspace}
/>
))}
</TableRow>
Expand All @@ -245,9 +309,7 @@ export const DeploymentPageContent: React.FC<DeploymentPageContentProps> = ({
key={release.id}
className="cursor-pointer hover:bg-transparent"
onClick={() =>
router.push(
`/${workspaceSlug}/systems/${systemSlug}/deployments/${deployment.slug}/releases/${release.id}`,
)
router.push(releaseUrl(release.id).baseUrl())
}
>
<TableCell className="sticky left-0 z-10 flex h-[60px] min-w-[400px] max-w-[750px] items-center gap-2 bg-background/95 text-base">
Expand Down Expand Up @@ -290,6 +352,20 @@ export const DeploymentPageContent: React.FC<DeploymentPageContentProps> = ({
/>
</TableCell>
))}
{directories.map((dir) => (
<TableCell
key={dir.path}
className="h-[60px] w-[220px] border-l px-1 py-0"
>
<DeploymentDirectoryCell
key={dir.path}
directory={dir}
deployment={deployment}
release={release}
systemSlug={systemSlug}
/>
</TableCell>
))}
</TableRow>
);
})}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
"use client";

import type { RouterOutputs } from "@ctrlplane/api";
import type * as SCHEMA from "@ctrlplane/db/schema";
import type { ReleaseStatusType } from "@ctrlplane/validators/releases";
import { useParams } from "next/navigation";
Expand All @@ -16,7 +15,6 @@ import { api } from "~/trpc/react";
import { DeployButton } from "./DeployButton";
import { Release } from "./TableCells";

type Environment = RouterOutputs["environment"]["bySystemId"][number];
type Release = {
id: string;
version: string;
Expand All @@ -26,7 +24,7 @@ type Release = {
};

type ReleaseEnvironmentCellProps = {
environment: Environment;
environment: SCHEMA.Environment;
deployment: SCHEMA.Deployment;
release: Release;
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,19 +28,25 @@ export async function generateMetadata(props: PageProps): Promise<Metadata> {
export default async function DeploymentPage(props: PageProps) {
const searchParams = await props.searchParams;
const params = await props.params;
const workspace = await api.workspace.bySlug(params.workspaceSlug);
if (workspace == null) return notFound();
const deployment = await api.deployment.bySlug(params);
if (deployment == null) return notFound();
const { system } = deployment;
const environments = await api.environment.bySystemId(system.id);
const roots = await api.system.directory.listRoots(system.id);
const { rootEnvironments: environments, directories } = roots;
const releaseChannel = searchParams["release-channel-id"]
? await api.deployment.releaseChannel.byId(
searchParams["release-channel-id"],
)
: null;

return (
<DeploymentPageContent
workspace={workspace}
deployment={deployment}
environments={environments}
directories={directories}
releaseChannel={releaseChannel}
/>
);
Expand Down
Loading

0 comments on commit 7e1ba73

Please sign in to comment.