Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions client/eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ const jsRules = {
"katex",
"kernelspec",
"Keycloak",
"Knative",
"kubernetes",
"Lausanne",
"linkify",
Expand Down
4 changes: 3 additions & 1 deletion client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@
"storybook-wait-server": "wait-on http://127.0.0.1:6006",
"storybook-test": "test-storybook",
"storybook-compile-and-test": "concurrently -k -s first -n 'BUILD,TEST' -c 'magenta,blue' 'npm run storybook-build && npm run storybook-start-server' 'npm run storybook-wait-server && npm run storybook-test'",
"generate-api": "npm run generate-api:computeResources && npm run generate-api:connectedServices && npm run generate-api:data-connectors && npm run generate-api:doiResolver && npm run generate-api:namespaceV2 && npm run generate-api:notifications && npm run generate-api:platform && npm run generate-api:projectCloudStorage && npm run generate-api:projectV2 && npm run generate-api:repositories && npm run generate-api:searchV2 && npm run generate-api:sessionLaunchersV2 && npm run generate-api:sessionsV2 && npm run generate-api:users",
"generate-api": "npm run generate-api:apps && npm run generate-api:computeResources && npm run generate-api:connectedServices && npm run generate-api:data-connectors && npm run generate-api:doiResolver && npm run generate-api:namespaceV2 && npm run generate-api:notifications && npm run generate-api:platform && npm run generate-api:projectCloudStorage && npm run generate-api:projectV2 && npm run generate-api:repositories && npm run generate-api:searchV2 && npm run generate-api:sessionLaunchersV2 && npm run generate-api:sessionsV2 && npm run generate-api:users",
"generate-api:apps": "rtk-query-codegen-openapi src/features/sessionsV2/api/apps.api-config.ts",
"generate-api:computeResources": "rtk-query-codegen-openapi src/features/sessionsV2/api/computeResources.api-config.ts",
"generate-api:connectedServices": "rtk-query-codegen-openapi src/features/connectedServices/api/connectedServices.api-config.ts",
"generate-api:data-connectors": "rtk-query-codegen-openapi src/features/dataConnectorsV2/api/data-connectors.api-config.ts",
Expand All @@ -37,6 +38,7 @@
"generate-api:sessionsV2": "rtk-query-codegen-openapi src/features/sessionsV2/api/sessionsV2.api-config.ts",
"generate-api:users": "rtk-query-codegen-openapi src/features/usersV2/api/users.api-config.ts",
"update-api": "node scripts/update_api_spec.js computeResources connectedServices dataConnectors namespaceV2 notifications platform projectCloudStorage projectV2 repositories searchV2 sessionLaunchersV2 sessionsV2 users",
"update-api:apps": "node scripts/update_api_spec.js apps",
"update-api:computeResources": "node scripts/update_api_spec.js computeResources",
"update-api:connectedServices": "node scripts/update_api_spec.js connectedServices",
"update-api:dataConnectors": "node scripts/update_api_spec.js dataConnectors",
Expand Down
1 change: 1 addition & 0 deletions client/run-telepresence.sh
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@ tee > ./public/config.json << EOF
"SESSION_CLASS_EMAIL_US": { "enabled": false },
"IMAGE_BUILDERS_ENABLED": true,
"BUILD_PRIVATE_REPO_BUILDS_ENABLED": true,
"APPS_ENABLED": true,
"CONTACT_EMAIL": "hello@renku.io"
}
EOF
Expand Down
15 changes: 14 additions & 1 deletion client/scripts/update_api_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ const DATA_SERVICES_RELEASE = "main";

async function main() {
argv.forEach((arg) => {
if (arg.trim() === "computeResources") {
if (arg.trim() === "apps") {
updateAppsApi();
} else if (arg.trim() === "computeResources") {
updateComputeResourcesApi();
} else if (arg.trim() === "connectedServices") {
updateConnectedServicesApi();
Expand Down Expand Up @@ -58,6 +60,17 @@ async function main() {
});
}

// NOTE: renku_apps is still on a feature branch in renku-data-services, so this
// will 404 against DATA_SERVICES_RELEASE ("main") until that branch is merged.
// It is also deliberately left out of the aggregate "update-api" script for the
// same reason — add it there once the backend lands on main.
async function updateAppsApi() {
updateApiFiles({
specFile: "components/renku_data_services/renku_apps/api.spec.yaml",
destFile: "src/features/sessionsV2/api/apps.openapi.json",
});
}

async function updateNotificationsApi() {
updateApiFiles({
specFile: "components/renku_data_services/notifications/api.spec.yaml",
Expand Down
1 change: 1 addition & 0 deletions client/server/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ export const CONFIG_JSON = {
IMAGE_BUILDERS_ENABLED: process.env.IMAGE_BUILDERS_ENABLED,
BUILD_PRIVATE_REPO_BUILDS_ENABLED:
process.env.BUILD_PRIVATE_REPO_BUILDS_ENABLED,
APPS_ENABLED: process.env.APPS_ENABLED,
CONTACT_EMAIL: process.env.CONTACT_EMAIL || "hello@renku.io",
};

Expand Down
1 change: 1 addition & 0 deletions client/src/components/entities/entities.types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export type EntityTypes =
| "app-launcher"
| "code-repository"
| "data-connector"
| "job-launcher"
Expand Down
11 changes: 8 additions & 3 deletions client/src/components/offcanvas/OffcanvasHeaderWithType.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import cx from "classnames";
import {
CircleSquare,
Database,
FileCode,
Gear,
Expand Down Expand Up @@ -32,6 +33,8 @@ export default function OffcanvasHeaderWithType({
<PlayCircle className="me-1" />
) : entityType === "job-launcher" ? (
<Gear className="me-1" />
) : entityType === "app-launcher" ? (
<CircleSquare className="me-1" />
) : entityType === "code-repository" ? (
<FileCode className="me-1" />
) : (
Expand All @@ -46,9 +49,11 @@ export default function OffcanvasHeaderWithType({
? "Job launcher"
: entityType === "session-launcher"
? "Session launcher"
: entityType === "code-repository"
? "Code repository"
: "Unknown";
: entityType === "app-launcher"
? "App launcher"
: entityType === "code-repository"
? "Code repository"
: "Unknown";

return (
<div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ export default function SessionLauncherCard({

const environment = launcher?.environment;
const hasSession = !!sessions?.length;

const sessionType = sessions?.at(0)?.session_type ?? "interactive";
// Orphan sessions have no launcher; get category from the session itself
const launcherCategory = sessionLauncherKindToCategory(
Expand All @@ -98,6 +99,9 @@ export default function SessionLauncherCard({
const launcherDefinition = getLauncherCategoryDefinition(launcherCategory);
const LauncherTypeIcon = launcherDefinition?.icon || PlayCircle;
const launcherTypeLabel = launcherDefinition?.text.display || null;
// App launchers use a compact, content-driven meta row; other launcher types
// keep the original grid layout untouched.
const isApp = launcherCategory === "app";

sessionLaunchersV2Api.endpoints.getEnvironmentsByEnvironmentIdBuilds.useQuerySubscription(
launcher && isBuildInProgress
Expand Down Expand Up @@ -179,43 +183,77 @@ export default function SessionLauncherCard({
>
<Row className="g-2">
<Col className={cx("align-items-center")} xs={12} lg={6} xl={7}>
{launcher && (
<Row className={cx("g-2", "mb-0")}>
<Col
xs={12}
xl={4}
{launcher &&
(isApp ? (
<div
className={cx(
"d-inline-block",
"link-primary",
"text-body",
"d-flex",
"flex-wrap",
"align-items-center",
"gap-3",
"mb-1",
)}
>
<span
className={cx(
"small",
"text-muted",
"me-3",
"d-inline-flex",
"align-items-center",
"gap-1",
"link-primary",
"text-body",
)}
>
<LauncherTypeIcon className={cx("bi")} size={14} />
<span className="fw-bold">{launcherTypeLabel}</span>{" "}
Launcher
</span>
</Col>
<Col xs={12} xl="auto">
{launcher?.environment &&
getEnvironmentKindLabel(launcher.environment) != null && (
<span className={cx(ENVIRONMENT_KIND_CLASSES)}>
<LauncherEnvironmentIcon launcher={launcher} />
{getEnvironmentKindLabel(launcher.environment)}
</span>
)}
</Col>
</Row>
)}
</div>
) : (
<Row className={cx("g-2", "mb-0")}>
<Col
xs={12}
xl={4}
className={cx(
"d-inline-block",
"link-primary",
"text-body",
)}
>
<span
className={cx(
"small",
"text-muted",
"me-3",
"d-inline-flex",
"align-items-center",
"gap-1",
)}
>
<LauncherTypeIcon className={cx("bi")} size={14} />
<span className="fw-bold">{launcherTypeLabel}</span>{" "}
Launcher
</span>
</Col>
<Col xs={12} xl="auto">
{launcher?.environment &&
getEnvironmentKindLabel(launcher.environment) != null && (
<span className={cx(ENVIRONMENT_KIND_CLASSES)}>
<LauncherEnvironmentIcon launcher={launcher} />
{getEnvironmentKindLabel(launcher.environment)}
</span>
)}
</Col>
</Row>
))}
<Row className={cx("g-2", isCodeEnvironment && "mb-2")}>
<Col
xs={12}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,21 @@
* limitations under the License.
*/

import { skipToken } from "@reduxjs/toolkit/query";
import { useCallback, useMemo, useState } from "react";

import useLocationHash from "../../../utils/customHooks/useLocationHash.hook";
import { Project } from "../../projectsV2/api/projectV2.api";
import type { SessionLauncher } from "../api/sessionLaunchersV2.api";
import type { SessionType } from "../api/sessionsV2.api";
import { useGetSessionsQuery as useGetSessionsQueryV2 } from "../api/sessionsV2.api";
import UpdateSessionLauncherMetadataModal from "../components/SessionModals/UpdateSessionLauncherMetadataModal";
import UpdateSessionLauncherEnvironmentModal from "../components/SessionModals/UpdateSessionLauncherModal";
import DeleteSessionV2Modal from "../DeleteSessionLauncherModal";
import {
buildLauncherHash,
buildLauncherJobHash,
isAppLauncher,
isLauncherHashOpen,
parseLauncherHash,
toggleLauncherHash,
Expand Down Expand Up @@ -93,9 +96,16 @@ export function SessionLauncherDisplay({
[launcher.id, setHash],
);

const { data: sessions } = useGetSessionsQueryV2({
sessionType: launcher.launcher_type,
});
// Apps do not spawn per-user sessions; their runtime state comes from the
// dedicated /apps API (fetched inside the app-specific components), so we
// skip the sessions query entirely for app launchers.
const isApp = isAppLauncher(launcher);
const { data: sessions } = useGetSessionsQueryV2(
isApp
? skipToken
: // Safe cast: non-app launcher types are exactly `SessionType`.
{ sessionType: launcher.launcher_type as SessionType },
);

const filteredSessions = useMemo(
() =>
Expand Down
Loading
Loading