mirror of
https://github.com/coder/coder.git
synced 2026-09-22 05:05:20 +08:00
feat(site): display warnings in tasks page when wildcard is not configured (#19780)
Closes #19739 This PR adds warnings to Task page to alert users when wildcard is not configured. Admin: <img width="1871" height="1209" alt="image" src="https://github.com/user-attachments/assets/01beb885-5493-41ed-a266-58609bee5b8b" /> Member: <img width="1713" height="1204" alt="image" src="https://github.com/user-attachments/assets/53c2bae5-5e0f-458c-b761-633399bdf2f0" />
This commit is contained in:
@@ -9,6 +9,7 @@ import {
|
||||
import { ExternalImage } from "components/ExternalImage/ExternalImage";
|
||||
import { InfoTooltip } from "components/InfoTooltip/InfoTooltip";
|
||||
import { Link } from "components/Link/Link";
|
||||
import { useProxy } from "contexts/ProxyContext";
|
||||
import { ChevronDownIcon, LayoutGridIcon } from "lucide-react";
|
||||
import { useAppLink } from "modules/apps/useAppLink";
|
||||
import type { Task } from "modules/tasks/tasks";
|
||||
@@ -18,6 +19,7 @@ import { Link as RouterLink } from "react-router";
|
||||
import { cn } from "utils/cn";
|
||||
import { docs } from "utils/docs";
|
||||
import { TaskAppIFrame } from "./TaskAppIframe";
|
||||
import { TaskWildcardWarning } from "./TaskWildcardWarning";
|
||||
|
||||
type TaskAppsProps = {
|
||||
task: Task;
|
||||
@@ -29,6 +31,8 @@ type AppWithAgent = {
|
||||
};
|
||||
|
||||
export const TaskApps: FC<TaskAppsProps> = ({ task }) => {
|
||||
const { proxy } = useProxy();
|
||||
|
||||
const agents = task.workspace.latest_build.resources
|
||||
.flatMap((r) => r.agents)
|
||||
.filter((a) => !!a);
|
||||
@@ -54,6 +58,10 @@ export const TaskApps: FC<TaskAppsProps> = ({ task }) => {
|
||||
embeddedApps[0]?.app.id,
|
||||
);
|
||||
|
||||
const activeApp = embeddedApps.find(({ app }) => app.id === activeAppId)?.app;
|
||||
const shouldDisplayWildcardWarning =
|
||||
activeApp?.subdomain && !proxy.proxy?.wildcard_hostname;
|
||||
|
||||
return (
|
||||
<main className="flex flex-col">
|
||||
<div className="w-full flex items-center border-0 border-b border-border border-solid">
|
||||
@@ -83,18 +91,22 @@ export const TaskApps: FC<TaskAppsProps> = ({ task }) => {
|
||||
</div>
|
||||
|
||||
{embeddedApps.length > 0 ? (
|
||||
<div className="flex-1">
|
||||
{embeddedApps.map(({ app }) => {
|
||||
return (
|
||||
shouldDisplayWildcardWarning ? (
|
||||
<div className="flex-1 flex flex-col items-center justify-center pb-4">
|
||||
<TaskWildcardWarning className="max-w-xl" />
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex-1">
|
||||
{embeddedApps.map(({ app }) => (
|
||||
<TaskAppIFrame
|
||||
key={app.id}
|
||||
active={activeAppId === app.id}
|
||||
app={app}
|
||||
task={task}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
) : (
|
||||
<div className="mx-auto my-auto flex flex-col items-center">
|
||||
<h3 className="font-medium text-content-primary text-base">
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import type { WorkspaceApp } from "api/typesGenerated";
|
||||
import { Spinner } from "components/Spinner/Spinner";
|
||||
import { useProxy } from "contexts/ProxyContext";
|
||||
import type { Task } from "modules/tasks/tasks";
|
||||
import type { FC } from "react";
|
||||
import { TaskAppIFrame } from "./TaskAppIframe";
|
||||
import { TaskWildcardWarning } from "./TaskWildcardWarning";
|
||||
|
||||
type TaskSidebarProps = {
|
||||
task: Task;
|
||||
@@ -64,21 +66,29 @@ const getSidebarApp = (task: Task): [WorkspaceApp | null, SidebarAppStatus] => {
|
||||
};
|
||||
|
||||
export const TaskSidebar: FC<TaskSidebarProps> = ({ task }) => {
|
||||
const proxy = useProxy();
|
||||
|
||||
const [sidebarApp, sidebarAppStatus] = getSidebarApp(task);
|
||||
const shouldDisplayWildcardWarning =
|
||||
sidebarApp?.subdomain && proxy.proxy?.preferredWildcardHostname === "";
|
||||
|
||||
return (
|
||||
<aside className="flex flex-col h-full shrink-0 w-full">
|
||||
{sidebarAppStatus === "healthy" && sidebarApp ? (
|
||||
{sidebarAppStatus === "loading" ? (
|
||||
<div className="flex-1 flex flex-col items-center justify-center pb-4">
|
||||
<Spinner loading />
|
||||
</div>
|
||||
) : shouldDisplayWildcardWarning ? (
|
||||
<div className="flex-1 flex flex-col items-center justify-center pb-4">
|
||||
<TaskWildcardWarning className="max-w-xl" />
|
||||
</div>
|
||||
) : sidebarAppStatus === "healthy" && sidebarApp ? (
|
||||
<TaskAppIFrame
|
||||
active
|
||||
key={sidebarApp.id}
|
||||
app={sidebarApp}
|
||||
task={task}
|
||||
/>
|
||||
) : sidebarAppStatus === "loading" ? (
|
||||
<div className="flex-1 flex flex-col items-center justify-center">
|
||||
<Spinner loading className="mb-4" />
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex-1 flex flex-col items-center justify-center">
|
||||
<h3 className="m-0 font-medium text-content-primary text-base">
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
import { Button } from "components/Button/Button";
|
||||
import { useAuthenticated } from "hooks/useAuthenticated";
|
||||
import { SquareArrowOutUpRightIcon } from "lucide-react";
|
||||
import { Link as RouterLink } from "react-router";
|
||||
import { cn } from "utils/cn";
|
||||
import { docs } from "utils/docs";
|
||||
|
||||
type TaskWildcardWarningProps = {
|
||||
className?: string;
|
||||
};
|
||||
|
||||
export const TaskWildcardWarning = ({
|
||||
className,
|
||||
}: TaskWildcardWarningProps) => {
|
||||
const { permissions } = useAuthenticated();
|
||||
const canEditDeploymentConfig = Boolean(permissions.editDeploymentConfig);
|
||||
|
||||
return (
|
||||
<div className={cn("text-center", className)}>
|
||||
<h3 className="font-medium text-content-primary text-base mb-3">Error</h3>
|
||||
<div className="text-content-secondary text-sm flex flex-col gap-3 items-center">
|
||||
<div className="px-4">
|
||||
This application has{" "}
|
||||
<code className="py-px px-1 bg-surface-tertiary rounded-sm text-content-primary">
|
||||
subdomain = true
|
||||
</code>
|
||||
{canEditDeploymentConfig ? (
|
||||
<>
|
||||
, but subdomain applications are not configured. This application
|
||||
won't be accessible until you configure the{" "}
|
||||
<code className="py-px px-1 bg-surface-tertiary rounded-sm text-content-primary whitespace-nowrap">
|
||||
--wildcard-access-url
|
||||
</code>{" "}
|
||||
flag when starting the Coder server.
|
||||
</>
|
||||
) : (
|
||||
", which requires a Coder deployment with a Wildcard Access URL configured. Please contact your administrator."
|
||||
)}
|
||||
</div>
|
||||
<Button size="sm" variant="outline" asChild>
|
||||
<RouterLink to={docs("/admin/networking/wildcard-access-url")}>
|
||||
<SquareArrowOutUpRightIcon />
|
||||
Learn more about wildcard access URL
|
||||
</RouterLink>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user