mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
fix: hide app icon if not found (#16684)
Fixes: https://github.com/coder/coder/issues/14759
This commit is contained in:
@@ -37,6 +37,7 @@ export const AppLink: FC<AppLinkProps> = ({ app, workspace, agent }) => {
|
|||||||
const preferredPathBase = proxy.preferredPathAppURL;
|
const preferredPathBase = proxy.preferredPathAppURL;
|
||||||
const appsHost = proxy.preferredWildcardHostname;
|
const appsHost = proxy.preferredWildcardHostname;
|
||||||
const [fetchingSessionToken, setFetchingSessionToken] = useState(false);
|
const [fetchingSessionToken, setFetchingSessionToken] = useState(false);
|
||||||
|
const [iconError, setIconError] = useState(false);
|
||||||
|
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const username = workspace.owner_name;
|
const username = workspace.owner_name;
|
||||||
@@ -67,7 +68,9 @@ export const AppLink: FC<AppLinkProps> = ({ app, workspace, agent }) => {
|
|||||||
// To avoid bugs in the healthcheck code locking users out of apps, we no
|
// To avoid bugs in the healthcheck code locking users out of apps, we no
|
||||||
// longer block access to apps if they are unhealthy/initializing.
|
// longer block access to apps if they are unhealthy/initializing.
|
||||||
let canClick = true;
|
let canClick = true;
|
||||||
let icon = <BaseIcon app={app} />;
|
let icon = !iconError && (
|
||||||
|
<BaseIcon app={app} onIconPathError={() => setIconError(true)} />
|
||||||
|
);
|
||||||
|
|
||||||
let primaryTooltip = "";
|
let primaryTooltip = "";
|
||||||
if (app.health === "initializing") {
|
if (app.health === "initializing") {
|
||||||
|
|||||||
@@ -4,14 +4,21 @@ import type { FC } from "react";
|
|||||||
|
|
||||||
interface BaseIconProps {
|
interface BaseIconProps {
|
||||||
app: WorkspaceApp;
|
app: WorkspaceApp;
|
||||||
|
onIconPathError?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const BaseIcon: FC<BaseIconProps> = ({ app }) => {
|
export const BaseIcon: FC<BaseIconProps> = ({ app, onIconPathError }) => {
|
||||||
return app.icon ? (
|
return app.icon ? (
|
||||||
<img
|
<img
|
||||||
alt={`${app.display_name} Icon`}
|
alt={`${app.display_name} Icon`}
|
||||||
src={app.icon}
|
src={app.icon}
|
||||||
style={{ pointerEvents: "none" }}
|
style={{ pointerEvents: "none" }}
|
||||||
|
onError={() => {
|
||||||
|
console.warn(
|
||||||
|
`Application icon for "${app.id}" has invalid source "${app.icon}".`,
|
||||||
|
);
|
||||||
|
onIconPathError?.();
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<ComputerIcon />
|
<ComputerIcon />
|
||||||
|
|||||||
@@ -80,6 +80,43 @@ export const Running: Story = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const AppIcons: Story = {
|
||||||
|
args: {
|
||||||
|
...Running.args,
|
||||||
|
workspace: {
|
||||||
|
...Mocks.MockWorkspace,
|
||||||
|
latest_build: {
|
||||||
|
...Mocks.MockWorkspace.latest_build,
|
||||||
|
resources: [
|
||||||
|
{
|
||||||
|
...Mocks.MockWorkspaceResource,
|
||||||
|
agents: [
|
||||||
|
{
|
||||||
|
...Mocks.MockWorkspaceAgent,
|
||||||
|
apps: [
|
||||||
|
{
|
||||||
|
...Mocks.MockWorkspaceApp,
|
||||||
|
id: "test-app-1",
|
||||||
|
slug: "test-app-1",
|
||||||
|
display_name: "Default Icon",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
...Mocks.MockWorkspaceApp,
|
||||||
|
id: "test-app-2",
|
||||||
|
slug: "test-app-2",
|
||||||
|
display_name: "Broken Icon",
|
||||||
|
icon: "/foobar/broken.png",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
export const Favorite: Story = {
|
export const Favorite: Story = {
|
||||||
args: {
|
args: {
|
||||||
...Running.args,
|
...Running.args,
|
||||||
|
|||||||
Reference in New Issue
Block a user