diff --git a/client/src/features/sessionsV2/SessionList/Actions.module.scss b/client/src/features/sessionsV2/SessionList/Actions.module.scss
new file mode 100644
index 0000000000..4e209e9567
--- /dev/null
+++ b/client/src/features/sessionsV2/SessionList/Actions.module.scss
@@ -0,0 +1,17 @@
+@import "~bootstrap/scss/functions";
+@import "~bootstrap/scss/variables";
+@import "~bootstrap/scss/variables-dark";
+@import "~bootstrap/scss/maps";
+@import "~bootstrap/scss/mixins";
+
+.actionsButton {
+ bottom: 0;
+ margin-bottom: 1rem;
+
+ @include media-breakpoint-up(md) {
+ top: 0;
+ margin-top: 1rem;
+ right: 0;
+ bottom: auto;
+ }
+}
diff --git a/client/src/features/sessionsV2/SessionList/SessionItemV2.tsx b/client/src/features/sessionsV2/SessionList/SessionItemV2.tsx
index 4f4207977f..fb74e3729f 100644
--- a/client/src/features/sessionsV2/SessionList/SessionItemV2.tsx
+++ b/client/src/features/sessionsV2/SessionList/SessionItemV2.tsx
@@ -19,13 +19,19 @@
import cx from "classnames";
import { useCallback, useMemo } from "react";
import { CaretRightFill } from "react-bootstrap-icons";
-import { ListGroupItem } from "reactstrap";
+import { Link } from "react-router-dom-v5-compat";
+import { Col, ListGroupItem, Row } from "reactstrap";
import useLocationHash from "../../../utils/customHooks/useLocationHash.hook";
+import { useProject } from "../../ProjectPageV2/ProjectPageContainer/ProjectPageContainer";
+import ActiveSessionButton from "../components/SessionButton/ActiveSessionButton";
import { SessionStatusV2Label } from "../components/SessionStatus/SessionStatus";
+import { getShowSessionUrlByProject } from "../SessionsV2";
import type { SessionLauncher, SessionV2 } from "../sessionsV2.types";
import SessionViewV2 from "../SessionView/SessionViewV2";
+import styles from "./Actions.module.scss";
+
interface SessionItemV2Props {
launcher: SessionLauncher;
session: SessionV2;
@@ -35,6 +41,8 @@ export default function SessionItemV2({
launcher,
session,
}: SessionItemV2Props) {
+ const { project } = useProject();
+
const [hash, setHash] = useLocationHash();
const sessionHash = useMemo(
() => `session-v2-${session.name}`,
@@ -53,20 +61,44 @@ export default function SessionItemV2({
return (
<>
-
-
-
+
+
+
+
+
+
+
+
+ {/* NOTE: This is a placeholder for the session actions button */}
+
+
+
+
+
+
+ {/* NOTE: The session actions button is visually placed within the link card, but its DOM tree is kept separate. */}
+
0) {
+ return ;
+ }
+
+ return (
+
+ );
+}
+
+function DisabledLaunchButton() {
+ const ref = useRef(null);
+
+ return (
+ <>
+
+
+
+
+ A session is already running from this launcher
+
+ >
+ );
+}
diff --git a/client/src/features/sessionsV2/SessionList/SessionLauncherItem.tsx b/client/src/features/sessionsV2/SessionList/SessionLauncherItem.tsx
index 7f98b76110..74e7f9a31a 100644
--- a/client/src/features/sessionsV2/SessionList/SessionLauncherItem.tsx
+++ b/client/src/features/sessionsV2/SessionList/SessionLauncherItem.tsx
@@ -19,6 +19,7 @@
import cx from "classnames";
import { useCallback, useMemo } from "react";
import { CircleFill } from "react-bootstrap-icons";
+import { Link } from "react-router-dom-v5-compat";
import { Badge, Col, ListGroupItem, Row } from "reactstrap";
import useLocationHash from "../../../utils/customHooks/useLocationHash.hook";
@@ -28,6 +29,9 @@ import type { SessionLauncher } from "../sessionsV2.types";
import SessionLauncherView from "../SessionView/SessionLauncherView";
import SessionItemV2 from "./SessionItemV2";
+import styles from "./Actions.module.scss";
+import SessionLauncherActions from "./SessionLauncherActions";
+
interface SessionLauncherItemProps {
launcher: SessionLauncher;
}
@@ -70,59 +74,69 @@ export default function SessionLauncherItem({
return (
<>
-
-
-
-
-
-
-
- {name}
-
-
-
-
+
+
+
-
- Ready
-
-
-
-
-
+
+ {name}
+
+
+
+
+
+ Ready
+
+
+
+
+
+ {/* NOTE: This is a placeholder for the session actions button */}
+
+
+
+
+
+
+ {/* NOTE: The session actions button is visually placed within the link card, but its DOM tree is kept separate. */}
+
+
+
{filteredSessions.map((session) => (
@@ -56,7 +62,15 @@ export default function SessionViewV2({
+
+
+
Container image
+
+
diff --git a/client/src/features/sessionsV2/components/SessionButton/ActiveSessionButton.tsx b/client/src/features/sessionsV2/components/SessionButton/ActiveSessionButton.tsx
index a57bc65d8f..ef3203bd92 100644
--- a/client/src/features/sessionsV2/components/SessionButton/ActiveSessionButton.tsx
+++ b/client/src/features/sessionsV2/components/SessionButton/ActiveSessionButton.tsx
@@ -374,7 +374,7 @@ export default function ActiveSessionButton({
return (