settings: add loader, improve css a bit

Loader appears on about/user profiles area. These two are now shown next
to each other.
on small screens, the sidebar list of sections is displayed without a
card around it, and the top left/right corner buttons on all pages are
correctly aligned with the content.
pull/297/head
Harvey Tindall 4 months ago
parent ce6a5772b1
commit b40211a6e0
No known key found for this signature in database
GPG Key ID: BBC65952848FB1A2

@ -66,14 +66,14 @@ html:not(.dark) .card.\@low:not(.\~neutral):not(.\~positive):not(.\~urge):not(.\
margin: 5% 20% 5% 20%;
}
@media (max-width: 1100px) {
@media (max-width: 1024px) {
.page-container {
margin: 2%;
margin-top: 5rem;
}
}
@media screen and (max-width: 1000px) {
@media screen and (max-width: 1024px) {
:root {
font-size: 0.9rem;
}

@ -535,7 +535,7 @@
</form>
</div>
<div id="notification-box"></div>
<div class="top-4 left-4 absolute flex flex-row gap-2">
<div class="top-[2%] left-[2%] lg:top-4 lg:left-4 absolute flex flex-row gap-2">
<span class="dropdown z-[11]" tabindex="0" id="lang-dropdown">
<span class="button ~urge dropdown-button">
<i class="ri-global-line"></i>
@ -558,7 +558,7 @@
<span class="button ~warning" alt="{{ .strings.theme }}" id="button-theme"><i class="ri-sun-line"></i></span>
</div>
{{ if .userPageEnabled }}
<div class="top-4 right-4 absolute">
<div class="top-[2%] lg:top-4 right-[2%] lg:right-4 absolute">
<a class="button ~info" href="{{ .urlBase }}/my/account"><i class="ri-account-circle-fill mr-2"></i>{{ .strings.myAccount }}</a>
</div>
{{ end }}
@ -895,7 +895,7 @@
</div>
</div>
<div id="tab-settings" class="unfocused">
<div class="card @low dark:~d_neutral settings overflow">
<div class="card @low dark:~d_neutral settings overflow flex flex-col gap-2">
<div class="flex flex-col md:flex-row align-middle gap-2">
<div class="flex flex-row align-middle justify-between md:justify-normal">
<span class="heading">{{ .strings.settings }}</span>
@ -912,16 +912,18 @@
</div>
</div>
<div class="flex flex-col md:flex-row gap-3">
<div class="card @low dark:~d_neutral col" id="settings-sidebar">
<div class="md:card @low dark:~d_neutral flex md:flex flex-col gap-2 flex-1" id="settings-sidebar">
<div class="flex flex-row justify-between">
<input type="search" class="field ~neutral @low input settings-section-button justify-between mb-2" id="settings-search" placeholder="{{ .strings.search }}">
<button class="button ~neutral @low center -ml-10 rounded-s-none mb-2 settings-search-clear" aria-label="{{ .strings.clearSearch }}" text="{{ .strings.clearSearch }}"><i class="ri-close-line"></i></button>
<input type="search" class="field ~neutral @low input settings-section-button justify-between" id="settings-search" placeholder="{{ .strings.search }}">
<button class="button ~neutral @low center -ml-10 rounded-s-none settings-search-clear" aria-label="{{ .strings.clearSearch }}" text="{{ .strings.clearSearch }}"><i class="ri-close-line"></i></button>
</div>
<aside class="aside sm ~urge dark:~d_info @low" id="settings-message">Note: <span class="badge ~critical">*</span> indicates a required field, <span class="badge ~info dark:~d_warning">R</span> indicates changes require a restart.</aside>
<div id="settings-loader" class="flex flex-row gap-2">
<span class="button ~neutral @low settings-section-button justify-center grow" id="setting-about"><span class="flex">{{ .strings.aboutProgram }} <i class="ri-information-line ml-2"></i></span></span>
<span class="button ~neutral @low settings-section-button justify-center grow" id="setting-profiles"><span class="flex">{{ .strings.userProfiles }} <i class="ri-user-line ml-2"></i></span></span>
</div>
<aside class="aside sm ~urge dark:~d_info mb-2 @low" id="settings-message">Note: <span class="badge ~critical">*</span> indicates a required field, <span class="badge ~info dark:~d_warning">R</span> indicates changes require a restart.</aside>
<span class="button ~neutral @low settings-section-button justify-between mb-2" id="setting-about"><span class="flex">{{ .strings.aboutProgram }} <i class="ri-information-line ml-2"></i></span></span>
<span class="button ~neutral @low settings-section-button justify-between mb-2" id="setting-profiles"><span class="flex">{{ .strings.userProfiles }} <i class="ri-user-line ml-2"></i></span></span>
</div>
<div class="card ~neutral @low col overflow" id="settings-panel">
<div class="card ~neutral @low overflow flex-1" id="settings-panel">
<div class="settings-section unfocused h-[100%]" id="settings-not-found">
<div class="flex flex-col h-[100%] justify-center items-center">
<span class="text-2xl font-medium italic mb-2">{{ .strings.noResultsFound }}</span>

@ -35,7 +35,7 @@
</div>
</div>
{{ template "account-linking.html" . }}
<div class="top-4 left-4 absolute">
<div class="top-[2%] lg:top-4 left-[2%] lg:left-4 absolute">
<span class="dropdown" tabindex="0" id="lang-dropdown">
<span class="button ~urge dropdown-button">
<i class="ri-global-line"></i>

@ -7,7 +7,7 @@
</head>
<body class="max-w-full overflow-x-hidden section">
<div id="notification-box"></div>
<div class="top-4 left-4 absolute">
<div class="top-[2%] lg:top-4 left-[2%] lg:left-4 absolute">
<span class="dropdown" tabindex="0" id="lang-dropdown">
<span class="button ~urge dropdown-button">
<i class="ri-global-line"></i>

@ -79,7 +79,7 @@
{{ template "login-modal.html" . }}
{{ template "account-linking.html" . }}
<div id="notification-box"></div>
<div class="top-4 left-4 absolute">
<div class="top-[2%] lg:top-4 left-[2%] lg:left-4 absolute">
<span class="dropdown" tabindex="0" id="lang-dropdown">
<span class="button ~urge dropdown-button">
<i class="ri-global-line"></i>
@ -102,7 +102,7 @@
<span class="button ~warning" alt="{{ .strings.theme }}" id="button-theme"><i class="ri-sun-line"></i></span>
<span class="button ~critical @low mb-4 unfocused" id="logout-button">{{ .strings.logout }}</span>
</div>
<div class="top-4 right-4 absolute">
<div class="top-[2%] lg:top-4 right-[2%] lg:right-4 absolute">
<a class="button ~info unfocused" href="/" id="admin-back-button"><i class="ri-arrow-left-fill mr-2"></i>{{ .strings.admin }}</a>
</div>
<div class="page-container unfocused">

@ -627,6 +627,8 @@ export class settingsList {
private _saveNoRestart = document.getElementById("settings-apply-no-restart") as HTMLSpanElement;
private _saveRestart = document.getElementById("settings-apply-restart") as HTMLSpanElement;
private _loader = document.getElementById("settings-loader") as HTMLDivElement;
private _panel = document.getElementById("settings-panel") as HTMLDivElement;
private _sidebar = document.getElementById("settings-sidebar") as HTMLDivElement;
private _visibleSection: string;
@ -650,7 +652,7 @@ export class settingsList {
this._sections[name] = section;
this._panel.appendChild(this._sections[name].asElement());
const button = document.createElement("span") as HTMLSpanElement;
button.classList.add("button", "~neutral", "@low", "settings-section-button", "justify-between", "mb-2");
button.classList.add("button", "~neutral", "@low", "settings-section-button", "justify-between");
button.textContent = s.meta.name;
if (subButton) { button.appendChild(subButton); }
button.onclick = () => { this._showPanel(name); };
@ -905,63 +907,73 @@ export class settingsList {
window.modals.matrix.show();
}
reload = () => _get("/config", null, (req: XMLHttpRequest) => {
if (req.readyState == 4) {
if (req.status != 200) {
window.notifications.customError("settingsLoadError", window.lang.notif("errorLoadSettings"));
return;
}
this._settings = req.response as Settings;
for (let name of this._settings.order) {
if (name in this._sections) {
this._sections[name].update(this._settings.sections[name]);
} else {
if (name == "messages" || name == "user_page") {
const editButton = document.createElement("div");
editButton.classList.add("tooltip", "left");
editButton.innerHTML = `
<span class="button ~neutral @low">
<i class="icon ri-edit-line"></i>
</span>
<span class="content sm">
${window.lang.get("strings", "customizeMessages")}
</span>
`;
(editButton.querySelector("span.button") as HTMLSpanElement).onclick = () => {
this._messageEditor.showList(name == "messages" ? "email" : "user");
};
this.addSection(name, this._settings.sections[name], editButton);
} else if (name == "updates") {
const icon = document.createElement("span") as HTMLSpanElement;
if (window.updater.updateAvailable) {
icon.classList.add("button", "~urge");
icon.innerHTML = `<i class="ri-download-line" title="${window.lang.strings("update")}"></i>`;
icon.onclick = () => window.updater.checkForUpdates(window.modals.updateInfo.show);
}
this.addSection(name, this._settings.sections[name], icon);
} else if (name == "matrix" && !window.matrixEnabled) {
const addButton = document.createElement("div");
addButton.classList.add("tooltip", "left");
addButton.innerHTML = `
<span class="button ~neutral @low">+</span>
<span class="content sm">
${window.lang.strings("linkMatrix")}
</span>
`;
(addButton.querySelector("span.button") as HTMLSpanElement).onclick = this._addMatrix;
this.addSection(name, this._settings.sections[name], addButton);
reload = () => {
for (let i = 0; i < this._loader.children.length; i++) {
this._loader.children[i].classList.add("invisible");
}
addLoader(this._loader, false, true);
_get("/config", null, (req: XMLHttpRequest) => {
if (req.readyState == 4) {
if (req.status != 200) {
window.notifications.customError("settingsLoadError", window.lang.notif("errorLoadSettings"));
return;
}
this._settings = req.response as Settings;
for (let name of this._settings.order) {
if (name in this._sections) {
this._sections[name].update(this._settings.sections[name]);
} else {
this.addSection(name, this._settings.sections[name]);
if (name == "messages" || name == "user_page") {
const editButton = document.createElement("div");
editButton.classList.add("tooltip", "left");
editButton.innerHTML = `
<span class="button ~neutral @low">
<i class="icon ri-edit-line"></i>
</span>
<span class="content sm">
${window.lang.get("strings", "customizeMessages")}
</span>
`;
(editButton.querySelector("span.button") as HTMLSpanElement).onclick = () => {
this._messageEditor.showList(name == "messages" ? "email" : "user");
};
this.addSection(name, this._settings.sections[name], editButton);
} else if (name == "updates") {
const icon = document.createElement("span") as HTMLSpanElement;
if (window.updater.updateAvailable) {
icon.classList.add("button", "~urge");
icon.innerHTML = `<i class="ri-download-line" title="${window.lang.strings("update")}"></i>`;
icon.onclick = () => window.updater.checkForUpdates(window.modals.updateInfo.show);
}
this.addSection(name, this._settings.sections[name], icon);
} else if (name == "matrix" && !window.matrixEnabled) {
const addButton = document.createElement("div");
addButton.classList.add("tooltip", "left");
addButton.innerHTML = `
<span class="button ~neutral @low">+</span>
<span class="content sm">
${window.lang.strings("linkMatrix")}
</span>
`;
(addButton.querySelector("span.button") as HTMLSpanElement).onclick = this._addMatrix;
this.addSection(name, this._settings.sections[name], addButton);
} else {
this.addSection(name, this._settings.sections[name]);
}
}
}
removeLoader(this._loader);
for (let i = 0; i < this._loader.children.length; i++) {
this._loader.children[i].classList.remove("invisible");
}
this._showPanel(this._settings.order[0]);
document.dispatchEvent(new CustomEvent("settings-loaded"));
document.dispatchEvent(new CustomEvent("settings-advancedState", { detail: false }));
this._saveButton.classList.add("unfocused");
this._needsRestart = false;
}
this._showPanel(this._settings.order[0]);
document.dispatchEvent(new CustomEvent("settings-loaded"));
document.dispatchEvent(new CustomEvent("settings-advancedState", { detail: false }));
this._saveButton.classList.add("unfocused");
this._needsRestart = false;
}
})
})
};
// FIXME: Search "About" & "User profiles", pseudo-search "User profiles" for things like "Ombi", "Referrals", etc.
search = (query: string) => {

Loading…
Cancel
Save