mirror of
https://github.com/hrfee/jfa-go.git
synced 2024-11-12 21:30:10 +00:00
add connection error notification, implement notify/delete function
This commit is contained in:
parent
1b41621569
commit
28187d0aa0
10
css/base.css
10
css/base.css
@ -274,6 +274,10 @@ sup.\~critical, .text-critical {
|
||||
resize: vertical;
|
||||
}
|
||||
|
||||
.overflow {
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
select {
|
||||
color: inherit;
|
||||
border: 0 solid var(--color-neutral-300);
|
||||
@ -291,4 +295,8 @@ p.top {
|
||||
margin-top: 0px;
|
||||
}
|
||||
|
||||
|
||||
#notification-box {
|
||||
position: fixed;
|
||||
right: 1rem;
|
||||
bottom: 1rem;
|
||||
}
|
||||
|
@ -113,6 +113,7 @@
|
||||
<input type="submit" class="button ~urge !normal full-width center supra submit" value="Submit">
|
||||
</form>
|
||||
</div>
|
||||
<div id="notification-box"></div>
|
||||
<div class="page-container max-w-screen-lg px-6 py-4 mx-auto lg:mx-auto md:py-8">
|
||||
<div class="mb-1">
|
||||
<header class="flex flex-wrap items-center justify-between">
|
||||
|
18
ts/admin.ts
18
ts/admin.ts
@ -2,6 +2,7 @@ import { toggleTheme, loadTheme } from "./modules/theme.js";
|
||||
import { Modal } from "./modules/modal.js";
|
||||
import { Tabs } from "./modules/tabs.js";
|
||||
import { inviteList } from "./modules/invites.js";
|
||||
import { notificationBox } from "./modules/common.js";
|
||||
|
||||
loadTheme();
|
||||
(document.getElementById('button-theme') as HTMLSpanElement).onclick = toggleTheme;
|
||||
@ -14,21 +15,8 @@ const whichAnimationEvent = () => {
|
||||
return "webkitAnimationEnd";
|
||||
}
|
||||
window.animationEvent = whichAnimationEvent();
|
||||
/*const toggles: HTMLInputElement[] = Array.from(document.getElementsByClassName('toggle-details'));
|
||||
for (let toggle of toggles) {
|
||||
toggle.onclick = () => {
|
||||
const el = toggle.parentElement.parentElement.parentElement.nextElementSibling as HTMLDivElement;
|
||||
if (el.classList.contains("focused")) {
|
||||
el.classList.toggle("focused");
|
||||
el.classList.toggle("unfocused");
|
||||
} else {
|
||||
el.classList.toggle("unfocused");
|
||||
el.classList.toggle("focused");
|
||||
}
|
||||
toggle.previousElementSibling.classList.toggle("rotated");
|
||||
toggle.previousElementSibling.classList.toggle("not-rotated");
|
||||
};
|
||||
}*/
|
||||
|
||||
window.notifications = new notificationBox(document.getElementById('notification-box') as HTMLDivElement, 5);
|
||||
|
||||
const checkInfUses = function (check: HTMLInputElement, mode = 2) {
|
||||
const uses = document.getElementById('inv-uses') as HTMLInputElement;
|
||||
|
@ -56,11 +56,11 @@ export const _get = (url: string, data: Object, onreadystatechange: (req: XMLHtt
|
||||
req.responseType = 'json';
|
||||
req.setRequestHeader("Authorization", "Bearer " + window.token);
|
||||
req.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
|
||||
req.onreadystatechange = () => { onreadystatechange(req); };
|
||||
req.onreadystatechange = () => { if (req.status == 0) { window.notifications.connectionError(); } else { onreadystatechange(req); } };
|
||||
req.send(JSON.stringify(data));
|
||||
};
|
||||
|
||||
export const _post = (url: string, data: Object, onreadystatechange: () => void, response?: boolean): void => {
|
||||
export const _post = (url: string, data: Object, onreadystatechange: (req: XMLHttpRequest) => void, response?: boolean): void => {
|
||||
let req = new XMLHttpRequest();
|
||||
req.open("POST", window.URLBase + url, true);
|
||||
if (response) {
|
||||
@ -68,16 +68,16 @@ export const _post = (url: string, data: Object, onreadystatechange: () => void,
|
||||
}
|
||||
req.setRequestHeader("Authorization", "Bearer " + window.token);
|
||||
req.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
|
||||
req.onreadystatechange = onreadystatechange;
|
||||
req.onreadystatechange = () => { if (req.status == 0) { window.notifications.connectionError(); } else { onreadystatechange(req); } };
|
||||
req.send(JSON.stringify(data));
|
||||
};
|
||||
|
||||
export function _delete(url: string, data: Object, onreadystatechange: () => void): void {
|
||||
export function _delete(url: string, data: Object, onreadystatechange: (req: XMLHttpRequest) => void): void {
|
||||
let req = new XMLHttpRequest();
|
||||
req.open("DELETE", window.URLBase + url, true);
|
||||
req.setRequestHeader("Authorization", "Bearer " + window.token);
|
||||
req.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
|
||||
req.onreadystatechange = onreadystatechange;
|
||||
req.onreadystatechange = () => { if (req.status == 0) { window.notifications.connectionError(); } else { onreadystatechange(req); } };
|
||||
req.send(JSON.stringify(data));
|
||||
}
|
||||
|
||||
@ -97,3 +97,32 @@ export function toClipboard (str: string) {
|
||||
document.getSelection().addRange(selected);
|
||||
}
|
||||
}
|
||||
|
||||
export class notificationBox implements NotificationBox {
|
||||
private _box: HTMLDivElement;
|
||||
timeout: number
|
||||
constructor(box: HTMLDivElement, timeout?: number) { this._box = box; this.timeout = timeout || 5; }
|
||||
|
||||
private _error = (message: string): HTMLElement => {
|
||||
const noti = document.createElement('aside');
|
||||
noti.classList.add("aside", "~critical", "!normal", "mt-half", "notification-error");
|
||||
noti.innerHTML = `<strong>Error:</strong> ${message}`;
|
||||
const closeButton = document.createElement('span') as HTMLSpanElement;
|
||||
closeButton.classList.add("button", "~critical", "!low", "ml-1");
|
||||
closeButton.innerHTML = `<i class="icon ri-close-line"></i>`;
|
||||
closeButton.onclick = () => { this._box.removeChild(noti); };
|
||||
noti.appendChild(closeButton);
|
||||
return noti;
|
||||
}
|
||||
|
||||
private _connectionError: boolean = false;
|
||||
connectionError = () => {
|
||||
const noti = this._error("Couldn't connect to jfa-go.");
|
||||
if (this._connectionError) {
|
||||
this._box.querySelector("aside.notification-error").remove();
|
||||
}
|
||||
this._box.appendChild(noti);
|
||||
this._connectionError = true;
|
||||
setTimeout(() => { this._box.removeChild(noti); this._connectionError = false; }, this.timeout*1000);
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,28 @@
|
||||
import { _get, _post, _delete, toClipboard } from "../modules/common.js";
|
||||
|
||||
export class DOMInvite implements Invite {
|
||||
|
||||
// TODO
|
||||
updateNotify = () => {}; // SetNotify
|
||||
delete = () => {}; // deleteInvite
|
||||
updateNotify = (checkbox: HTMLInputElement) => {
|
||||
let state: { [code: string]: { [type: string]: boolean } } = {};
|
||||
let revertChanges: () => void;
|
||||
if (checkbox.classList.contains("inv-notify-expiry")) {
|
||||
revertChanges = () => { this.notifyExpiry = !this.notifyExpiry };
|
||||
state[this.code] = { "notify-expiry": this.notifyExpiry };
|
||||
} else {
|
||||
revertChanges = () => { this.notifyCreation = !this.notifyCreation };
|
||||
state[this.code] = { "notify-creation": this.notifyCreation };
|
||||
}
|
||||
_post("/invites/notify", state, (req: XMLHttpRequest) => {
|
||||
if (req.readyState == 4 && !(req.status == 200 || req.status == 204)) {
|
||||
revertChanges();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
delete = () => { _delete("/invites", { "code": this.code }, (req: XMLHttpRequest) => {
|
||||
if (req.readyState == 4 && (req.status == 200 || req.status == 204)) {
|
||||
this.remove();
|
||||
}
|
||||
}); }
|
||||
|
||||
private _code: string = "None";
|
||||
get code(): string { return this._code; }
|
||||
@ -175,7 +193,7 @@ export class DOMInvite implements Invite {
|
||||
|
||||
this._header = document.createElement('div') as HTMLDivElement;
|
||||
this._container.appendChild(this._header);
|
||||
this._header.classList.add("card", "~neutral", "!normal", "inv-header", "flex-expand", "mt-half");
|
||||
this._header.classList.add("card", "~neutral", "!normal", "inv-header", "flex-expand", "mt-half", "overflow");
|
||||
|
||||
this._codeArea = document.createElement('div') as HTMLDivElement;
|
||||
this._header.appendChild(this._codeArea);
|
||||
@ -234,6 +252,11 @@ export class DOMInvite implements Invite {
|
||||
<span>On user creation</span>
|
||||
</label>
|
||||
`;
|
||||
const notifyExpiry = this._left.querySelector("input.inv-notify-expiry") as HTMLInputElement;
|
||||
notifyExpiry.onchange = () => { this._notifyExpiry = notifyExpiry.checked; this.updateNotify(notifyExpiry); };
|
||||
|
||||
const notifyCreation = this._left.querySelector("input.inv-notify-creation") as HTMLInputElement;
|
||||
notifyCreation.onchange = () => { this._notifyCreation = notifyCreation.checked; this.updateNotify(notifyCreation); };
|
||||
|
||||
this._middle = document.createElement('div') as HTMLDivElement;
|
||||
detailsInner.appendChild(this._middle);
|
||||
|
@ -23,6 +23,11 @@ declare interface Window {
|
||||
animationEvent: string;
|
||||
tabs: Tabs;
|
||||
invites: inviteList;
|
||||
notifications: NotificationBox;
|
||||
}
|
||||
|
||||
declare interface NotificationBox {
|
||||
connectionError: (timeout: number) => void;
|
||||
}
|
||||
|
||||
declare interface Tabs {
|
||||
|
Loading…
Reference in New Issue
Block a user