From 2e1a869ba2c4de2cf519ac3205f5ebd9fe6bc23f Mon Sep 17 00:00:00 2001 From: Mubangizi Allan Date: Tue, 14 Apr 2026 17:07:26 +0300 Subject: [PATCH 1/2] add app restart functionality --- src/pages/Apps/AppDetailPage.tsx | 140 +++++++++++++++++++++-------- src/pages/Apps/AppSettingsPage.tsx | 23 +++-- 2 files changed, 117 insertions(+), 46 deletions(-) diff --git a/src/pages/Apps/AppDetailPage.tsx b/src/pages/Apps/AppDetailPage.tsx index 37c01c545..97aff87d0 100644 --- a/src/pages/Apps/AppDetailPage.tsx +++ b/src/pages/Apps/AppDetailPage.tsx @@ -1,7 +1,8 @@ -import React from "react"; +import React, { useEffect, useState } from "react"; import { useGetApp, useSetContainerSize } from "@/utils/helpers"; -import { Link, useParams } from "react-router-dom"; +import { Link, useNavigate, useParams } from "react-router-dom"; import { + ActionIcon, Button, Card, Code, @@ -11,6 +12,7 @@ import { Skeleton, Stack, Text, + Tooltip, } from "@mantine/core"; import TitleText, { CustomText } from "@/components/TitleText"; import { TbCopy, TbWorld } from "react-icons/tb"; @@ -18,11 +20,22 @@ import { FiExternalLink } from "react-icons/fi"; import { FaDocker } from "react-icons/fa"; import { LuScreenShare } from "react-icons/lu"; import { SiJupyter } from "react-icons/si"; +import { ModalConfirm } from "@/components/Elements/Modals"; +import usePost from "@/utils/usePost"; +import { RiRefreshLine } from "react-icons/ri"; const AppDetailPage = () => { const { app_id } = useParams(); const { app, loading } = useGetApp(app_id || ""); useSetContainerSize("md"); + const [refreshModalOpened, setRefreshModalOpened] = useState(false); + const navigate = useNavigate(); + + const { + uploadData: refreshApp, + submitting: refreshingApp, + success: refreshedAppSuccess, + } = usePost(); const getAppStatus = (status: string) => { if (status === "running") { @@ -87,6 +100,25 @@ const AppDetailPage = () => { value: getAppStatus(app?.app_running_status), }, ]; + + const handleRefresh = () => { + refreshApp({ + api: `apps/${app?.id}/restart`, + params: { + restart: true, + }, + }); + }; + + useEffect(() => { + if (refreshedAppSuccess) { + setRefreshModalOpened(false); + navigate( + `/projects/${app?.project_id}/apps/${app?.id}/settings?tab=deployments`, + ); + } + }, [refreshedAppSuccess]); + return ( { ) : ( - - {app?.image && !app?.is_notebook && ( - - Image - - } - > - {app?.image} - - + + + {app?.image && !app?.is_notebook && ( + + Image + + } + > + {app?.image} + + + + )} + + }> + Domain + + + {app?.url} + + - )} - - }> - Domain - - + + + + Notebook + + + + )} + + + setRefreshModalOpened(true)} > - {app?.url} - - - - {app?.is_notebook && ( - - - - - Notebook - - - - )} + + + + setRefreshModalOpened(false)} + title="Refresh App" + buttonColor="gray.9" + buttonText="Refresh" + onConfirm={handleRefresh} + loading={refreshingApp} + leftSection={} + > + Are you sure you want to refresh the app? + + This action will restart the app and pull the latest image. This + may take a few minutes. + + + {appInfo.map((info) => ( { const { app_id } = useParams(); - const [refresh, setRefresh] = useState(0); + const [refresh, setRefresh] = useState(0); const { app } = useGetApp(app_id || "", refresh); const { setContainerSize } = useContext(MenuContext); + const [searchParams, setSearchParams] = useSearchParams(); + const activeTab = searchParams.get("tab") || "general"; + + const handleTabChange = (value: string | null) => { + setSearchParams({ tab: value || "" }); + }; useEffect(() => { setContainerSize("md"); - return () => { - setContainerSize("xl"); - }; + return () => setContainerSize("xl"); }, [setContainerSize]); - useEffect(() => {}, [app]); + return ( - + General CI / CD From 97dd2560df0ac0bdead7df10d20dcdba831f1148 Mon Sep 17 00:00:00 2001 From: Mubangizi Allan Date: Tue, 14 Apr 2026 17:10:57 +0300 Subject: [PATCH 2/2] add the useeffect --- src/pages/Apps/AppSettingsPage.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/pages/Apps/AppSettingsPage.tsx b/src/pages/Apps/AppSettingsPage.tsx index dbd6dec2a..0b0eb9a0c 100644 --- a/src/pages/Apps/AppSettingsPage.tsx +++ b/src/pages/Apps/AppSettingsPage.tsx @@ -86,6 +86,8 @@ const AppSettingsPage = () => { return () => setContainerSize("xl"); }, [setContainerSize]); + useEffect(() => {}, [app]); + return (