mirror of
https://github.com/aljazceru/hummingbot-dashboard.git
synced 2025-12-23 16:24:22 +01:00
(feat) add error handling for active instances
This commit is contained in:
@@ -109,7 +109,9 @@ class BackendAPIClient:
|
|||||||
url = f"{self.base_url}/get-bot-status/{bot_name}"
|
url = f"{self.base_url}/get-bot-status/{bot_name}"
|
||||||
response = requests.get(url)
|
response = requests.get(url)
|
||||||
if response.status_code == 200:
|
if response.status_code == 200:
|
||||||
return response.json()["data"]
|
return response.json()
|
||||||
|
else:
|
||||||
|
return {"status": "error", "data": "Bot not found"}
|
||||||
|
|
||||||
def get_bot_history(self, bot_name: str):
|
def get_bot_history(self, bot_name: str):
|
||||||
"""Get the historical data of a bot."""
|
"""Get the historical data of a bot."""
|
||||||
@@ -127,7 +129,7 @@ class BackendAPIClient:
|
|||||||
if response.status_code == 200:
|
if response.status_code == 200:
|
||||||
return response.json() # Successful request
|
return response.json() # Successful request
|
||||||
else:
|
else:
|
||||||
return response.json() # Handle errors or no data found
|
return {"status": "error", "data": "No active bots found"}
|
||||||
|
|
||||||
def get_all_controllers_config(self):
|
def get_all_controllers_config(self):
|
||||||
"""Get all controller configurations."""
|
"""Get all controller configurations."""
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import time
|
||||||
|
|
||||||
from streamlit_elements import mui
|
from streamlit_elements import mui
|
||||||
|
|
||||||
from CONFIG import BACKEND_API_HOST, BACKEND_API_PORT
|
from CONFIG import BACKEND_API_HOST, BACKEND_API_PORT
|
||||||
@@ -44,10 +46,17 @@ class BotPerformanceCardV2(Dashboard.Item):
|
|||||||
def _handle_active_row_selection(self, params, _):
|
def _handle_active_row_selection(self, params, _):
|
||||||
self._active_controller_config_selected = params
|
self._active_controller_config_selected = params
|
||||||
|
|
||||||
def stop_controllers(self, bot_name):
|
def _handle_errors_row_selection(self, params, _):
|
||||||
|
self._error_controller_config_selected = params
|
||||||
|
|
||||||
|
def stop_active_controllers(self, bot_name):
|
||||||
for controller in self._active_controller_config_selected:
|
for controller in self._active_controller_config_selected:
|
||||||
self._backend_api_client.stop_controller_from_bot(bot_name, controller)
|
self._backend_api_client.stop_controller_from_bot(bot_name, controller)
|
||||||
|
|
||||||
|
def stop_errors_controllers(self, bot_name):
|
||||||
|
for controller in self._error_controller_config_selected:
|
||||||
|
self._backend_api_client.stop_controller_from_bot(bot_name, controller)
|
||||||
|
|
||||||
def start_controllers(self, bot_name):
|
def start_controllers(self, bot_name):
|
||||||
for controller in self._stopped_controller_config_selected:
|
for controller in self._stopped_controller_config_selected:
|
||||||
self._backend_api_client.start_controller_from_bot(bot_name, controller)
|
self._backend_api_client.start_controller_from_bot(bot_name, controller)
|
||||||
@@ -56,166 +65,210 @@ class BotPerformanceCardV2(Dashboard.Item):
|
|||||||
try:
|
try:
|
||||||
controller_configs = backend_api_client.get_all_configs_from_bot(bot_name)
|
controller_configs = backend_api_client.get_all_configs_from_bot(bot_name)
|
||||||
bot_status = backend_api_client.get_bot_status(bot_name)
|
bot_status = backend_api_client.get_bot_status(bot_name)
|
||||||
is_running = False
|
# Controllers Table
|
||||||
if bot_status and len(bot_status) > 0:
|
active_controllers_list = []
|
||||||
# Controllers Table
|
stopped_controllers_list = []
|
||||||
active_controllers_list = []
|
error_controllers_list = []
|
||||||
stopped_controllers_list = []
|
total_global_pnl_quote = 0
|
||||||
total_global_pnl_quote = 0
|
total_volume_traded = 0
|
||||||
total_volume_traded = 0
|
total_open_order_volume = 0
|
||||||
total_open_order_volume = 0
|
total_imbalance = 0
|
||||||
total_imbalance = 0
|
total_unrealized_pnl_quote = 0
|
||||||
total_unrealized_pnl_quote = 0
|
if bot_status.get("status") == "error":
|
||||||
for controller, inner_dict in bot_status.items():
|
with mui.Card(key=self._key,
|
||||||
controller_config = next((config for config in controller_configs if config.get("id") == controller),
|
sx={"display": "flex", "flexDirection": "column", "borderRadius": 2, "overflow": "auto"},
|
||||||
{})
|
elevation=2):
|
||||||
kill_switch_status = True if controller_config.get("manual_kill_switch") is True else False
|
mui.CardHeader(
|
||||||
realized_pnl_quote = inner_dict.get("realized_pnl_quote", 0)
|
title=bot_name,
|
||||||
unrealized_pnl_quote = inner_dict.get("unrealized_pnl_quote", 0)
|
subheader="Not Available",
|
||||||
global_pnl_quote = inner_dict.get("global_pnl_quote", 0)
|
avatar=mui.Avatar("🤖", sx={"bgcolor": "red"}),
|
||||||
volume_traded = inner_dict.get("volume_traded", 0)
|
className=self._draggable_class)
|
||||||
open_order_volume = inner_dict.get("open_order_volume", 0)
|
mui.Alert(f"An error occurred while fetching bot status of the bot {bot_name}. Please check the bot client.", severity="error")
|
||||||
imbalance = inner_dict.get("imbalance", 0)
|
else:
|
||||||
controller_info = {
|
bot_data = bot_status.get("data")
|
||||||
"id": controller,
|
is_running = bot_data.get("status") == "running"
|
||||||
"realized_pnl_quote": realized_pnl_quote,
|
performance = bot_data.get("performance")
|
||||||
"unrealized_pnl_quote": unrealized_pnl_quote,
|
if is_running:
|
||||||
"global_pnl_quote": global_pnl_quote,
|
for controller, inner_dict in performance.items():
|
||||||
"volume_traded": volume_traded,
|
controller_status = inner_dict.get("status")
|
||||||
"open_order_volume": open_order_volume,
|
if controller_status == "error":
|
||||||
"imbalance": imbalance,
|
error_controllers_list.append(
|
||||||
}
|
{"id": controller, "error": inner_dict.get("error")})
|
||||||
if len(controller_info) > 0:
|
continue
|
||||||
is_running = True
|
controller_performance = inner_dict.get("performance")
|
||||||
if kill_switch_status:
|
controller_config = next((config for config in controller_configs if config.get("id") == controller), {})
|
||||||
stopped_controllers_list.append(controller_info)
|
kill_switch_status = True if controller_config.get("manual_kill_switch") is True else False
|
||||||
else:
|
realized_pnl_quote = controller_performance.get("realized_pnl_quote", 0)
|
||||||
active_controllers_list.append(controller_info)
|
unrealized_pnl_quote = controller_performance.get("unrealized_pnl_quote", 0)
|
||||||
total_global_pnl_quote += global_pnl_quote
|
global_pnl_quote = controller_performance.get("global_pnl_quote", 0)
|
||||||
total_volume_traded += volume_traded
|
volume_traded = controller_performance.get("volume_traded", 0)
|
||||||
total_open_order_volume += open_order_volume
|
open_order_volume = controller_performance.get("open_order_volume", 0)
|
||||||
total_imbalance += imbalance
|
imbalance = controller_performance.get("imbalance", 0)
|
||||||
total_unrealized_pnl_quote += unrealized_pnl_quote
|
controller_info = {
|
||||||
|
"id": controller,
|
||||||
|
"realized_pnl_quote": realized_pnl_quote,
|
||||||
|
"unrealized_pnl_quote": unrealized_pnl_quote,
|
||||||
|
"global_pnl_quote": global_pnl_quote,
|
||||||
|
"volume_traded": volume_traded,
|
||||||
|
"open_order_volume": open_order_volume,
|
||||||
|
"imbalance": imbalance,
|
||||||
|
}
|
||||||
|
if kill_switch_status:
|
||||||
|
stopped_controllers_list.append(controller_info)
|
||||||
|
else:
|
||||||
|
active_controllers_list.append(controller_info)
|
||||||
|
total_global_pnl_quote += global_pnl_quote
|
||||||
|
total_volume_traded += volume_traded
|
||||||
|
total_open_order_volume += open_order_volume
|
||||||
|
total_imbalance += imbalance
|
||||||
|
total_unrealized_pnl_quote += unrealized_pnl_quote
|
||||||
total_global_pnl_pct = total_global_pnl_quote / total_volume_traded if total_volume_traded > 0 else 0
|
total_global_pnl_pct = total_global_pnl_quote / total_volume_traded if total_volume_traded > 0 else 0
|
||||||
|
|
||||||
if is_running:
|
|
||||||
status = "Running"
|
|
||||||
color = "green"
|
|
||||||
else:
|
|
||||||
status = "Stopped"
|
|
||||||
color = "red"
|
|
||||||
|
|
||||||
with mui.Card(key=self._key,
|
|
||||||
sx={"display": "flex", "flexDirection": "column", "borderRadius": 2, "overflow": "auto"},
|
|
||||||
elevation=2):
|
|
||||||
mui.CardHeader(
|
|
||||||
title=bot_name,
|
|
||||||
subheader=status,
|
|
||||||
avatar=mui.Avatar("🤖", sx={"bgcolor": color}),
|
|
||||||
action=mui.IconButton(mui.icon.Stop, onClick=lambda: stop_bot(bot_name)) if is_running else mui.IconButton(mui.icon.Archive, onClick=lambda: archive_bot(bot_name)),
|
|
||||||
className=self._draggable_class)
|
|
||||||
if is_running:
|
if is_running:
|
||||||
with mui.CardContent(sx={"flex": 1}):
|
status = "Running"
|
||||||
with mui.Grid(container=True, spacing=2, sx={"padding": "10px 15px 10px 15px"}):
|
color = "green"
|
||||||
with mui.Grid(item=True, xs=2):
|
else:
|
||||||
with mui.Paper(key=self._key,
|
status = "Stopped"
|
||||||
sx={"display": "flex", "flexDirection": "column", "borderRadius": 3,
|
color = "red"
|
||||||
"overflow": "hidden"},
|
|
||||||
elevation=1):
|
|
||||||
with self.title_bar(padding="10px 15px 10px 15px", dark_switcher=False):
|
|
||||||
mui.Typography("🏦 NET PNL", variant="h6")
|
|
||||||
mui.Typography(f"$ {total_global_pnl_quote:.2f}", variant="h6", sx={"padding": "10px 15px 10px 15px"})
|
|
||||||
with mui.Grid(item=True, xs=2):
|
|
||||||
with mui.Paper(key=self._key,
|
|
||||||
sx={"display": "flex", "flexDirection": "column", "borderRadius": 3,
|
|
||||||
"overflow": "hidden"},
|
|
||||||
elevation=1):
|
|
||||||
with self.title_bar(padding="10px 15px 10px 15px", dark_switcher=False):
|
|
||||||
mui.Typography("📊 NET PNL (%)", variant="h6")
|
|
||||||
mui.Typography(f"{total_global_pnl_pct:.2%}", variant="h6", sx={"padding": "10px 15px 10px 15px"})
|
|
||||||
with mui.Grid(item=True, xs=2):
|
|
||||||
with mui.Paper(key=self._key,
|
|
||||||
sx={"display": "flex", "flexDirection": "column", "borderRadius": 3,
|
|
||||||
"overflow": "hidden"},
|
|
||||||
elevation=1):
|
|
||||||
with self.title_bar(padding="10px 15px 10px 15px", dark_switcher=False):
|
|
||||||
mui.Typography("💸 Volume Traded", variant="h6")
|
|
||||||
mui.Typography(f"$ {total_volume_traded:.2f}", variant="h6", sx={"padding": "10px 15px 10px 15px"})
|
|
||||||
with mui.Grid(item=True, xs=2):
|
|
||||||
with mui.Paper(key=self._key,
|
|
||||||
sx={"display": "flex", "flexDirection": "column", "borderRadius": 3,
|
|
||||||
"overflow": "hidden"},
|
|
||||||
elevation=1):
|
|
||||||
with self.title_bar(padding="10px 15px 10px 15px", dark_switcher=False):
|
|
||||||
mui.Typography("📖 Liquidity Placed", variant="h6")
|
|
||||||
mui.Typography(f"$ {total_open_order_volume:.2f}", variant="h6", sx={"padding": "10px 15px 10px 15px"})
|
|
||||||
with mui.Grid(item=True, xs=2):
|
|
||||||
with mui.Paper(key=self._key,
|
|
||||||
sx={"display": "flex", "flexDirection": "column", "borderRadius": 3,
|
|
||||||
"overflow": "hidden"},
|
|
||||||
elevation=1):
|
|
||||||
with self.title_bar(padding="10px 15px 10px 15px", dark_switcher=False):
|
|
||||||
mui.Typography("💹 Unrealized PNL", variant="h6")
|
|
||||||
mui.Typography(f"$ {total_unrealized_pnl_quote:.2f}", variant="h6", sx={"padding": "10px 15px 10px 15px"})
|
|
||||||
with mui.Grid(item=True, xs=2):
|
|
||||||
with mui.Paper(key=self._key,
|
|
||||||
sx={"display": "flex", "flexDirection": "column", "borderRadius": 3,
|
|
||||||
"overflow": "hidden"},
|
|
||||||
elevation=1):
|
|
||||||
with self.title_bar(padding="10px 15px 10px 15px", dark_switcher=False):
|
|
||||||
mui.Typography("📊 Imbalance", variant="h6")
|
|
||||||
mui.Typography(f"$ {total_imbalance:.2f}", variant="h6", sx={"padding": "10px 15px 10px 15px"})
|
|
||||||
|
|
||||||
with mui.Grid(container=True, spacing=1, sx={"padding": "10px 15px 10px 15px"}):
|
with mui.Card(key=self._key,
|
||||||
with mui.Grid(item=True, xs=11):
|
sx={"display": "flex", "flexDirection": "column", "borderRadius": 2, "overflow": "auto"},
|
||||||
with mui.Paper(key=self._key,
|
elevation=2):
|
||||||
sx={"display": "flex", "flexDirection": "column", "borderRadius": 3,
|
mui.CardHeader(
|
||||||
"overflow": "hidden"},
|
title=bot_name,
|
||||||
elevation=1):
|
subheader=status,
|
||||||
with self.title_bar(padding="10px 15px 10px 15px", dark_switcher=False):
|
avatar=mui.Avatar("🤖", sx={"bgcolor": color}),
|
||||||
mui.Typography("🚀 Active Controllers", variant="h6")
|
action=mui.IconButton(mui.icon.Stop, onClick=lambda: stop_bot(bot_name)) if is_running else mui.IconButton(mui.icon.Archive, onClick=lambda: archive_bot(bot_name)),
|
||||||
mui.DataGrid(
|
className=self._draggable_class)
|
||||||
rows=active_controllers_list,
|
if is_running:
|
||||||
columns=self.DEFAULT_COLUMNS,
|
with mui.CardContent(sx={"flex": 1}):
|
||||||
autoHeight=True,
|
with mui.Grid(container=True, spacing=2, sx={"padding": "10px 15px 10px 15px"}):
|
||||||
density="compact",
|
with mui.Grid(item=True, xs=2):
|
||||||
checkboxSelection=True,
|
with mui.Paper(key=self._key,
|
||||||
disableSelectionOnClick=True,
|
sx={"display": "flex", "flexDirection": "column", "borderRadius": 3,
|
||||||
onSelectionModelChange=self._handle_active_row_selection,
|
"overflow": "hidden"},
|
||||||
hideFooter=True
|
elevation=1):
|
||||||
)
|
with self.title_bar(padding="10px 15px 10px 15px", dark_switcher=False):
|
||||||
with mui.Grid(item=True, xs=1):
|
mui.Typography("🏦 NET PNL", variant="h6")
|
||||||
with mui.Button(onClick=lambda x: self.stop_controllers(bot_name),
|
mui.Typography(f"$ {total_global_pnl_quote:.3f}", variant="h6", sx={"padding": "10px 15px 10px 15px"})
|
||||||
variant="outlined",
|
with mui.Grid(item=True, xs=2):
|
||||||
color="warning",
|
with mui.Paper(key=self._key,
|
||||||
sx={"width": "100%", "height": "100%"}):
|
sx={"display": "flex", "flexDirection": "column", "borderRadius": 3,
|
||||||
mui.icon.AddCircleOutline()
|
"overflow": "hidden"},
|
||||||
mui.Typography("Stop")
|
elevation=1):
|
||||||
with mui.Grid(container=True, spacing=1, sx={"padding": "10px 15px 10px 15px"}):
|
with self.title_bar(padding="10px 15px 10px 15px", dark_switcher=False):
|
||||||
with mui.Grid(item=True, xs=11):
|
mui.Typography("📊 NET PNL (%)", variant="h6")
|
||||||
with mui.Paper(key=self._key,
|
mui.Typography(f"{total_global_pnl_pct:.3%}", variant="h6", sx={"padding": "10px 15px 10px 15px"})
|
||||||
sx={"display": "flex", "flexDirection": "column", "borderRadius": 3,
|
with mui.Grid(item=True, xs=2):
|
||||||
"overflow": "hidden"},
|
with mui.Paper(key=self._key,
|
||||||
elevation=1):
|
sx={"display": "flex", "flexDirection": "column", "borderRadius": 3,
|
||||||
with self.title_bar(padding="10px 15px 10px 15px", dark_switcher=False):
|
"overflow": "hidden"},
|
||||||
mui.Typography("💤 Stopped Controllers", variant="h6")
|
elevation=1):
|
||||||
mui.DataGrid(
|
with self.title_bar(padding="10px 15px 10px 15px", dark_switcher=False):
|
||||||
rows=stopped_controllers_list,
|
mui.Typography("💸 Volume Traded", variant="h6")
|
||||||
columns=self.DEFAULT_COLUMNS,
|
mui.Typography(f"$ {total_volume_traded:.2f}", variant="h6", sx={"padding": "10px 15px 10px 15px"})
|
||||||
autoHeight=True,
|
with mui.Grid(item=True, xs=2):
|
||||||
density="compact",
|
with mui.Paper(key=self._key,
|
||||||
checkboxSelection=True,
|
sx={"display": "flex", "flexDirection": "column", "borderRadius": 3,
|
||||||
disableSelectionOnClick=True,
|
"overflow": "hidden"},
|
||||||
onSelectionModelChange=self._handle_stopped_row_selection,
|
elevation=1):
|
||||||
hideFooter=True
|
with self.title_bar(padding="10px 15px 10px 15px", dark_switcher=False):
|
||||||
)
|
mui.Typography("📖 Liquidity Placed", variant="h6")
|
||||||
with mui.Grid(item=True, xs=1):
|
mui.Typography(f"$ {total_open_order_volume:.2f}", variant="h6", sx={"padding": "10px 15px 10px 15px"})
|
||||||
with mui.Button(onClick=lambda x: self.start_controllers(bot_name),
|
with mui.Grid(item=True, xs=2):
|
||||||
variant="outlined",
|
with mui.Paper(key=self._key,
|
||||||
color="success",
|
sx={"display": "flex", "flexDirection": "column", "borderRadius": 3,
|
||||||
sx={"width": "100%", "height": "100%"}):
|
"overflow": "hidden"},
|
||||||
mui.icon.AddCircleOutline()
|
elevation=1):
|
||||||
mui.Typography("Start")
|
with self.title_bar(padding="10px 15px 10px 15px", dark_switcher=False):
|
||||||
|
mui.Typography("💹 Unrealized PNL", variant="h6")
|
||||||
|
mui.Typography(f"$ {total_unrealized_pnl_quote:.2f}", variant="h6", sx={"padding": "10px 15px 10px 15px"})
|
||||||
|
with mui.Grid(item=True, xs=2):
|
||||||
|
with mui.Paper(key=self._key,
|
||||||
|
sx={"display": "flex", "flexDirection": "column", "borderRadius": 3,
|
||||||
|
"overflow": "hidden"},
|
||||||
|
elevation=1):
|
||||||
|
with self.title_bar(padding="10px 15px 10px 15px", dark_switcher=False):
|
||||||
|
mui.Typography("📊 Imbalance", variant="h6")
|
||||||
|
mui.Typography(f"$ {total_imbalance:.2f}", variant="h6", sx={"padding": "10px 15px 10px 15px"})
|
||||||
|
|
||||||
|
with mui.Grid(container=True, spacing=1, sx={"padding": "10px 15px 10px 15px"}):
|
||||||
|
with mui.Grid(item=True, xs=11):
|
||||||
|
with mui.Paper(key=self._key,
|
||||||
|
sx={"display": "flex", "flexDirection": "column", "borderRadius": 3,
|
||||||
|
"overflow": "hidden"},
|
||||||
|
elevation=1):
|
||||||
|
with self.title_bar(padding="10px 15px 10px 15px", dark_switcher=False):
|
||||||
|
mui.Typography("🚀 Active Controllers", variant="h6")
|
||||||
|
mui.DataGrid(
|
||||||
|
rows=active_controllers_list,
|
||||||
|
columns=self.DEFAULT_COLUMNS,
|
||||||
|
autoHeight=True,
|
||||||
|
density="compact",
|
||||||
|
checkboxSelection=True,
|
||||||
|
disableSelectionOnClick=True,
|
||||||
|
onSelectionModelChange=self._handle_active_row_selection,
|
||||||
|
hideFooter=True
|
||||||
|
)
|
||||||
|
with mui.Grid(item=True, xs=1):
|
||||||
|
with mui.Button(onClick=lambda x: self.stop_active_controllers(bot_name),
|
||||||
|
variant="outlined",
|
||||||
|
color="warning",
|
||||||
|
sx={"width": "100%", "height": "100%"}):
|
||||||
|
mui.icon.AddCircleOutline()
|
||||||
|
mui.Typography("Stop")
|
||||||
|
if len(stopped_controllers_list) > 0:
|
||||||
|
with mui.Grid(container=True, spacing=1, sx={"padding": "10px 15px 10px 15px"}):
|
||||||
|
with mui.Grid(item=True, xs=11):
|
||||||
|
with mui.Paper(key=self._key,
|
||||||
|
sx={"display": "flex", "flexDirection": "column", "borderRadius": 3,
|
||||||
|
"overflow": "hidden"},
|
||||||
|
elevation=1):
|
||||||
|
with self.title_bar(padding="10px 15px 10px 15px", dark_switcher=False):
|
||||||
|
mui.Typography("💤 Stopped Controllers", variant="h6")
|
||||||
|
mui.DataGrid(
|
||||||
|
rows=stopped_controllers_list,
|
||||||
|
columns=self.DEFAULT_COLUMNS,
|
||||||
|
autoHeight=True,
|
||||||
|
density="compact",
|
||||||
|
checkboxSelection=True,
|
||||||
|
disableSelectionOnClick=True,
|
||||||
|
onSelectionModelChange=self._handle_stopped_row_selection,
|
||||||
|
hideFooter=True
|
||||||
|
)
|
||||||
|
with mui.Grid(item=True, xs=1):
|
||||||
|
with mui.Button(onClick=lambda x: self.start_controllers(bot_name),
|
||||||
|
variant="outlined",
|
||||||
|
color="success",
|
||||||
|
sx={"width": "100%", "height": "100%"}):
|
||||||
|
mui.icon.AddCircleOutline()
|
||||||
|
mui.Typography("Start")
|
||||||
|
if len(error_controllers_list) > 0:
|
||||||
|
with mui.Grid(container=True, spacing=1, sx={"padding": "10px 15px 10px 15px"}):
|
||||||
|
with mui.Grid(item=True, xs=11):
|
||||||
|
with mui.Paper(key=self._key,
|
||||||
|
sx={"display": "flex", "flexDirection": "column", "borderRadius": 3,
|
||||||
|
"overflow": "hidden"},
|
||||||
|
elevation=1):
|
||||||
|
with self.title_bar(padding="10px 15px 10px 15px", dark_switcher=False):
|
||||||
|
mui.Typography("💀 Controllers with errors", variant="h6")
|
||||||
|
mui.DataGrid(
|
||||||
|
rows=error_controllers_list,
|
||||||
|
columns=self.DEFAULT_COLUMNS,
|
||||||
|
autoHeight=True,
|
||||||
|
density="compact",
|
||||||
|
checkboxSelection=True,
|
||||||
|
disableSelectionOnClick=True,
|
||||||
|
onSelectionModelChange=self._handle_errors_row_selection,
|
||||||
|
hideFooter=True
|
||||||
|
)
|
||||||
|
with mui.Grid(item=True, xs=1):
|
||||||
|
with mui.Button(onClick=lambda x: self.stop_errors_controllers(bot_name),
|
||||||
|
variant="outlined",
|
||||||
|
color="warning",
|
||||||
|
sx={"width": "100%", "height": "100%"}):
|
||||||
|
mui.icon.AddCircleOutline()
|
||||||
|
mui.Typography("Stop")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(e)
|
print(e)
|
||||||
with mui.Card(key=self._key,
|
with mui.Card(key=self._key,
|
||||||
@@ -229,4 +282,4 @@ class BotPerformanceCardV2(Dashboard.Item):
|
|||||||
className=self._draggable_class)
|
className=self._draggable_class)
|
||||||
with mui.CardContent(sx={"flex": 1}):
|
with mui.CardContent(sx={"flex": 1}):
|
||||||
mui.Typography("An error occurred while fetching bot status.", sx={"padding": "10px 15px 10px 15px"})
|
mui.Typography("An error occurred while fetching bot status.", sx={"padding": "10px 15px 10px 15px"})
|
||||||
mui.Typography(str(e), sx={"padding": "10px 15px 10px 15px"})
|
mui.Typography(str(e), sx={"padding": "10px 15px 10px 15px"})
|
||||||
@@ -21,7 +21,7 @@ def get_grid_positions(n_cards: int, cols: int = NUM_CARD_COLS, card_width: int
|
|||||||
return sorted(x_y, key=lambda x: (x[1], x[0]))
|
return sorted(x_y, key=lambda x: (x[1], x[0]))
|
||||||
|
|
||||||
|
|
||||||
def update_active_bots(api_client, active_instances_board):
|
def update_active_bots(api_client):
|
||||||
active_bots_response = api_client.get_active_bots_status()
|
active_bots_response = api_client.get_active_bots_status()
|
||||||
if active_bots_response.get("status") == "success":
|
if active_bots_response.get("status") == "success":
|
||||||
current_active_bots = active_bots_response.get("data")
|
current_active_bots = active_bots_response.get("data")
|
||||||
@@ -29,16 +29,12 @@ def update_active_bots(api_client, active_instances_board):
|
|||||||
|
|
||||||
new_bots = set(current_active_bots.keys()) - set(stored_bots.keys())
|
new_bots = set(current_active_bots.keys()) - set(stored_bots.keys())
|
||||||
removed_bots = set(stored_bots.keys()) - set(current_active_bots.keys())
|
removed_bots = set(stored_bots.keys()) - set(current_active_bots.keys())
|
||||||
|
|
||||||
for bot in new_bots:
|
|
||||||
x, y = get_grid_positions(1)[0] # Get a new position
|
|
||||||
card = BotPerformanceCardV2(active_instances_board, x, y, CARD_WIDTH, CARD_HEIGHT)
|
|
||||||
st.session_state.active_instances_board.bot_cards.append((card, bot))
|
|
||||||
|
|
||||||
for bot in removed_bots:
|
for bot in removed_bots:
|
||||||
st.session_state.active_instances_board.bot_cards = [card for card in st.session_state.active_instances_board.bot_cards if card[1] != bot]
|
st.session_state.active_instances_board.bot_cards = [card for card in st.session_state.active_instances_board.bot_cards if card[1] != bot]
|
||||||
|
positions = get_grid_positions(len(current_active_bots), NUM_CARD_COLS, CARD_WIDTH, CARD_HEIGHT)
|
||||||
st.session_state.active_instances_board.bot_cards.sort(key=lambda x: x[1]) # Sort by bot name
|
for bot, (x, y) in zip(new_bots, positions[:len(new_bots)]):
|
||||||
|
card = BotPerformanceCardV2(st.session_state.active_instances_board.dashboard, x, y, CARD_WIDTH, CARD_HEIGHT)
|
||||||
|
st.session_state.active_instances_board.bot_cards.append((card, bot))
|
||||||
|
|
||||||
|
|
||||||
initialize_st_page(title="Instances", icon="🦅")
|
initialize_st_page(title="Instances", icon="🦅")
|
||||||
@@ -49,26 +45,23 @@ if not api_client.is_docker_running():
|
|||||||
st.stop()
|
st.stop()
|
||||||
|
|
||||||
if "active_instances_board" not in st.session_state:
|
if "active_instances_board" not in st.session_state:
|
||||||
try:
|
active_bots_response = api_client.get_active_bots_status()
|
||||||
active_bots_response = api_client.get_active_bots_status()
|
bot_cards = []
|
||||||
active_bots = active_bots_response.get("data")
|
board = Dashboard()
|
||||||
bot_cards = []
|
st.session_state.active_instances_board = SimpleNamespace(
|
||||||
board = Dashboard()
|
dashboard=board,
|
||||||
if active_bots:
|
bot_cards=bot_cards,
|
||||||
positions = get_grid_positions(len(active_bots), NUM_CARD_COLS, CARD_WIDTH, CARD_HEIGHT)
|
)
|
||||||
for (bot, bot_info), (x, y) in zip(active_bots.items(), positions):
|
active_bots = active_bots_response.get("data")
|
||||||
card = BotPerformanceCardV2(board, x, y, CARD_WIDTH, CARD_HEIGHT)
|
number_of_bots = len(active_bots)
|
||||||
bot_cards.append((card, bot))
|
if number_of_bots > 0:
|
||||||
st.session_state.active_instances_board = SimpleNamespace(
|
positions = get_grid_positions(number_of_bots, NUM_CARD_COLS, CARD_WIDTH, CARD_HEIGHT)
|
||||||
dashboard=board,
|
for (bot, bot_info), (x, y) in zip(active_bots.items(), positions):
|
||||||
bot_cards=bot_cards,
|
bot_status = api_client.get_bot_status(bot)
|
||||||
)
|
card = BotPerformanceCardV2(board, x, y, CARD_WIDTH, CARD_HEIGHT)
|
||||||
except Exception as e:
|
st.session_state.active_instances_board.bot_cards.append((card, bot))
|
||||||
st.error(f"Error fetching active bots, reload the page if persists: {e}")
|
|
||||||
st.rerun()
|
|
||||||
else:
|
else:
|
||||||
active_instances_board = st.session_state.active_instances_board
|
update_active_bots(api_client)
|
||||||
update_active_bots(api_client, active_instances_board)
|
|
||||||
|
|
||||||
with elements("active_instances_board"):
|
with elements("active_instances_board"):
|
||||||
with mui.Paper(sx={"padding": "2rem"}, variant="outlined"):
|
with mui.Paper(sx={"padding": "2rem"}, variant="outlined"):
|
||||||
@@ -76,7 +69,3 @@ with elements("active_instances_board"):
|
|||||||
for card, bot in st.session_state.active_instances_board.bot_cards:
|
for card, bot in st.session_state.active_instances_board.bot_cards:
|
||||||
with st.session_state.active_instances_board.dashboard():
|
with st.session_state.active_instances_board.dashboard():
|
||||||
card(bot)
|
card(bot)
|
||||||
|
|
||||||
while True:
|
|
||||||
time.sleep(2)
|
|
||||||
st.rerun()
|
|
||||||
Reference in New Issue
Block a user