mirror of
https://github.com/hrfee/jfa-go.git
synced 2024-12-28 20:10:11 +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;
|
resize: vertical;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.overflow {
|
||||||
|
overflow: visible;
|
||||||
|
}
|
||||||
|
|
||||||
select {
|
select {
|
||||||
color: inherit;
|
color: inherit;
|
||||||
border: 0 solid var(--color-neutral-300);
|
border: 0 solid var(--color-neutral-300);
|
||||||
@ -291,4 +295,8 @@ p.top {
|
|||||||
margin-top: 0px;
|
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">
|
<input type="submit" class="button ~urge !normal full-width center supra submit" value="Submit">
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</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="page-container max-w-screen-lg px-6 py-4 mx-auto lg:mx-auto md:py-8">
|
||||||
<div class="mb-1">
|
<div class="mb-1">
|
||||||
<header class="flex flex-wrap items-center justify-between">
|
<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 { Modal } from "./modules/modal.js";
|
||||||
import { Tabs } from "./modules/tabs.js";
|
import { Tabs } from "./modules/tabs.js";
|
||||||
import { inviteList } from "./modules/invites.js";
|
import { inviteList } from "./modules/invites.js";
|
||||||
|
import { notificationBox } from "./modules/common.js";
|
||||||
|
|
||||||
loadTheme();
|
loadTheme();
|
||||||
(document.getElementById('button-theme') as HTMLSpanElement).onclick = toggleTheme;
|
(document.getElementById('button-theme') as HTMLSpanElement).onclick = toggleTheme;
|
||||||
@ -14,21 +15,8 @@ const whichAnimationEvent = () => {
|
|||||||
return "webkitAnimationEnd";
|
return "webkitAnimationEnd";
|
||||||
}
|
}
|
||||||
window.animationEvent = whichAnimationEvent();
|
window.animationEvent = whichAnimationEvent();
|
||||||
/*const toggles: HTMLInputElement[] = Array.from(document.getElementsByClassName('toggle-details'));
|
|
||||||
for (let toggle of toggles) {
|
window.notifications = new notificationBox(document.getElementById('notification-box') as HTMLDivElement, 5);
|
||||||
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");
|
|
||||||
};
|
|
||||||
}*/
|
|
||||||
|
|
||||||
const checkInfUses = function (check: HTMLInputElement, mode = 2) {
|
const checkInfUses = function (check: HTMLInputElement, mode = 2) {
|
||||||
const uses = document.getElementById('inv-uses') as HTMLInputElement;
|
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.responseType = 'json';
|
||||||
req.setRequestHeader("Authorization", "Bearer " + window.token);
|
req.setRequestHeader("Authorization", "Bearer " + window.token);
|
||||||
req.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
|
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));
|
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();
|
let req = new XMLHttpRequest();
|
||||||
req.open("POST", window.URLBase + url, true);
|
req.open("POST", window.URLBase + url, true);
|
||||||
if (response) {
|
if (response) {
|
||||||
@ -68,16 +68,16 @@ export const _post = (url: string, data: Object, onreadystatechange: () => void,
|
|||||||
}
|
}
|
||||||
req.setRequestHeader("Authorization", "Bearer " + window.token);
|
req.setRequestHeader("Authorization", "Bearer " + window.token);
|
||||||
req.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
|
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));
|
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();
|
let req = new XMLHttpRequest();
|
||||||
req.open("DELETE", window.URLBase + url, true);
|
req.open("DELETE", window.URLBase + url, true);
|
||||||
req.setRequestHeader("Authorization", "Bearer " + window.token);
|
req.setRequestHeader("Authorization", "Bearer " + window.token);
|
||||||
req.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
|
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));
|
req.send(JSON.stringify(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,3 +97,32 @@ export function toClipboard (str: string) {
|
|||||||
document.getSelection().addRange(selected);
|
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";
|
import { _get, _post, _delete, toClipboard } from "../modules/common.js";
|
||||||
|
|
||||||
export class DOMInvite implements Invite {
|
export class DOMInvite implements Invite {
|
||||||
|
updateNotify = (checkbox: HTMLInputElement) => {
|
||||||
// TODO
|
let state: { [code: string]: { [type: string]: boolean } } = {};
|
||||||
updateNotify = () => {}; // SetNotify
|
let revertChanges: () => void;
|
||||||
delete = () => {}; // deleteInvite
|
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";
|
private _code: string = "None";
|
||||||
get code(): string { return this._code; }
|
get code(): string { return this._code; }
|
||||||
@ -175,7 +193,7 @@ export class DOMInvite implements Invite {
|
|||||||
|
|
||||||
this._header = document.createElement('div') as HTMLDivElement;
|
this._header = document.createElement('div') as HTMLDivElement;
|
||||||
this._container.appendChild(this._header);
|
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._codeArea = document.createElement('div') as HTMLDivElement;
|
||||||
this._header.appendChild(this._codeArea);
|
this._header.appendChild(this._codeArea);
|
||||||
@ -234,6 +252,11 @@ export class DOMInvite implements Invite {
|
|||||||
<span>On user creation</span>
|
<span>On user creation</span>
|
||||||
</label>
|
</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;
|
this._middle = document.createElement('div') as HTMLDivElement;
|
||||||
detailsInner.appendChild(this._middle);
|
detailsInner.appendChild(this._middle);
|
||||||
|
@ -23,6 +23,11 @@ declare interface Window {
|
|||||||
animationEvent: string;
|
animationEvent: string;
|
||||||
tabs: Tabs;
|
tabs: Tabs;
|
||||||
invites: inviteList;
|
invites: inviteList;
|
||||||
|
notifications: NotificationBox;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare interface NotificationBox {
|
||||||
|
connectionError: (timeout: number) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
declare interface Tabs {
|
declare interface Tabs {
|
||||||
|
Loading…
Reference in New Issue
Block a user