mirror of
https://github.com/tiqi-group/pydase.git
synced 2025-04-21 00:40:01 +02:00
feat: added frontend exception notifications
This commit is contained in:
parent
85a171c33e
commit
b30295d840
@ -16,3 +16,6 @@ input.instantUpdate {
|
|||||||
.notificationToast {
|
.notificationToast {
|
||||||
background-color: rgba(114, 214, 253, 0.5) !important;
|
background-color: rgba(114, 214, 253, 0.5) !important;
|
||||||
}
|
}
|
||||||
|
.exceptionToast {
|
||||||
|
background-color: rgba(216, 41, 18, 0.678) !important;
|
||||||
|
}
|
@ -20,9 +20,12 @@ type State = DataServiceJSON | null;
|
|||||||
type Action =
|
type Action =
|
||||||
| { type: 'SET_DATA'; data: DataServiceJSON }
|
| { type: 'SET_DATA'; data: DataServiceJSON }
|
||||||
| { type: 'UPDATE_ATTRIBUTE'; parent_path: string; name: string; value: ValueType };
|
| { type: 'UPDATE_ATTRIBUTE'; parent_path: string; name: string; value: ValueType };
|
||||||
type NotificationElement = {
|
type UpdateNotification = {
|
||||||
data: { parent_path: string; name: string; value: object };
|
data: { parent_path: string; name: string; value: object };
|
||||||
};
|
};
|
||||||
|
type ExceptionNotification = {
|
||||||
|
data: { exception: string; type: string };
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A function to update a specific property in a deeply nested object.
|
* A function to update a specific property in a deeply nested object.
|
||||||
@ -128,7 +131,7 @@ const App = () => {
|
|||||||
const handleCloseSettings = () => setShowSettings(false);
|
const handleCloseSettings = () => setShowSettings(false);
|
||||||
const handleShowSettings = () => setShowSettings(true);
|
const handleShowSettings = () => setShowSettings(true);
|
||||||
|
|
||||||
function onNotify(value: NotificationElement) {
|
function onNotify(value: UpdateNotification) {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: 'UPDATE_ATTRIBUTE',
|
type: 'UPDATE_ATTRIBUTE',
|
||||||
parent_path: value.data.parent_path,
|
parent_path: value.data.parent_path,
|
||||||
@ -142,6 +145,15 @@ const App = () => {
|
|||||||
setNotifications((prevNotifications) => [newNotification, ...prevNotifications]);
|
setNotifications((prevNotifications) => [newNotification, ...prevNotifications]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function onException(value: ExceptionNotification) {
|
||||||
|
const newNotification = {
|
||||||
|
type: 'exception',
|
||||||
|
id: Math.random(),
|
||||||
|
text: `${value.data.type}: ${value.data.exception}.`
|
||||||
|
};
|
||||||
|
setNotifications((prevNotifications) => [newNotification, ...prevNotifications]);
|
||||||
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// Fetch data from the API when the component mounts
|
// Fetch data from the API when the component mounts
|
||||||
fetch(`http://${hostname}:${port}/service-properties`)
|
fetch(`http://${hostname}:${port}/service-properties`)
|
||||||
@ -149,9 +161,11 @@ const App = () => {
|
|||||||
.then((data: DataServiceJSON) => dispatch({ type: 'SET_DATA', data }));
|
.then((data: DataServiceJSON) => dispatch({ type: 'SET_DATA', data }));
|
||||||
|
|
||||||
socket.on('notify', onNotify);
|
socket.on('notify', onNotify);
|
||||||
|
socket.on('exception', onException);
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
socket.off('notify', onNotify);
|
socket.off('notify', onNotify);
|
||||||
|
socket.off('exception', onException);
|
||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
@ -175,7 +189,11 @@ const App = () => {
|
|||||||
style={{ position: 'fixed' }}>
|
style={{ position: 'fixed' }}>
|
||||||
{notifications.map((notification) => (
|
{notifications.map((notification) => (
|
||||||
<Toast
|
<Toast
|
||||||
className="notificationToast"
|
className={
|
||||||
|
notification.type === 'exception'
|
||||||
|
? 'exceptionToast'
|
||||||
|
: 'notificationToast'
|
||||||
|
}
|
||||||
key={notification.id}
|
key={notification.id}
|
||||||
onClose={() => {
|
onClose={() => {
|
||||||
removeNotificationById(notification.id);
|
removeNotificationById(notification.id);
|
||||||
@ -184,13 +202,25 @@ const App = () => {
|
|||||||
removeNotificationById(notification.id);
|
removeNotificationById(notification.id);
|
||||||
}}
|
}}
|
||||||
onMouseLeave={() => {
|
onMouseLeave={() => {
|
||||||
|
// For exception type notifications, do not dismiss on mouse leave
|
||||||
|
if (notification.type !== 'exception') {
|
||||||
removeNotificationById(notification.id);
|
removeNotificationById(notification.id);
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
show={true}
|
show={true}
|
||||||
autohide
|
autohide={notification.type !== 'exception'} // Do not autohide for 'exception' type notifications
|
||||||
delay={2000}>
|
delay={notification.type === 'exception' ? 0 : 2000} // No delay for 'exception' type notifications
|
||||||
<Toast.Header closeButton={false} className="notificationToast">
|
>
|
||||||
<strong className="mr-auto">Notification</strong>
|
<Toast.Header
|
||||||
|
closeButton={false}
|
||||||
|
className={
|
||||||
|
notification.type === 'exception'
|
||||||
|
? 'exceptionToast'
|
||||||
|
: 'notificationToast'
|
||||||
|
}>
|
||||||
|
<strong className="mr-auto">
|
||||||
|
{notification.type === 'exception' ? 'Exception' : 'Notification'}
|
||||||
|
</strong>
|
||||||
</Toast.Header>
|
</Toast.Header>
|
||||||
<Toast.Body>{notification.text}</Toast.Body>
|
<Toast.Body>{notification.text}</Toast.Body>
|
||||||
</Toast>
|
</Toast>
|
||||||
|
@ -396,6 +396,7 @@ class Server:
|
|||||||
if self._enable_web:
|
if self._enable_web:
|
||||||
|
|
||||||
async def emit_exception() -> None:
|
async def emit_exception() -> None:
|
||||||
|
try:
|
||||||
await self._wapi.sio.emit( # type: ignore
|
await self._wapi.sio.emit( # type: ignore
|
||||||
"exception",
|
"exception",
|
||||||
{
|
{
|
||||||
@ -405,6 +406,8 @@ class Server:
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(f"Failed to send notification: {e}")
|
||||||
|
|
||||||
loop.create_task(emit_exception())
|
loop.create_task(emit_exception())
|
||||||
else:
|
else:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user