2020-12-02 12:56:26 +00:00
|
|
|
import { LitElement, html, customElement, TemplateResult } from "lit-element";
|
|
|
|
import { DefaultClient } from "../api/client";
|
2020-10-16 13:26:51 +00:00
|
|
|
|
2020-11-20 21:08:00 +00:00
|
|
|
const LEVEL_ICON_MAP: { [key: string]: string } = {
|
2020-11-21 19:48:49 +00:00
|
|
|
error: "fas fa-exclamation-circle",
|
|
|
|
warning: "fas fa-exclamation-triangle",
|
|
|
|
success: "fas fa-check-circle",
|
|
|
|
info: "fas fa-info",
|
2020-10-16 13:26:51 +00:00
|
|
|
};
|
|
|
|
|
2020-12-01 08:15:41 +00:00
|
|
|
const ID = function (prefix: string) {
|
2020-10-16 14:30:38 +00:00
|
|
|
return prefix + Math.random().toString(36).substr(2, 9);
|
2020-10-16 13:26:51 +00:00
|
|
|
};
|
|
|
|
|
2020-11-20 21:08:00 +00:00
|
|
|
interface Message {
|
2020-12-01 16:27:19 +00:00
|
|
|
level_tag: string;
|
2020-11-26 17:36:26 +00:00
|
|
|
tags: string;
|
2020-11-20 21:08:00 +00:00
|
|
|
message: string;
|
|
|
|
}
|
2020-10-16 13:26:51 +00:00
|
|
|
|
2020-11-20 21:08:00 +00:00
|
|
|
@customElement("pb-messages")
|
|
|
|
export class Messages extends LitElement {
|
2020-12-02 12:56:26 +00:00
|
|
|
url = DefaultClient.makeUrl(["root", "messages"]);
|
2020-11-20 21:08:00 +00:00
|
|
|
|
2020-11-26 16:23:29 +00:00
|
|
|
messageSocket?: WebSocket;
|
2020-12-01 08:15:41 +00:00
|
|
|
retryDelay = 200;
|
2020-11-26 17:04:24 +00:00
|
|
|
|
2020-12-01 16:27:19 +00:00
|
|
|
createRenderRoot(): ShadowRoot | Element {
|
2020-10-16 13:26:51 +00:00
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
2020-11-26 16:23:29 +00:00
|
|
|
constructor() {
|
|
|
|
super();
|
2020-11-26 17:36:26 +00:00
|
|
|
try {
|
|
|
|
this.connect();
|
|
|
|
} catch (error) {
|
|
|
|
console.warn(`passbook/messages: failed to connect to ws ${error}`);
|
|
|
|
}
|
2020-10-16 18:11:24 +00:00
|
|
|
}
|
|
|
|
|
2020-12-01 16:27:19 +00:00
|
|
|
firstUpdated(): void {
|
2020-11-26 17:16:50 +00:00
|
|
|
this.fetchMessages();
|
|
|
|
}
|
|
|
|
|
2020-12-01 16:27:19 +00:00
|
|
|
connect(): void {
|
2020-11-26 16:23:29 +00:00
|
|
|
const wsUrl = `${window.location.protocol.replace("http", "ws")}//${
|
|
|
|
window.location.host
|
|
|
|
}/ws/client/`;
|
|
|
|
this.messageSocket = new WebSocket(wsUrl);
|
2020-12-01 16:27:19 +00:00
|
|
|
this.messageSocket.addEventListener("open", () => {
|
2020-11-26 16:23:29 +00:00
|
|
|
console.debug(`passbook/messages: connected to ${wsUrl}`);
|
|
|
|
});
|
|
|
|
this.messageSocket.addEventListener("close", (e) => {
|
|
|
|
console.debug(`passbook/messages: closed ws connection: ${e}`);
|
|
|
|
setTimeout(() => {
|
2020-11-26 22:35:59 +00:00
|
|
|
console.debug(`passbook/messages: reconnecting ws in ${this.retryDelay}ms`);
|
2020-11-26 16:23:29 +00:00
|
|
|
this.connect();
|
2020-11-26 17:04:24 +00:00
|
|
|
}, this.retryDelay);
|
|
|
|
this.retryDelay = this.retryDelay * 2;
|
2020-11-26 16:23:29 +00:00
|
|
|
});
|
|
|
|
this.messageSocket.addEventListener("message", (e) => {
|
|
|
|
const data = JSON.parse(e.data);
|
2020-11-26 17:36:26 +00:00
|
|
|
this.renderMessage(data);
|
2020-11-26 16:23:29 +00:00
|
|
|
});
|
2020-11-26 17:36:26 +00:00
|
|
|
this.messageSocket.addEventListener("error", (e) => {
|
|
|
|
console.warn(`passbook/messages: error ${e}`);
|
|
|
|
this.retryDelay = this.retryDelay * 2;
|
2020-11-26 21:37:41 +00:00
|
|
|
});
|
2020-10-16 13:26:51 +00:00
|
|
|
}
|
|
|
|
|
2020-11-26 17:16:50 +00:00
|
|
|
/* Fetch messages which were stored in the session.
|
|
|
|
* This mostly gets messages which were created when the user arrives/leaves the site
|
|
|
|
* and especially the login flow */
|
2020-12-01 16:27:19 +00:00
|
|
|
fetchMessages(): Promise<void> {
|
2020-12-01 08:15:41 +00:00
|
|
|
console.debug("passbook/messages: fetching messages over direct api");
|
2020-11-26 17:16:50 +00:00
|
|
|
return fetch(this.url)
|
|
|
|
.then((r) => r.json())
|
2020-12-01 16:27:19 +00:00
|
|
|
.then((r: Message[]) => {
|
|
|
|
r.forEach((m: Message) => {
|
|
|
|
this.renderMessage(m);
|
2020-11-26 17:16:50 +00:00
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2020-12-01 16:27:19 +00:00
|
|
|
renderMessage(message: Message): void {
|
|
|
|
const container = <HTMLElement>this.querySelector(".pf-c-alert-group");
|
|
|
|
if (!container) {
|
|
|
|
console.warn("passbook/messages: failed to find container");
|
|
|
|
return;
|
|
|
|
}
|
2020-10-16 14:30:38 +00:00
|
|
|
const id = ID("pb-message");
|
|
|
|
const el = document.createElement("template");
|
|
|
|
el.innerHTML = `<li id=${id} class="pf-c-alert-group__item">
|
2020-12-01 16:27:19 +00:00
|
|
|
<div class="pf-c-alert pf-m-${message.level_tag} ${message.level_tag === "error" ? "pf-m-danger" : ""}">
|
2020-10-16 13:26:51 +00:00
|
|
|
<div class="pf-c-alert__icon">
|
2020-12-01 16:27:19 +00:00
|
|
|
<i class="${LEVEL_ICON_MAP[message.level_tag]}"></i>
|
2020-10-16 13:26:51 +00:00
|
|
|
</div>
|
|
|
|
<p class="pf-c-alert__title">
|
|
|
|
${message.message}
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
</li>`;
|
|
|
|
setTimeout(() => {
|
2020-11-20 21:08:00 +00:00
|
|
|
this.querySelector(`#${id}`)?.remove();
|
2020-10-16 13:26:51 +00:00
|
|
|
}, 1500);
|
2020-12-01 16:27:19 +00:00
|
|
|
container.appendChild(el.content.firstChild!); // eslint-disable-line
|
2020-10-16 13:26:51 +00:00
|
|
|
}
|
|
|
|
|
2020-12-01 16:27:19 +00:00
|
|
|
render(): TemplateResult {
|
2020-10-16 17:22:44 +00:00
|
|
|
return html`<ul class="pf-c-alert-group pf-m-toast"></ul>`;
|
2020-10-16 13:26:51 +00:00
|
|
|
}
|
|
|
|
}
|