Skip to content

Commit 2f4d166

Browse files
committed
wip
1 parent 768059e commit 2f4d166

File tree

5 files changed

+62
-12
lines changed

5 files changed

+62
-12
lines changed

client/src/features/sessionsV2/SessionImageModal.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ export default function SessionImageModal({
7676
) : (
7777
<>
7878
<div className="mb-2">
79-
<SessionImageBadge data={data} loading={isLoading} />
79+
<SessionImageBadge data={data} isLoading={isLoading} />
8080
</div>
8181
{!data.connection && !data.provider ? (
8282
<>

client/src/features/sessionsV2/SessionList/SessionLauncherCard.tsx

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919
import { skipToken } from "@reduxjs/toolkit/query";
2020
import cx from "classnames";
21-
import { useContext } from "react";
21+
import { useContext, useMemo } from "react";
2222
import { CircleFill, Link45deg, Pencil, Trash } from "react-bootstrap-icons";
2323
import { Card, CardBody, Col, DropdownItem, Row } from "reactstrap";
2424

@@ -29,6 +29,7 @@ import { DEFAULT_APP_PARAMS } from "../../../utils/context/appParams.constants";
2929
import PermissionsGuard from "../../permissionsV2/PermissionsGuard";
3030
import useProjectPermissions from "../../ProjectPageV2/utils/useProjectPermissions.hook";
3131
import { Project } from "../../projectsV2/api/projectV2.api";
32+
import { computeResourcesApi } from "../api/computeResources.api";
3233
import type { SessionLauncher } from "../api/sessionLaunchersV2.api";
3334
import {
3435
sessionLaunchersV2Api,
@@ -127,7 +128,7 @@ export default function SessionLauncherCard({
127128
"text-muted",
128129
];
129130

130-
const { data: containerImage, isLoading: loadingContainerImage } =
131+
const { data: containerImage, isLoading: isLoadingContainerImage } =
131132
useGetSessionsImagesQuery(
132133
environment &&
133134
environment.environment_kind === "CUSTOM" &&
@@ -136,6 +137,17 @@ export default function SessionLauncherCard({
136137
: skipToken
137138
);
138139

140+
const { data: resourcePools, isLoading: isLoadingResourcePools } =
141+
computeResourcesApi.endpoints.getResourcePools.useQueryState({});
142+
const resourcePool = useMemo(() => {
143+
if (launcher?.resource_class_id == null || resourcePools == null) {
144+
return undefined;
145+
}
146+
return resourcePools.find(({ classes }) =>
147+
classes.some(({ id }) => id === launcher.resource_class_id)
148+
);
149+
}, [launcher?.resource_class_id, resourcePools]);
150+
139151
return (
140152
<Card
141153
className={cx(
@@ -259,7 +271,9 @@ export default function SessionLauncherCard({
259271
<Col>
260272
<SessionImageBadge
261273
data={containerImage}
262-
loading={loadingContainerImage}
274+
isLoading={isLoadingContainerImage}
275+
resourcePool={resourcePool}
276+
isLoadingResourcePools={isLoadingResourcePools}
263277
/>
264278
</Col>
265279
</Row>

client/src/features/sessionsV2/SessionView/EnvironmentCard.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ function CustomImageEnvironmentValues({
188188
return (
189189
<>
190190
<div className="mb-2">
191-
<SessionImageBadge data={data} loading={isLoading} />
191+
<SessionImageBadge data={data} isLoading={isLoading} />
192192
{!isLoading && data?.accessible === false && (
193193
<div className="mt-2">
194194
{!data.connection && !data.provider ? (

client/src/features/sessionsV2/components/SessionStatus/SessionImageBadge.tsx

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,26 +17,43 @@
1717
*/
1818

1919
import cx from "classnames";
20+
import { useMemo } from "react";
2021
import { CircleFill } from "react-bootstrap-icons";
2122

2223
import { Loader } from "~/components/Loader";
2324
import RenkuBadge from "~/components/renkuBadge/RenkuBadge";
24-
import { ImageCheckResponse } from "../../api/sessionsV2.generated-api";
25+
import type { ResourcePoolWithId } from "../../api/computeResources.api";
26+
import type { ImageCheckResponse } from "../../api/sessionsV2.api";
27+
import { isImageCompatibleWith } from "../../session.utils";
2528

2629
interface SessionImageBadgeProps {
2730
data?: ImageCheckResponse | null;
28-
loading: boolean;
31+
isLoading: boolean;
32+
33+
resourcePool?: ResourcePoolWithId;
34+
isLoadingResourcePools?: boolean;
2935
}
3036

3137
export default function SessionImageBadge({
3238
data,
33-
loading,
39+
isLoading,
40+
resourcePool,
41+
isLoadingResourcePools,
3442
}: SessionImageBadgeProps) {
43+
const isCompatible = useMemo(() => {
44+
if (data == null || resourcePool == null) {
45+
return "unknown";
46+
}
47+
return isImageCompatibleWith(data, resourcePool.platform);
48+
}, [data, resourcePool]);
49+
3550
return (
3651
<RenkuBadge
3752
color={
38-
loading
53+
isLoading || isLoadingResourcePools
3954
? "light"
55+
: isCompatible === false
56+
? "danger"
4057
: data?.accessible
4158
? "success"
4259
: data?.provider?.id &&
@@ -47,15 +64,19 @@ export default function SessionImageBadge({
4764
className="fw-normal"
4865
pill
4966
>
50-
{loading ? (
67+
{isLoading || isLoadingResourcePools ? (
5168
<>
5269
<Loader className="me-1" size={12} inline />
5370
Checking image status.
5471
</>
5572
) : (
5673
<>
5774
<CircleFill className={cx("bi", "me-1")} />
58-
{data?.accessible
75+
{isCompatible === false
76+
? `Image incompatible${
77+
resourcePool?.platform ? ` with ${resourcePool.platform}` : ""
78+
}`
79+
: data?.accessible
5980
? "Image accessible"
6081
: data?.provider?.id &&
6182
(!data?.connection || data?.connection?.status !== "connected")

client/src/features/sessionsV2/session.utils.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,18 +18,20 @@
1818

1919
import { FaviconStatus } from "../display/display.types";
2020
import { SessionStatusState } from "../session/sessions.types";
21+
import type { ResourcePoolWithId } from "./api/computeResources.api";
2122
import type {
2223
EnvironmentList as SessionEnvironmentList,
2324
SessionLauncher,
2425
SessionLauncherEnvironmentParams,
2526
SessionLauncherEnvironmentPatchParams,
2627
} from "./api/sessionLaunchersV2.api";
28+
import type { ImageCheckResponse } from "./api/sessionsV2.api";
2729
import {
2830
BUILDER_PLATFORMS,
2931
DEFAULT_URL,
3032
ENV_VARIABLES_RESERVED_PREFIX,
3133
} from "./session.constants";
32-
import { SessionLauncherForm } from "./sessionsV2.types";
34+
import type { SessionLauncherForm } from "./sessionsV2.types";
3335

3436
export function getSessionFavicon(
3537
sessionState?: SessionStatusState,
@@ -402,3 +404,16 @@ export function validateEnvVariableName(name: string): true | string {
402404
}
403405
return true;
404406
}
407+
408+
export function isImageCompatibleWith(
409+
image: ImageCheckResponse,
410+
platform: ResourcePoolWithId["platform"]
411+
): boolean | "unknown" {
412+
if (image.platforms == null) {
413+
return "unknown";
414+
}
415+
const imagePlatforms = image.platforms?.map(
416+
({ os, architecture }) => `${os}/${architecture}`
417+
);
418+
return imagePlatforms.some((p) => p === platform);
419+
}

0 commit comments

Comments
 (0)