Files
jfa-go/ts/admin.ts
Harvey Tindall ee96bb9f1b tabs: add clearURL method, loading tabs clears previous qps
Navigatable has clearURL, which for Search clears "search" qp, and
invites clears "invite" qp. Tab interfaces optionally include
"contentObject: AsTab", and show/hide funcs are passed the contentObject
of the previously loaded tab if one is available, so that they can call
it's clearURL method. This means searches you typed for the accounts tab
won't pop up when switching to activity.
2026-01-05 10:39:20 +00:00

215 lines
7.6 KiB
TypeScript

import { ThemeManager } from "./modules/theme.js";
import { lang, LangFile, loadLangSelector } from "./modules/lang.js";
import { Modal } from "./modules/modal.js";
import { TabManager, isPageEventBindable, isNavigatable } from "./modules/tabs.js";
import { DOMInviteList, createInvite } from "./modules/invites.js";
import { accountsList } from "./modules/accounts.js";
import { settingsList } from "./modules/settings.js";
import { activityList } from "./modules/activity.js";
import { ProfileEditor, reloadProfileNames } from "./modules/profiles.js";
import { _get, _post, notificationBox, whichAnimationEvent, bindManualDropdowns } from "./modules/common.js";
import { Updater } from "./modules/update.js";
import { Login } from "./modules/login.js";
declare var window: GlobalWindow;
const theme = new ThemeManager(document.getElementById("button-theme"));
window.lang = new lang(window.langFile as LangFile);
loadLangSelector("admin");
// _get(`/lang/admin/${window.language}.json`, null, (req: XMLHttpRequest) => {
// if (req.readyState == 4 && req.status == 200) {
// langLoaded = true;
// window.lang = new lang(req.response as LangFile);
// }
// });
window.animationEvent = whichAnimationEvent();
window.token = "";
window.availableProfiles = window.availableProfiles || [];
// load modals
(() => {
window.modals = {} as Modals;
window.modals.login = new Modal(document.getElementById("modal-login"), true);
window.modals.addUser = new Modal(document.getElementById("modal-add-user"));
window.modals.about = new Modal(document.getElementById("modal-about"));
(document.getElementById("setting-about") as HTMLSpanElement).onclick = window.modals.about.toggle;
window.modals.modifyUser = new Modal(document.getElementById("modal-modify-user"));
window.modals.deleteUser = new Modal(document.getElementById("modal-delete-user"));
window.modals.settingsRestart = new Modal(document.getElementById("modal-restart"));
window.modals.settingsRefresh = new Modal(document.getElementById("modal-refresh"));
window.modals.ombiProfile = new Modal(document.getElementById("modal-ombi-profile"));
document.getElementById("form-ombi-defaults").addEventListener("submit", window.modals.ombiProfile.close);
window.modals.jellyseerrProfile = new Modal(document.getElementById("modal-jellyseerr-profile"));
document
.getElementById("form-jellyseerr-defaults")
.addEventListener("submit", window.modals.jellyseerrProfile.close);
window.modals.profiles = new Modal(document.getElementById("modal-user-profiles"));
window.modals.addProfile = new Modal(document.getElementById("modal-add-profile"));
window.modals.editProfile = new Modal(document.getElementById("modal-edit-profile"));
window.modals.announce = new Modal(document.getElementById("modal-announce"));
window.modals.editor = new Modal(document.getElementById("modal-editor"));
window.modals.customizeEmails = new Modal(document.getElementById("modal-customize"));
window.modals.extendExpiry = new Modal(document.getElementById("modal-extend-expiry"));
window.modals.updateInfo = new Modal(document.getElementById("modal-update"));
window.modals.matrix = new Modal(document.getElementById("modal-matrix"));
window.modals.logs = new Modal(document.getElementById("modal-logs"));
window.modals.tasks = new Modal(document.getElementById("modal-tasks"));
window.modals.backedUp = new Modal(document.getElementById("modal-backed-up"));
window.modals.backups = new Modal(document.getElementById("modal-backups"));
if (window.telegramEnabled) {
window.modals.telegram = new Modal(document.getElementById("modal-telegram"));
}
if (window.discordEnabled) {
window.modals.discord = new Modal(document.getElementById("modal-discord"));
}
if (window.linkResetEnabled) {
window.modals.sendPWR = new Modal(document.getElementById("modal-send-pwr"));
}
if (window.referralsEnabled) {
window.modals.enableReferralsUser = new Modal(document.getElementById("modal-enable-referrals-user"));
window.modals.enableReferralsProfile = new Modal(document.getElementById("modal-enable-referrals-profile"));
}
})();
// Make the navbar horizontally scrollable by dragging (with mouse)
// doesn't work incredibly well so disabled.
/*[...document.getElementsByClassName("horizontally-scrollable")].forEach((c: HTMLElement) => {
c.classList.add("cursor-pointer");
let down = false;
let startX: number, scrollLeft: number;
c.addEventListener("mousedown", (ev: MouseEvent) => {
console.log("down");
down = true;
c.classList.add("active");
startX = ev.pageX - c.offsetLeft;
scrollLeft = c.scrollLeft;
});
const leave = () => {
console.log("up");
down = false;
c.classList.remove("active");
};
c.addEventListener("mouseleave", leave);
c.addEventListener("mouseup", leave);
c.addEventListener("mousemove", (ev: MouseEvent) => {
if (!down) return;
const x = ev.pageX - c.offsetLeft;
const walk = x - startX;
c.scrollLeft = scrollLeft - walk;
});
});*/
// tab content objects will register with this independently, so initialise now
window.tabs = new TabManager();
var inviteCreator = new createInvite();
var accounts = new accountsList();
var activity = new activityList();
window.invites = new DOMInviteList();
var settings = new settingsList();
var profiles = new ProfileEditor();
window.notifications = new notificationBox(document.getElementById("notification-box") as HTMLDivElement, 5);
// only use a navigatable URL once
let navigated = false;
// load tabs
const tabs: { id: string; url: string; reloader: () => void; unloader?: () => void }[] = [];
[window.invites, accounts, activity, settings].forEach((p: AsTab) => {
let t: { id: string; url: string; reloader: (previous?: AsTab) => void; unloader?: () => void } = {
id: p.tabName,
url: p.pagePath,
reloader: (previous: AsTab) => {
if (isPageEventBindable(p)) p.bindPageEvents();
if (!navigated && isNavigatable(p) && p.isURL()) {
navigated = true;
p.navigate();
} else {
if (navigated && previous && isNavigatable(previous)) {
// Clear the query param, as it was likely for a different page
previous.clearURL();
}
p.reload(() => {});
}
},
};
if (isPageEventBindable(p)) t.unloader = p.unbindPageEvents;
tabs.push(t);
window.tabs.addTab(
t.id,
window.pages.Base + window.pages.Admin + "/" + t.url,
p,
null,
t.reloader,
t.unloader || null,
);
});
let matchedTab = false;
for (const tab of tabs) {
if (window.location.pathname.startsWith(window.pages.Base + window.pages.Current + "/" + tab.url)) {
window.tabs.switch(tab.url, true);
matchedTab = true;
}
}
// Default tab
if (!matchedTab) {
window.tabs.switch("", true);
}
const login = new Login(window.modals.login as Modal, "/", window.loginAppearance);
login.onLogin = () => {
console.log("Logged in.");
window.updater = new Updater();
// FIXME: Decide whether to autoload activity or not
reloadProfileNames();
setInterval(() => {
window.invites.reload();
accounts.reloadIfNotInScroll();
}, 30 * 1000);
// Triggers pre and post funcs, even though we're already on that page
window.tabs.switch(window.tabs.current);
};
bindManualDropdowns();
login.bindLogout(document.getElementById("logout-button"));
login.login("", "");