Domain
diff --git a/web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/(overview)/deployments/components/table/components/actions/deployment-list-table-action.popover.constants.tsx b/web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/(overview)/deployments/components/table/components/actions/deployment-list-table-action.popover.constants.tsx
index 358ffc21b2..c9ff73e57a 100644
--- a/web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/(overview)/deployments/components/table/components/actions/deployment-list-table-action.popover.constants.tsx
+++ b/web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/(overview)/deployments/components/table/components/actions/deployment-list-table-action.popover.constants.tsx
@@ -1,9 +1,8 @@
"use client";
-import { useProject } from "@/app/(app)/[workspaceSlug]/projects/[projectId]/(overview)/layout-provider";
+import { useProjectData } from "@/app/(app)/[workspaceSlug]/projects/[projectId]/(overview)/data-provider";
import { type MenuItem, TableActionPopover } from "@/components/logs/table-action.popover";
import { useWorkspaceNavigation } from "@/hooks/use-workspace-navigation";
import type { Deployment, Environment } from "@/lib/collections";
-import { eq, useLiveQuery } from "@tanstack/react-db";
import { ArrowDottedRotateAnticlockwise, ChevronUp, Layers3 } from "@unkey/icons";
import { useRouter } from "next/navigation";
import { useMemo } from "react";
@@ -22,13 +21,10 @@ export const DeploymentListTableActions = ({
environment,
}: DeploymentListTableActionsProps) => {
const workspace = useWorkspaceNavigation();
- const { collections } = useProject();
- const { data } = useLiveQuery((q) =>
- q
- .from({ domain: collections.domains })
- .where(({ domain }) => eq(domain.deploymentId, selectedDeployment.id))
- .select(({ domain }) => ({ host: domain.fullyQualifiedDomainName })),
- );
+ const { getDomainsForDeployment } = useProjectData();
+ const data = getDomainsForDeployment(selectedDeployment.id).map((domain) => ({
+ host: domain.fullyQualifiedDomainName,
+ }));
const router = useRouter();
// biome-ignore lint/correctness/useExhaustiveDependencies: its okay
diff --git a/web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/(overview)/deployments/components/table/components/actions/promotion-dialog.tsx b/web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/(overview)/deployments/components/table/components/actions/promotion-dialog.tsx
index 155c152226..9e9c18c1af 100644
--- a/web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/(overview)/deployments/components/table/components/actions/promotion-dialog.tsx
+++ b/web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/(overview)/deployments/components/table/components/actions/promotion-dialog.tsx
@@ -1,6 +1,6 @@
"use client";
-import { type Deployment, collection, collectionManager } from "@/lib/collections";
+import { type Deployment, collection } from "@/lib/collections";
import { shortenId } from "@/lib/shorten-id";
import { trpc } from "@/lib/trpc/client";
import { eq, inArray, useLiveQuery } from "@tanstack/react-db";
@@ -22,14 +22,14 @@ export const PromotionDialog = ({
liveDeployment,
}: PromotionDialogProps) => {
const utils = trpc.useUtils();
- const domainCollection = collectionManager.getProjectCollections(
- liveDeployment.projectId,
- ).domains;
- const domains = useLiveQuery((q) =>
- q
- .from({ domain: domainCollection })
- .where(({ domain }) => inArray(domain.sticky, ["environment", "live"]))
- .where(({ domain }) => eq(domain.deploymentId, liveDeployment.id)),
+ const domains = useLiveQuery(
+ (q) =>
+ q
+ .from({ domain: collection.domains })
+ .where(({ domain }) => eq(domain.projectId, liveDeployment.projectId))
+ .where(({ domain }) => inArray(domain.sticky, ["environment", "live"]))
+ .where(({ domain }) => eq(domain.deploymentId, liveDeployment.id)),
+ [liveDeployment.projectId, liveDeployment.id],
);
const promote = trpc.deploy.deployment.promote.useMutation({
onSuccess: () => {
@@ -39,11 +39,8 @@ export const PromotionDialog = ({
});
// hack to revalidate
try {
- // @ts-expect-error Their docs say it's here
collection.projects.utils.refetch();
- // @ts-expect-error Their docs say it's here
collection.deployments.utils.refetch();
- // @ts-expect-error Their docs say it's here
collection.domains.utils.refetch();
} catch (error) {
console.error("Refetch error:", error);
diff --git a/web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/(overview)/deployments/components/table/components/actions/rollback-dialog.tsx b/web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/(overview)/deployments/components/table/components/actions/rollback-dialog.tsx
index afb05b5585..b1cc8f1acb 100644
--- a/web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/(overview)/deployments/components/table/components/actions/rollback-dialog.tsx
+++ b/web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/(overview)/deployments/components/table/components/actions/rollback-dialog.tsx
@@ -2,9 +2,9 @@
import { type Deployment, collection } from "@/lib/collections";
import { trpc } from "@/lib/trpc/client";
-import { inArray, useLiveQuery } from "@tanstack/react-db";
+import { eq, inArray, useLiveQuery } from "@tanstack/react-db";
import { Button, DialogContainer, toast } from "@unkey/ui";
-import { useProject } from "../../../../../layout-provider";
+import { useProjectData } from "../../../../../data-provider";
import { DeploymentSection } from "./components/deployment-section";
import { DomainsSection } from "./components/domains-section";
@@ -23,13 +23,14 @@ export const RollbackDialog = ({
}: RollbackDialogProps) => {
const utils = trpc.useUtils();
- const {
- collections: { domains: domainCollection },
- } = useProject();
- const domains = useLiveQuery((q) =>
- q
- .from({ domain: domainCollection })
- .where(({ domain }) => inArray(domain.sticky, ["environment", "live"])),
+ const { projectId } = useProjectData();
+ const domains = useLiveQuery(
+ (q) =>
+ q
+ .from({ domain: collection.domains })
+ .where(({ domain }) => eq(domain.projectId, projectId))
+ .where(({ domain }) => inArray(domain.sticky, ["environment", "live"])),
+ [projectId],
);
const rollback = trpc.deploy.deployment.rollback.useMutation({
@@ -40,11 +41,8 @@ export const RollbackDialog = ({
});
// hack to revalidate
try {
- // @ts-expect-error Their docs say it's here
collection.projects.utils.refetch();
- // @ts-expect-error Their docs say it's here
collection.deployments.utils.refetch();
- // @ts-expect-error Their docs say it's here
collection.domains.utils.refetch();
} catch (error) {
console.error("Refetch error:", error);
diff --git a/web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/(overview)/deployments/components/table/components/deployment-status-badge.tsx b/web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/(overview)/deployments/components/table/components/deployment-status-badge.tsx
index d7c7ada268..09701063e9 100644
--- a/web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/(overview)/deployments/components/table/components/deployment-status-badge.tsx
+++ b/web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/(overview)/deployments/components/table/components/deployment-status-badge.tsx
@@ -93,31 +93,13 @@ export const DeploymentStatusBadge = ({ status, className }: DeploymentStatusBad
)}
>
{animated && (
-
+
)}
{label}
-
- {animated && (
-
- )}
);
};
diff --git a/web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/(overview)/deployments/components/table/components/domain_list.tsx b/web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/(overview)/deployments/components/table/components/domain_list.tsx
index 42315370c5..0540645c32 100644
--- a/web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/(overview)/deployments/components/table/components/domain_list.tsx
+++ b/web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/(overview)/deployments/components/table/components/domain_list.tsx
@@ -1,33 +1,44 @@
-import { eq, useLiveQuery } from "@tanstack/react-db";
import { InfoTooltip } from "@unkey/ui";
-import { useProject } from "../../../../layout-provider";
+import { useProjectData } from "../../../../data-provider";
+import type { DeploymentStatus } from "../../../filters.schema";
import { DomainListSkeleton } from "./skeletons";
type Props = {
deploymentId: string;
+ status: DeploymentStatus;
};
-export const DomainList = ({ deploymentId }: Props) => {
- const { collections } = useProject();
+export const DomainList = ({ deploymentId, status }: Props) => {
+ const { getDomainsForDeployment, isDomainsLoading } = useProjectData();
- const domains = useLiveQuery((q) =>
- q
- .from({ domain: collections.domains })
- .where(({ domain }) => eq(domain.deploymentId, deploymentId))
- .orderBy(({ domain }) => domain.fullyQualifiedDomainName, "asc"),
- );
+ // Show placeholder for failed deployments
+ if (status === "failed") {
+ return
;
+ }
- if (domains.isLoading || !domains.data.length) {
+ // Only show skeleton when actually loading
+ if (isDomainsLoading) {
return
;
}
+ // Get domains for this deployment and sort client-side
+ const domainsForDeployment = getDomainsForDeployment(deploymentId);
+ const sortedDomains = [...domainsForDeployment].sort((a, b) =>
+ a.fullyQualifiedDomainName.localeCompare(b.fullyQualifiedDomainName),
+ );
+
+ // Handle empty domains (valid for non-failed deployments)
+ if (!sortedDomains.length) {
+ return
;
+ }
+
// Always show environment domain first, fallback to first domain if none
- const environmentDomain = domains.data.find((d) => d.sticky === "environment");
- const primaryDomain = environmentDomain ?? domains.data[0];
- const additionalDomains = domains.data.filter((d) => d.id !== primaryDomain.id);
+ const environmentDomain = sortedDomains.find((d) => d.sticky === "environment");
+ const primaryDomain = environmentDomain ?? sortedDomains[0];
+ const additionalDomains = sortedDomains.filter((d) => d.id !== primaryDomain.id);
// Single domain case - no tooltip needed
- if (domains.data.length === 1) {
+ if (sortedDomains.length === 1) {
return (