This repository has been archived on 2024-10-24. You can view files and clone it, but cannot push or open issues or pull requests.
fradrive-old/frontend/src/utils/alerts/alerts.js
2020-04-16 17:19:16 +02:00

171 lines
4.8 KiB
JavaScript

import { Utility } from '../../core/utility';
import './alerts.sass';
const ALERTS_INITIALIZED_CLASS = 'alerts--initialized';
const ALERTS_ELEVATED_CLASS = 'alerts--elevated';
const ALERTS_TOGGLER_CLASS = 'alerts__toggler';
const ALERTS_TOGGLER_VISIBLE_CLASS = 'alerts__toggler--visible';
const ALERTS_TOGGLER_APPEAR_DELAY = 120;
const ALERT_CLASS = 'alert';
const ALERT_INITIALIZED_CLASS = 'alert--initialized';
const ALERT_CLOSER_CLASS = 'alert__closer';
const ALERT_ICON_CLASS = 'alert__icon';
const ALERT_CONTENT_CLASS = 'alert__content';
const ALERT_INVISIBLE_CLASS = 'alert--invisible';
const ALERT_AUTO_HIDE_DELAY = 10;
const ALERT_AUTOCLOSING_MATCHER = '.alert-info, .alert-success';
/*
* Dataset-Inputs:
* - decay (data-decay): Custom time (in seconds) for this alert to stay visible
*/
@Utility({
selector: '[uw-alerts]',
})
export class Alerts {
_togglerCheckRequested = false;
_togglerElement;
_alertElements;
_element;
_app;
constructor(element, app) {
if (!element) {
throw new Error('Alerts util has to be called with an element!');
}
this._element = element;
this._app = app;
if (this._element.classList.contains(ALERTS_INITIALIZED_CLASS)) {
return false;
}
this._togglerElement = this._element.querySelector('.' + ALERTS_TOGGLER_CLASS);
this._alertElements = this._gatherAlertElements();
if (this._togglerElement) {
this._initToggler();
}
this._initAlerts();
// register http client interceptor to filter out Alerts Header
this._setupHttpInterceptor();
// mark initialized
this._element.classList.add(ALERTS_INITIALIZED_CLASS);
}
destroy() {
console.log('TBD: Destroy Alert');
}
_gatherAlertElements() {
return Array.from(this._element.querySelectorAll('.' + ALERT_CLASS)).filter(function(alert) {
return !alert.classList.contains(ALERT_INITIALIZED_CLASS);
});
}
_initToggler() {
this._togglerElement.addEventListener('click', () => {
this._alertElements.forEach((alertEl) => this._toggleAlert(alertEl, true));
this._togglerElement.classList.remove(ALERTS_TOGGLER_VISIBLE_CLASS);
});
}
_initAlerts() {
this._alertElements.forEach((alert) => this._initAlert(alert));
}
_initAlert(alertElement) {
let autoHideDelay = ALERT_AUTO_HIDE_DELAY;
if (alertElement.dataset.decay) {
autoHideDelay = parseInt(alertElement.dataset.decay, 10);
}
const closeEl = alertElement.querySelector('.' + ALERT_CLOSER_CLASS);
closeEl.addEventListener('click', () => {
this._toggleAlert(alertElement);
});
if (autoHideDelay > 0 && alertElement.matches(ALERT_AUTOCLOSING_MATCHER)) {
window.setTimeout(() => this._toggleAlert(alertElement), autoHideDelay * 1000);
}
}
_toggleAlert(alertEl, visible) {
alertEl.classList.toggle(ALERT_INVISIBLE_CLASS, !visible);
this._checkToggler();
}
_checkToggler() {
if (this._togglerCheckRequested) {
return;
}
const alertsHidden = this._alertElements.reduce(function(acc, alert) {
return acc && alert.classList.contains(ALERT_INVISIBLE_CLASS);
}, true);
window.setTimeout(() => {
this._togglerElement.classList.toggle(ALERTS_TOGGLER_VISIBLE_CLASS, alertsHidden);
this._togglerCheckRequested = false;
}, ALERTS_TOGGLER_APPEAR_DELAY);
}
_setupHttpInterceptor() {
this._app.httpClient.addResponseInterceptor(this._responseInterceptor.bind(this));
}
_elevateAlerts() {
this._element.classList.add(ALERTS_ELEVATED_CLASS);
}
_responseInterceptor = (response) => {
let alerts;
for (const header of response.headers) {
if (header[0] === 'alerts') {
const decodedHeader = decodeURIComponent(header[1]);
alerts = JSON.parse(decodedHeader);
break;
}
}
if (alerts) {
alerts.forEach((alert) => {
const alertElement = this._createAlertElement(alert.status, alert.content, alert.icon === null ? undefined : alert.icon);
this._element.appendChild(alertElement);
this._alertElements.push(alertElement);
this._initAlert(alertElement);
});
this._elevateAlerts();
}
}
_createAlertElement(type, content, icon = 'info-circle') {
const alertElement = document.createElement('div');
alertElement.classList.add(ALERT_CLASS, 'alert-' + type);
const alertCloser = document.createElement('div');
alertCloser.classList.add(ALERT_CLOSER_CLASS);
const alertIcon = document.createElement('div');
alertIcon.classList.add(ALERT_ICON_CLASS, 'fas', 'fa-' + icon);
const alertContent = document.createElement('div');
alertContent.classList.add(ALERT_CONTENT_CLASS);
alertContent.innerHTML = content;
alertElement.appendChild(alertCloser);
alertElement.appendChild(alertIcon);
alertElement.appendChild(alertContent);
return alertElement;
}
}