mirror of
https://github.com/hrfee/jfa-go.git
synced 2024-12-22 17:10:10 +00:00
split into pages, hide email pages when disabled, add history navigation
This commit is contained in:
parent
8c871bc5fa
commit
c7f5aa2e2b
@ -16,23 +16,23 @@
|
||||
</div>
|
||||
</div>
|
||||
</span>
|
||||
<div class="page-container">
|
||||
<div class="page-container" id="page-container">
|
||||
<div class="card ~neutral !low mb-1">
|
||||
<div class="row">
|
||||
<img class="banner header" src="banner.svg" alt="jfa-go" />
|
||||
</div>
|
||||
<div class="row col flex center">
|
||||
<span class="heading">{{ .lang.StartPage.welcome }}</span>
|
||||
<span class="heading welcome">{{ .lang.StartPage.welcome }}</span>
|
||||
</div>
|
||||
<div class="row col flex center">
|
||||
<p class="content">{{ .lang.StartPage.pressStart }}</p>
|
||||
</div>
|
||||
<section class="section ~neutral banner footer flex-expand middle">
|
||||
<span class="support">{{ .lang.StartPage.httpsNotice }}</span>
|
||||
<span class="button ~urge !normal">{{ .lang.StartPage.start }}</span>
|
||||
<span class="button ~urge !normal next">{{ .lang.StartPage.start }}</span>
|
||||
</section>
|
||||
</div>
|
||||
<div class="card ~neutral !low mb-1">
|
||||
<div class="card ~neutral !low mb-1 unfocused">
|
||||
<span class="heading">{{ .lang.Language.title }}</span>
|
||||
<p class="content" id="language-description"></p>
|
||||
<label class="label">
|
||||
@ -61,7 +61,7 @@
|
||||
<span class="button ~urge !normal next">{{ .lang.Strings.next }}</span>
|
||||
</section>
|
||||
</div>
|
||||
<div class="card ~neutral !low mb-1">
|
||||
<div class="card ~neutral !low mb-1 unfocused">
|
||||
<span class="heading">{{ .lang.Login.title }}</span>
|
||||
<p class="content">{{ .lang.Login.description }}</p>
|
||||
<div class="pl-1">
|
||||
@ -95,7 +95,7 @@
|
||||
<span class="button ~urge !normal next">{{ .lang.Strings.next }}</span>
|
||||
</section>
|
||||
</div>
|
||||
<div class="card ~neutral !low mb-1">
|
||||
<div class="card ~neutral !low mb-1 unfocused">
|
||||
<span class="heading">{{ .lang.JellyfinEmby.title }}</span>
|
||||
<p class="content">{{ .lang.JellyfinEmby.description }}</p>
|
||||
<label class="label">
|
||||
@ -138,7 +138,7 @@
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
<div class="card ~neutral !low mb-1">
|
||||
<div class="card ~neutral !low mb-1 unfocused">
|
||||
<span class="heading">{{ .lang.Email.title }}</span>
|
||||
<p class="content" id="email-description"></p>
|
||||
<div class="row">
|
||||
@ -181,6 +181,7 @@
|
||||
</div>
|
||||
<div class="col">
|
||||
<div id="email-smtp">
|
||||
<p class="subheading">SMTP</p>
|
||||
<label class="label">
|
||||
<span>{{ .lang.Email.encryption }}</span>
|
||||
<div class="select ~neutral !normal mt-half mb-1">
|
||||
@ -208,6 +209,7 @@
|
||||
</label>
|
||||
</div>
|
||||
<div id="email-mailgun">
|
||||
<p class="subheading">Mailgun</p>
|
||||
<label class="label">
|
||||
<span class="mt-half">{{ .lang.Email.mailgunApiURL }}</span>
|
||||
<input type="url" class="input ~neutral !normal mt-half mb-1" id="mailgun-api_url" placeholder="https://api.eu.mailgun.net/v3/mail.jellyf.in/messages">
|
||||
@ -226,7 +228,7 @@
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
<div class="card ~neutral !low mb-1 related-to-email">
|
||||
<div class="card ~neutral !low mb-1 unfocused related-to-email">
|
||||
<span class="heading">{{ .lang.Notifications.title }}</span>
|
||||
<p class="content">{{ .lang.Notifications.description }}</p>
|
||||
<label class="row switch pb-1">
|
||||
@ -241,8 +243,14 @@
|
||||
<span class="mt-half">{{ .lang.Strings.emailSubject }}</span>
|
||||
<input type="text" class="input ~neutral !normal mt-half mb-1" id="welcome_email-subject" placeholder="{{ .emailLang.WelcomeEmail.title }}">
|
||||
</label>
|
||||
<section class="section ~neutral banner footer flex-expand middle">
|
||||
<span class="button ~neutral !normal back">{{ .lang.Strings.back }}</span>
|
||||
<div>
|
||||
<span class="button ~urge !normal next">{{ .lang.Strings.next }}</span>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
<div class="card ~neutral !low mb-1 related-to-email">
|
||||
<div class="card ~neutral !low mb-1 unfocused related-to-email">
|
||||
<span class="heading">{{ .lang.InviteEmails.title }}</span>
|
||||
<p class="content">{{ .lang.InviteEmails.description }}</p>
|
||||
<label class="row switch pb-1">
|
||||
@ -263,7 +271,7 @@
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
<div class="card ~neutral !low mb-1 related-to-email">
|
||||
<div class="card ~neutral !low mb-1 unfocused related-to-email">
|
||||
<span class="heading">{{ .lang.PasswordResets.title }}</span>
|
||||
<p class="content">{{ .lang.PasswordResets.description }}</p>
|
||||
<label class="row switch pb-1">
|
||||
@ -285,7 +293,7 @@
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
<div class="card ~neutral !low mb-1">
|
||||
<div class="card ~neutral !low mb-1 unfocused">
|
||||
<span class="heading">{{ .lang.PasswordValidation.title }}</span>
|
||||
<p class="content">{{ .lang.PasswordValidation.description }}</p>
|
||||
<label class="row switch pb-1">
|
||||
@ -318,7 +326,7 @@
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
<div class="card ~neutral !low mb-1">
|
||||
<div class="card ~neutral !low mb-1 unfocused">
|
||||
<span class="heading">{{ .lang.HelpMessages.title }}</span>
|
||||
<p class="content">{{ .lang.HelpMessages.description }}</p>
|
||||
<label class="label">
|
||||
@ -348,7 +356,7 @@
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
<div class="card ~neutral !low mb-1">
|
||||
<div class="card ~neutral !low mb-1 unfocused">
|
||||
<div class="row col flex center">
|
||||
<span class="heading">{{ .lang.EndPage.finished }}</span>
|
||||
</div>
|
||||
@ -356,6 +364,7 @@
|
||||
<p class="content">{{ .lang.EndPage.restartMessage }}</p>
|
||||
</div>
|
||||
<div class="row col flex center">
|
||||
<span class="button ~neutral !normal back mr-1">{{ .lang.Strings.back }}</span>
|
||||
<span class="button ~urge !normal" id="restart">{{ .lang.Strings.submit }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
177
ts/setup.ts
177
ts/setup.ts
@ -19,6 +19,8 @@ class Input {
|
||||
private _el: HTMLInputElement;
|
||||
get value(): string { return ""+this._el.value; }
|
||||
set value(v: string) { this._el.value = v; }
|
||||
// Nothing depends on input, but we add an empty broadcast function so we can just loop over all settings to fix dependents on start.
|
||||
broadcast = () => {}
|
||||
constructor(el: HTMLElement, placeholder?: any, value?: any, depends?: string, dependsTrue?: boolean, section?: string) {
|
||||
this._el = el as HTMLInputElement;
|
||||
if (placeholder) { this._el.placeholder = placeholder; }
|
||||
@ -41,13 +43,21 @@ class Checkbox {
|
||||
private _el: HTMLInputElement;
|
||||
get value(): string { return this._el.checked ? "true" : "false"; }
|
||||
set value(v: string) { this._el.checked = (v == "true") ? true : false; }
|
||||
|
||||
private _section: string;
|
||||
private _setting: string;
|
||||
broadcast = () => {
|
||||
if (this._section && this._setting) {
|
||||
const ev = new CustomEvent(`settings-${this._section}-${this._setting}`, { "detail": this._el.checked })
|
||||
document.dispatchEvent(ev);
|
||||
}
|
||||
}
|
||||
constructor(el: HTMLElement, depends?: string, dependsTrue?: boolean, section?: string, setting?: string) {
|
||||
this._el = el as HTMLInputElement;
|
||||
if (section && setting) {
|
||||
this._el.onchange = () => {
|
||||
const ev = new CustomEvent(`settings-${section}-${setting}`, { "detail": this._el.checked })
|
||||
document.dispatchEvent(ev);
|
||||
};
|
||||
this._section = section;
|
||||
this._setting = setting;
|
||||
this._el.onchange = this.broadcast;
|
||||
}
|
||||
if (depends) {
|
||||
document.addEventListener(`settings-${section}-${depends}`, (event: boolEvent) => {
|
||||
@ -71,15 +81,22 @@ class BoolRadios {
|
||||
this._els[0].checked = bool;
|
||||
this._els[1].checked = !bool;
|
||||
}
|
||||
|
||||
private _section: string;
|
||||
private _setting: string;
|
||||
broadcast = () => {
|
||||
if (this._section && this._setting) {
|
||||
const ev = new CustomEvent(`settings-${this._section}-${this._setting}`, { "detail": this._els[0].checked })
|
||||
document.dispatchEvent(ev);
|
||||
}
|
||||
}
|
||||
constructor(name: string, depends?: string, dependsTrue?: boolean, section?: string, setting?: string) {
|
||||
this._els = document.getElementsByName(name) as NodeListOf<HTMLInputElement>;
|
||||
if (section && setting) {
|
||||
const onchange = () => {
|
||||
const ev = new CustomEvent(`settings-${section}-${setting}`, { "detail": this._els[0].checked })
|
||||
document.dispatchEvent(ev);
|
||||
};
|
||||
this._els[0].onchange = onchange;
|
||||
this._els[1].onchange = onchange;
|
||||
this._section = section;
|
||||
this._setting = setting;
|
||||
this._els[0].onchange = this.broadcast;
|
||||
this._els[1].onchange = this.broadcast;
|
||||
}
|
||||
if (depends) {
|
||||
document.addEventListener(`settings-${section}-${depends}`, (event: boolEvent) => {
|
||||
@ -103,25 +120,25 @@ class BoolRadios {
|
||||
}
|
||||
}
|
||||
|
||||
class Radios {
|
||||
private _el: HTMLInputElement;
|
||||
get value(): string { return this._el.value; }
|
||||
set value(v: string) { this._el.value = v; }
|
||||
constructor(name: string, depends?: string, dependsTrue?: boolean, section?: string) {
|
||||
this._el = document.getElementsByName(name)[0] as HTMLInputElement;
|
||||
if (depends) {
|
||||
document.addEventListener(`settings-${section}-${depends}`, (event: boolEvent) => {
|
||||
let el = this._el as HTMLElement;
|
||||
if (el.parentElement.tagName == "LABEL") { el = el.parentElement; }
|
||||
if (event.detail !== dependsTrue) {
|
||||
el.classList.add("unfocused");
|
||||
} else {
|
||||
el.classList.remove("unfocused");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
// class Radios {
|
||||
// private _el: HTMLInputElement;
|
||||
// get value(): string { return this._el.value; }
|
||||
// set value(v: string) { this._el.value = v; }
|
||||
// constructor(name: string, depends?: string, dependsTrue?: boolean, section?: string) {
|
||||
// this._el = document.getElementsByName(name)[0] as HTMLInputElement;
|
||||
// if (depends) {
|
||||
// document.addEventListener(`settings-${section}-${depends}`, (event: boolEvent) => {
|
||||
// let el = this._el as HTMLElement;
|
||||
// if (el.parentElement.tagName == "LABEL") { el = el.parentElement; }
|
||||
// if (event.detail !== dependsTrue) {
|
||||
// el.classList.add("unfocused");
|
||||
// } else {
|
||||
// el.classList.remove("unfocused");
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
class Select {
|
||||
private _el: HTMLSelectElement;
|
||||
@ -136,13 +153,21 @@ class Select {
|
||||
set onchange(f: () => void) {
|
||||
this._el.addEventListener("change", f);
|
||||
}
|
||||
|
||||
private _section: string;
|
||||
private _setting: string;
|
||||
broadcast = () => {
|
||||
if (this._section && this._setting) {
|
||||
const ev = new CustomEvent(`settings-${this._section}-${this._setting}`, { "detail": this.value ? true : false })
|
||||
document.dispatchEvent(ev);
|
||||
}
|
||||
}
|
||||
constructor(el: HTMLElement, depends?: string, dependsTrue?: boolean, section?: string, setting?: string) {
|
||||
this._el = el as HTMLSelectElement;
|
||||
if (section && setting) {
|
||||
this._el.addEventListener("change", () => {
|
||||
const ev = new CustomEvent(`settings-${section}-${setting}`, { "detail": this.value ? true : false })
|
||||
document.dispatchEvent(ev);
|
||||
});
|
||||
this._section = section;
|
||||
this._setting = setting;
|
||||
this._el.addEventListener("change", this.broadcast);
|
||||
}
|
||||
if (depends) {
|
||||
document.addEventListener(`settings-${section}-${depends}`, (event: boolEvent) => {
|
||||
@ -246,7 +271,7 @@ const settings = {
|
||||
};
|
||||
|
||||
const relatedToEmail = Array.from(document.getElementsByClassName("related-to-email"));
|
||||
settings["email"]["method"].onchange = () => {
|
||||
const emailMethodChange = () => {
|
||||
const val = settings["email"]["method"].value;
|
||||
const smtp = document.getElementById("email-smtp");
|
||||
const mailgun = document.getElementById("email-mailgun");
|
||||
@ -254,21 +279,99 @@ settings["email"]["method"].onchange = () => {
|
||||
smtp.classList.remove("unfocused");
|
||||
mailgun.classList.add("unfocused");
|
||||
for (let el of relatedToEmail) {
|
||||
el.classList.remove("unfocused");
|
||||
el.classList.remove("hidden");
|
||||
}
|
||||
} else if (val == "mailgun") {
|
||||
mailgun.classList.remove("unfocused");
|
||||
smtp.classList.add("unfocused");
|
||||
for (let el of relatedToEmail) {
|
||||
el.classList.remove("unfocused");
|
||||
el.classList.remove("hidden");
|
||||
}
|
||||
} else {
|
||||
mailgun.classList.add("unfocused");
|
||||
smtp.classList.add("unfocused");
|
||||
for (let el of relatedToEmail) {
|
||||
el.classList.add("unfocused");
|
||||
el.classList.add("hidden");
|
||||
}
|
||||
}
|
||||
};
|
||||
settings["email"]["method"].onchange = emailMethodChange;
|
||||
emailMethodChange();
|
||||
|
||||
(window as any).settings = settings;
|
||||
|
||||
for (let section in settings) {
|
||||
for (let setting in settings[section]) {
|
||||
settings[section][setting].broadcast();
|
||||
}
|
||||
}
|
||||
|
||||
const pageNames: string[][] = [];
|
||||
|
||||
window.history.replaceState("welcome", "Setup - jfa-go");
|
||||
|
||||
const changePage = (title: string, pageTitle: string) => {
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
const lang = urlParams.get("lang");
|
||||
let page = "/#" + title;
|
||||
if (lang) { page += "?lang=" + lang; }
|
||||
window.history.pushState(title || "welcome", pageTitle, page);
|
||||
};
|
||||
const cards = Array.from(document.getElementById("page-container").getElementsByClassName("card")) as Array<HTMLDivElement>;
|
||||
(window as any).cards = cards;
|
||||
window.onpopstate = (event: PopStateEvent) => {
|
||||
if (event.state === "welcome") {
|
||||
cards[0].classList.remove("unfocused");
|
||||
for (let i = 1; i < cards.length; i++) { cards[i].classList.add("unfocused"); }
|
||||
return;
|
||||
}
|
||||
for (let i = 0; i < cards.length; i++) {
|
||||
if (event.state === pageNames[i][0]) {
|
||||
cards[i].classList.remove("unfocused");
|
||||
} else {
|
||||
cards[i].classList.add("unfocused");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
(() => {
|
||||
for (let i = 0; i < cards.length; i++) {
|
||||
const card = cards[i];
|
||||
const back = card.getElementsByClassName("back")[0] as HTMLSpanElement;
|
||||
const next = card.getElementsByClassName("next")[0] as HTMLSpanElement;
|
||||
console.log(cards[i]);
|
||||
const titleEl = cards[i].querySelector("span.heading") as HTMLElement;
|
||||
let title = titleEl.textContent.replace("/", "_").replace(" ", "-");
|
||||
if (titleEl.classList.contains("welcome")) {
|
||||
title = "";
|
||||
}
|
||||
let pageTitle = titleEl.textContent + " - jfa-go";
|
||||
pageNames.push([title, pageTitle]);
|
||||
if (back) { back.addEventListener("click", () => {
|
||||
let found = false;
|
||||
for (let ind = cards.length - 1; ind >= 0; ind--) {
|
||||
cards[ind].classList.add("unfocused");
|
||||
if (ind < i && !(cards[ind].classList.contains("hidden")) && !found) {
|
||||
cards[ind].classList.remove("unfocused");
|
||||
changePage(pageNames[ind][0], pageNames[ind][1]);
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
window.scrollTo(0, 0);
|
||||
}); }
|
||||
if (next) { next.addEventListener("click", () => {
|
||||
let found = false;
|
||||
for (let ind = 0; ind < cards.length; ind++) {
|
||||
cards[ind].classList.add("unfocused");
|
||||
if (ind > i && !(cards[ind].classList.contains("hidden")) && !found) {
|
||||
cards[ind].classList.remove("unfocused");
|
||||
changePage(pageNames[ind][0], pageNames[ind][1]);
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
window.scrollTo(0, 0);
|
||||
}); }
|
||||
}
|
||||
})()
|
||||
|
||||
loadLangSelector("setup");
|
||||
|
Loading…
Reference in New Issue
Block a user