diff --git a/site/src/modules/resources/AppLink/AppLink.stories.tsx b/site/src/modules/resources/AppLink/AppLink.stories.tsx index d7d00a1c02..e094c6a32b 100644 --- a/site/src/modules/resources/AppLink/AppLink.stories.tsx +++ b/site/src/modules/resources/AppLink/AppLink.stories.tsx @@ -77,6 +77,19 @@ export const ExternalAppNotInstalled: Story = { }, }; +export const ExternalAppShareable: Story = { + args: { + workspace: MockWorkspace, + app: { + ...MockWorkspaceApp, + url: "vscode://open", + external: true, + sharing_level: "authenticated", + }, + agent: MockWorkspaceAgent, + }, +}; + export const SharingLevelOwner: Story = { args: { workspace: MockWorkspace, diff --git a/site/src/modules/resources/AppLink/AppLink.tsx b/site/src/modules/resources/AppLink/AppLink.tsx index 419148ed09..9294f94912 100644 --- a/site/src/modules/resources/AppLink/AppLink.tsx +++ b/site/src/modules/resources/AppLink/AppLink.tsx @@ -9,13 +9,19 @@ import { TooltipTrigger, } from "components/Tooltip/Tooltip"; import { useProxy } from "contexts/ProxyContext"; -import { CircleAlertIcon } from "lucide-react"; +import { + Building2Icon, + CircleAlertIcon, + GlobeIcon, + type LucideIcon, + SquareArrowOutUpRightIcon, + UsersIcon, +} from "lucide-react"; import { isExternalApp, needsSessionToken } from "modules/apps/apps"; import { useAppLink } from "modules/apps/useAppLink"; import { type FC, type ReactNode, useState } from "react"; import { AgentButton } from "../AgentButton"; import { BaseIcon } from "./BaseIcon"; -import { ShareIcon } from "./ShareIcon"; export const DisplayAppNameMap: Record = { port_forwarding_helper: "Ports", @@ -115,13 +121,24 @@ export const AppLink: FC = ({ } const canShare = app.sharing_level !== "owner"; + const { shareTooltip, shareIcon: ShareIcon } = canShare + ? app.external + ? { + shareTooltip: "Open external URL", + shareIcon: SquareArrowOutUpRightIcon, + } + : shareDetails[app.sharing_level] + : { + shareTooltip: null, + shareIcon: null, + }; const button = grouped ? ( {icon} {link.label} - {canShare && } + {ShareIcon && } ) : ( @@ -129,7 +146,7 @@ export const AppLink: FC = ({ {icon} {link.label} - {canShare && } + {ShareIcon && } ); @@ -146,6 +163,7 @@ export const AppLink: FC = ({ {app.tooltip} ) : null} + {shareTooltip} ); @@ -153,3 +171,23 @@ export const AppLink: FC = ({ return button; }; + +const shareDetails: { + [SharingLevel in TypesGen.WorkspaceAppSharingLevel as Exclude< + SharingLevel, + "owner" + >]: { shareTooltip: string; shareIcon: LucideIcon }; +} = { + authenticated: { + shareTooltip: "Shared with all authenticated users", + shareIcon: UsersIcon, + }, + organization: { + shareTooltip: "Shared with organization members", + shareIcon: Building2Icon, + }, + public: { + shareTooltip: "Shared publicly", + shareIcon: GlobeIcon, + }, +}; diff --git a/site/src/modules/resources/AppLink/ShareIcon.tsx b/site/src/modules/resources/AppLink/ShareIcon.tsx deleted file mode 100644 index d9d536f999..0000000000 --- a/site/src/modules/resources/AppLink/ShareIcon.tsx +++ /dev/null @@ -1,45 +0,0 @@ -import Tooltip from "@mui/material/Tooltip"; -import type * as TypesGen from "api/typesGenerated"; -import { - Building2Icon, - GlobeIcon, - SquareArrowOutUpRightIcon, - UsersIcon, -} from "lucide-react"; - -interface ShareIconProps { - app: TypesGen.WorkspaceApp; -} - -export const ShareIcon = ({ app }: ShareIconProps) => { - if (app.external) { - return ( - - - - ); - } - if (app.sharing_level === "authenticated") { - return ( - - - - ); - } - if (app.sharing_level === "organization") { - return ( - - - - ); - } - if (app.sharing_level === "public") { - return ( - - - - ); - } - - return null; -};