88 lines
3.3 KiB
TypeScript
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>
|
|
}
|
|
} |