User Panel added API Docs link
This commit is contained in:
@@ -5,6 +5,7 @@
|
|||||||
- Generate OpenAPI spec and API HTML docs
|
- Generate OpenAPI spec and API HTML docs
|
||||||
- Fully auto‑generated OpenAPI spec (`openapi.json`) and interactive HTML docs (`api.html`) powered by Redoc.
|
- Fully auto‑generated OpenAPI spec (`openapi.json`) and interactive HTML docs (`api.html`) powered by Redoc.
|
||||||
- .gitattributes added to mark (`openapi.json`) & (`api.html`) as documentation.
|
- .gitattributes added to mark (`openapi.json`) & (`api.html`) as documentation.
|
||||||
|
- User Panel added API Docs link.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -166,105 +166,112 @@ export function openUserPanel() {
|
|||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
max-height: 350px !important;
|
max-height: 400px !important;
|
||||||
border: ${isDarkMode ? "1px solid #444" : "1px solid #ccc"};
|
border: ${isDarkMode ? "1px solid #444" : "1px solid #ccc"};
|
||||||
transform: none;
|
transform: none;
|
||||||
transition: none;
|
transition: none;
|
||||||
`;
|
`;
|
||||||
// Retrieve the language setting from local storage, default to English ("en")
|
|
||||||
const savedLanguage = localStorage.getItem("language") || "en";
|
const savedLanguage = localStorage.getItem("language") || "en";
|
||||||
|
|
||||||
if (!userPanelModal) {
|
if (!userPanelModal) {
|
||||||
userPanelModal = document.createElement("div");
|
userPanelModal = document.createElement("div");
|
||||||
userPanelModal.id = "userPanelModal";
|
userPanelModal.id = "userPanelModal";
|
||||||
userPanelModal.style.cssText = `
|
userPanelModal.style.cssText = `
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
width: 100vw;
|
width: 100vw;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
background-color: ${overlayBackground};
|
background-color: ${overlayBackground};
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
z-index: 3000;
|
z-index: 3000;
|
||||||
`;
|
`;
|
||||||
userPanelModal.innerHTML = `
|
userPanelModal.innerHTML = `
|
||||||
<div class="modal-content user-panel-content" style="${modalContentStyles}">
|
<div class="modal-content user-panel-content" style="${modalContentStyles}">
|
||||||
<span id="closeUserPanel" style="position: absolute; top: 10px; right: 10px; cursor: pointer; font-size: 24px;">×</span>
|
<span id="closeUserPanel" style="position: absolute; top: 10px; right: 10px; cursor: pointer; font-size: 24px;">×</span>
|
||||||
<h3>${t("user_panel")} (${username})</h3>
|
<h3>${t("user_panel")} (${username})</h3>
|
||||||
<button type="button" id="openChangePasswordModalBtn" class="btn btn-primary" style="margin-bottom: 15px;">${t("change_password")}</button>
|
|
||||||
<fieldset style="margin-bottom: 15px;">
|
<button type="button" id="openChangePasswordModalBtn" class="btn btn-primary" style="margin-bottom: 15px;">
|
||||||
<legend>${t("totp_settings")}</legend>
|
${t("change_password")}
|
||||||
<div class="form-group">
|
</button>
|
||||||
<label for="userTOTPEnabled">${t("enable_totp")}:</label>
|
|
||||||
<input type="checkbox" id="userTOTPEnabled" style="vertical-align: middle;" />
|
<fieldset style="margin-bottom: 15px;">
|
||||||
</div>
|
<legend>${t("totp_settings")}</legend>
|
||||||
</fieldset>
|
<div class="form-group">
|
||||||
<fieldset style="margin-bottom: 15px;">
|
<label for="userTOTPEnabled">${t("enable_totp")}:</label>
|
||||||
<legend>${t("language")}</legend>
|
<input type="checkbox" id="userTOTPEnabled" style="vertical-align: middle;" />
|
||||||
<div class="form-group">
|
</div>
|
||||||
<label for="languageSelector">${t("select_language")}:</label>
|
</fieldset>
|
||||||
<select id="languageSelector">
|
|
||||||
<option value="en">${t("english")}</option>
|
<fieldset style="margin-bottom: 15px;">
|
||||||
<option value="es">${t("spanish")}</option>
|
<legend>${t("language")}</legend>
|
||||||
<option value="fr">${t("french")}</option>
|
<div class="form-group">
|
||||||
<option value="de">${t("german")}</option>
|
<label for="languageSelector">${t("select_language")}:</label>
|
||||||
</select>
|
<select id="languageSelector">
|
||||||
</div>
|
<option value="en">${t("english")}</option>
|
||||||
</fieldset>
|
<option value="es">${t("spanish")}</option>
|
||||||
|
<option value="fr">${t("french")}</option>
|
||||||
|
<option value="de">${t("german")}</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<!-- New API Docs link -->
|
||||||
|
<div style="margin-bottom: 15px;">
|
||||||
|
<a href="api.html" target="_blank" class="btn btn-secondary">
|
||||||
|
${t("api_docs") || "API Docs"}
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
`;
|
</div>
|
||||||
|
`;
|
||||||
document.body.appendChild(userPanelModal);
|
document.body.appendChild(userPanelModal);
|
||||||
// Close button handler
|
|
||||||
|
// Handlers…
|
||||||
document.getElementById("closeUserPanel").addEventListener("click", () => {
|
document.getElementById("closeUserPanel").addEventListener("click", () => {
|
||||||
userPanelModal.style.display = "none";
|
userPanelModal.style.display = "none";
|
||||||
});
|
});
|
||||||
// Change Password button
|
|
||||||
document.getElementById("openChangePasswordModalBtn").addEventListener("click", () => {
|
document.getElementById("openChangePasswordModalBtn").addEventListener("click", () => {
|
||||||
document.getElementById("changePasswordModal").style.display = "block";
|
document.getElementById("changePasswordModal").style.display = "block";
|
||||||
});
|
});
|
||||||
// TOTP checkbox behavior
|
|
||||||
|
// TOTP checkbox
|
||||||
const totpCheckbox = document.getElementById("userTOTPEnabled");
|
const totpCheckbox = document.getElementById("userTOTPEnabled");
|
||||||
totpCheckbox.checked = localStorage.getItem("userTOTPEnabled") === "true";
|
totpCheckbox.checked = localStorage.getItem("userTOTPEnabled") === "true";
|
||||||
totpCheckbox.addEventListener("change", function () {
|
totpCheckbox.addEventListener("change", function () {
|
||||||
localStorage.setItem("userTOTPEnabled", this.checked ? "true" : "false");
|
localStorage.setItem("userTOTPEnabled", this.checked ? "true" : "false");
|
||||||
const enabled = this.checked;
|
|
||||||
fetch("api/updateUserPanel.php", {
|
fetch("api/updateUserPanel.php", {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
credentials: "include",
|
credentials: "include",
|
||||||
headers: {
|
headers: { "Content-Type": "application/json", "X-CSRF-Token": window.csrfToken },
|
||||||
"Content-Type": "application/json",
|
body: JSON.stringify({ totp_enabled: this.checked })
|
||||||
"X-CSRF-Token": window.csrfToken
|
|
||||||
},
|
|
||||||
body: JSON.stringify({ totp_enabled: enabled })
|
|
||||||
})
|
})
|
||||||
.then(r => r.json())
|
.then(r => r.json())
|
||||||
.then(result => {
|
.then(result => {
|
||||||
if (!result.success) {
|
if (!result.success) showToast(t("error_updating_totp_setting") + ": " + result.error);
|
||||||
showToast(t("error_updating_totp_setting") + ": " + result.error);
|
else if (this.checked) openTOTPModal();
|
||||||
} else if (enabled) {
|
|
||||||
openTOTPModal();
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
.catch(() => { showToast(t("error_updating_totp_setting")); });
|
.catch(() => showToast(t("error_updating_totp_setting")));
|
||||||
});
|
});
|
||||||
// Language dropdown initialization
|
|
||||||
|
// Language selector
|
||||||
const languageSelector = document.getElementById("languageSelector");
|
const languageSelector = document.getElementById("languageSelector");
|
||||||
languageSelector.value = savedLanguage;
|
languageSelector.value = savedLanguage;
|
||||||
languageSelector.addEventListener("change", function () {
|
languageSelector.addEventListener("change", function () {
|
||||||
const selectedLanguage = this.value;
|
localStorage.setItem("language", this.value);
|
||||||
localStorage.setItem("language", selectedLanguage);
|
setLocale(this.value);
|
||||||
setLocale(selectedLanguage);
|
|
||||||
applyTranslations();
|
applyTranslations();
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
// If the modal already exists, update its colors
|
// Update colors if already exists
|
||||||
userPanelModal.style.backgroundColor = overlayBackground;
|
userPanelModal.style.backgroundColor = overlayBackground;
|
||||||
const modalContent = userPanelModal.querySelector(".modal-content");
|
const modalContent = userPanelModal.querySelector(".modal-content");
|
||||||
modalContent.style.background = isDarkMode ? "#2c2c2c" : "#fff";
|
modalContent.style.background = isDarkMode ? "#2c2c2c" : "#fff";
|
||||||
modalContent.style.color = isDarkMode ? "#e0e0e0" : "#000";
|
modalContent.style.color = isDarkMode ? "#e0e0e0" : "#000";
|
||||||
modalContent.style.border = isDarkMode ? "1px solid #444" : "1px solid #ccc";
|
modalContent.style.border = isDarkMode ? "1px solid #444" : "1px solid #ccc";
|
||||||
}
|
}
|
||||||
|
|
||||||
userPanelModal.style.display = "flex";
|
userPanelModal.style.display = "flex";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -549,7 +556,7 @@ function showCustomConfirmModal(message) {
|
|||||||
noBtn.removeEventListener("click", onNo);
|
noBtn.removeEventListener("click", onNo);
|
||||||
modal.style.display = "none";
|
modal.style.display = "none";
|
||||||
}
|
}
|
||||||
|
|
||||||
yesBtn.addEventListener("click", onYes);
|
yesBtn.addEventListener("click", onYes);
|
||||||
noBtn.addEventListener("click", onNo);
|
noBtn.addEventListener("click", onNo);
|
||||||
});
|
});
|
||||||
@@ -688,7 +695,7 @@ export function openAdminPanel() {
|
|||||||
openUserPermissionsModal();
|
openUserPermissionsModal();
|
||||||
});
|
});
|
||||||
document.getElementById("saveAdminSettings").addEventListener("click", () => {
|
document.getElementById("saveAdminSettings").addEventListener("click", () => {
|
||||||
|
|
||||||
const disableFormLoginCheckbox = document.getElementById("disableFormLogin");
|
const disableFormLoginCheckbox = document.getElementById("disableFormLogin");
|
||||||
const disableBasicAuthCheckbox = document.getElementById("disableBasicAuth");
|
const disableBasicAuthCheckbox = document.getElementById("disableBasicAuth");
|
||||||
const disableOIDCLoginCheckbox = document.getElementById("disableOIDCLogin");
|
const disableOIDCLoginCheckbox = document.getElementById("disableOIDCLogin");
|
||||||
@@ -707,7 +714,7 @@ export function openAdminPanel() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const newHeaderTitle = document.getElementById("headerTitle").value.trim();
|
const newHeaderTitle = document.getElementById("headerTitle").value.trim();
|
||||||
|
|
||||||
const newOIDCConfig = {
|
const newOIDCConfig = {
|
||||||
providerUrl: document.getElementById("oidcProviderUrl").value.trim(),
|
providerUrl: document.getElementById("oidcProviderUrl").value.trim(),
|
||||||
clientId: document.getElementById("oidcClientId").value.trim(),
|
clientId: document.getElementById("oidcClientId").value.trim(),
|
||||||
@@ -739,7 +746,7 @@ export function openAdminPanel() {
|
|||||||
captureInitialAdminConfig();
|
captureInitialAdminConfig();
|
||||||
closeAdminPanel();
|
closeAdminPanel();
|
||||||
loadAdminConfigFunc();
|
loadAdminConfigFunc();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
showToast(t("error_updating_settings") + ": " + (response.error || t("unknown_error")));
|
showToast(t("error_updating_settings") + ": " + (response.error || t("unknown_error")));
|
||||||
}
|
}
|
||||||
@@ -764,7 +771,7 @@ export function openAdminPanel() {
|
|||||||
document.getElementById("disableFormLogin").checked = config.loginOptions.disableFormLogin === true;
|
document.getElementById("disableFormLogin").checked = config.loginOptions.disableFormLogin === true;
|
||||||
document.getElementById("disableBasicAuth").checked = config.loginOptions.disableBasicAuth === true;
|
document.getElementById("disableBasicAuth").checked = config.loginOptions.disableBasicAuth === true;
|
||||||
document.getElementById("disableOIDCLogin").checked = config.loginOptions.disableOIDCLogin === true;
|
document.getElementById("disableOIDCLogin").checked = config.loginOptions.disableOIDCLogin === true;
|
||||||
|
|
||||||
// Capture initial state after the modal loads.
|
// Capture initial state after the modal loads.
|
||||||
captureInitialAdminConfig();
|
captureInitialAdminConfig();
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -237,7 +237,8 @@ const translations = {
|
|||||||
"ok": "OK",
|
"ok": "OK",
|
||||||
"show": "Show",
|
"show": "Show",
|
||||||
"items_per_page": "items per page",
|
"items_per_page": "items per page",
|
||||||
"columns":"Columns"
|
"columns":"Columns",
|
||||||
|
"api_docs": "API Docs"
|
||||||
},
|
},
|
||||||
es: {
|
es: {
|
||||||
"please_log_in_to_continue": "Por favor, inicie sesión para continuar.",
|
"please_log_in_to_continue": "Por favor, inicie sesión para continuar.",
|
||||||
|
|||||||
Reference in New Issue
Block a user