diff --git a/frontend/app/block/blockframe.tsx b/frontend/app/block/blockframe.tsx
index d473433a1..99facd9cb 100644
--- a/frontend/app/block/blockframe.tsx
+++ b/frontend/app/block/blockframe.tsx
@@ -5,6 +5,7 @@ import {
blockViewToIcon,
blockViewToName,
ConnectionButton,
+ ControllerStatusIcon,
getBlockHeaderIcon,
IconButton,
Input,
@@ -192,6 +193,7 @@ const BlockFrame_Header = ({
);
headerTextElems.unshift(connButtonElem);
}
+ headerTextElems.unshift();
return (
diff --git a/frontend/app/block/blockutil.tsx b/frontend/app/block/blockutil.tsx
index 57e31f8a0..26debf54a 100644
--- a/frontend/app/block/blockutil.tsx
+++ b/frontend/app/block/blockutil.tsx
@@ -2,7 +2,9 @@
// SPDX-License-Identifier: Apache-2.0
import { useLongClick } from "@/app/hook/useLongClick";
-import { getConnStatusAtom } from "@/app/store/global";
+import { getConnStatusAtom, waveEventSubscribe, WOS } from "@/app/store/global";
+import * as services from "@/app/store/services";
+import { makeORef } from "@/app/store/wos";
import * as util from "@/util/util";
import clsx from "clsx";
import * as jotai from "jotai";
@@ -150,6 +152,51 @@ interface ConnectionButtonProps {
changeConnModalAtom: jotai.PrimitiveAtom;
}
+export const ControllerStatusIcon = React.memo(({ blockId }: { blockId: string }) => {
+ const [blockData] = WOS.useWaveObjectValue(WOS.makeORef("block", blockId));
+ const hasController = !util.isBlank(blockData?.meta?.controller);
+ const [controllerStatus, setControllerStatus] = React.useState(null);
+ const connection = blockData?.meta?.connection ?? "local";
+ const connStatusAtom = getConnStatusAtom(connection);
+ const connStatus = jotai.useAtomValue(connStatusAtom);
+ React.useEffect(() => {
+ if (!hasController) {
+ return;
+ }
+ const initialRTStatus = services.BlockService.GetControllerStatus(blockId);
+ initialRTStatus.then((rts) => {
+ setControllerStatus(rts);
+ });
+ const unsubFn = waveEventSubscribe("controllerstatus", makeORef("block", blockId), (event) => {
+ const cstatus: BlockControllerRuntimeStatus = event.data;
+ setControllerStatus(cstatus);
+ });
+ return () => {
+ unsubFn();
+ };
+ }, [hasController]);
+ if (!hasController) {
+ return null;
+ }
+ if (
+ controllerStatus == null ||
+ (controllerStatus?.status == "running" && controllerStatus?.shellprocstatus == "running")
+ ) {
+ return null;
+ }
+ if (connStatus?.status != "connected") {
+ return null;
+ }
+ const controllerStatusElem = (
+
+ );
+ return controllerStatusElem;
+});
+
export const ConnectionButton = React.memo(
React.forwardRef(
({ connection, changeConnModalAtom }: ConnectionButtonProps, ref) => {
diff --git a/pkg/blockcontroller/blockcontroller.go b/pkg/blockcontroller/blockcontroller.go
index 10d61ffe4..1b116ee53 100644
--- a/pkg/blockcontroller/blockcontroller.go
+++ b/pkg/blockcontroller/blockcontroller.go
@@ -22,6 +22,7 @@ import (
"github.com/wavetermdev/thenextwave/pkg/shellexec"
"github.com/wavetermdev/thenextwave/pkg/wavebase"
"github.com/wavetermdev/thenextwave/pkg/waveobj"
+ "github.com/wavetermdev/thenextwave/pkg/wps"
"github.com/wavetermdev/thenextwave/pkg/wshrpc"
"github.com/wavetermdev/thenextwave/pkg/wshutil"
"github.com/wavetermdev/thenextwave/pkg/wstore"
@@ -124,12 +125,21 @@ func (bc *BlockController) UpdateControllerAndSendUpdate(updateFn func() bool) {
sendUpdate = updateFn()
})
if sendUpdate {
- log.Printf("sending blockcontroller update %#v\n", bc.GetRuntimeStatus())
+ rtStatus := bc.GetRuntimeStatus()
+ log.Printf("sending blockcontroller update %#v\n", rtStatus)
go eventbus.SendEvent(eventbus.WSEventType{
EventType: eventbus.WSEvent_BlockControllerStatus,
ORef: waveobj.MakeORef(waveobj.OType_Block, bc.BlockId).String(),
- Data: bc.GetRuntimeStatus(),
+ Data: rtStatus,
})
+ waveEvent := wshrpc.WaveEvent{
+ Event: wshrpc.Event_ControllerStatus,
+ Scopes: []string{
+ waveobj.MakeORef(waveobj.OType_Tab, bc.TabId).String(),
+ },
+ Data: rtStatus,
+ }
+ wps.Broker.Publish(waveEvent)
}
}
diff --git a/pkg/wshrpc/wshrpctypes.go b/pkg/wshrpc/wshrpctypes.go
index 583cdb25e..a107da5bb 100644
--- a/pkg/wshrpc/wshrpctypes.go
+++ b/pkg/wshrpc/wshrpctypes.go
@@ -25,9 +25,10 @@ const (
)
const (
- Event_BlockClose = "blockclose"
- Event_ConnChange = "connchange"
- Event_SysInfo = "sysinfo"
+ Event_BlockClose = "blockclose"
+ Event_ConnChange = "connchange"
+ Event_SysInfo = "sysinfo"
+ Event_ControllerStatus = "controllerstatus"
)
const (