TDMS/web/src/components/NotificationContainer.tsx
Maksim Skobaro d298a5f1f4 Improvements
2025-02-15 13:54:53 +03:00

88 lines
3.3 KiB
TypeScript

import {ComponentContext} from "../utils/ComponentContext";
import {observer} from "mobx-react";
import {Notification, NotificationType} from "../store/NotificationStore";
import {Card, CardBody, CardHeader, CardText, CardTitle} from "react-bootstrap";
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
import {action, makeObservable} from "mobx";
@observer
export class NotificationContainer extends ComponentContext {
forEachNotificationRender(notifications: Notification[], type: NotificationType) {
return notifications.map(notification => (
<NotificationPopup key={notification.uuid} notification={notification} type={type}/>
));
}
render() {
return <div style={{position: 'fixed', left: '50%', transform: 'translateX(-50%)', zIndex: 2000}}>
{this.forEachNotificationRender(this.notificationStore.errors, NotificationType.ERROR)}
{this.forEachNotificationRender(this.notificationStore.successes, NotificationType.SUCCESS)}
{this.forEachNotificationRender(this.notificationStore.warnings, NotificationType.WARNING)}
{this.forEachNotificationRender(this.notificationStore.infos, NotificationType.INFO)}
</div>
}
}
@observer
class NotificationPopup extends ComponentContext<{ notification: Notification, type: NotificationType }> {
constructor(props: { notification: Notification, type: NotificationType }) {
super(props);
makeObservable(this);
}
@action.bound
close() {
this.notificationStore.close(this.props.notification.uuid);
}
get cardClassName() {
switch (this.props.type) {
case NotificationType.ERROR:
return 'text-bg-danger';
case NotificationType.WARNING:
return 'text-bg-warning';
case NotificationType.INFO:
return 'text-bg-info';
case NotificationType.SUCCESS:
return 'text-bg-success';
}
}
render() {
const hasTitle = !!this.props.notification.title && this.props.notification.title.length > 0;
const title = this.props.notification.title?.split('\n').map((item, key) =>
<span key={key}>{item}<br/></span>);
const message = this.props.notification.message?.split('\n').map((item, key) =>
<span key={key}>{item}<br/></span>);
const closeIcon = <span className={'ms-2'}>
<FontAwesomeIcon icon={'close'} onClick={this.close}/>
</span>;
return <Card className={`position-relative mt-3 opacity-75 ${this.cardClassName}`}>
{
hasTitle &&
<CardHeader>
<CardTitle className={'d-flex justify-content-between align-items-start'}>
<span>
{title}
</span>
{closeIcon}
</CardTitle>
</CardHeader>
}
<CardBody>
<CardText className={'d-flex justify-content-between align-items-start'}>
<span>
{message ?? ''}
</span>
{
!hasTitle &&
closeIcon
}
</CardText>
</CardBody>
</Card>
}
}