mirror of
https://github.com/dani-garcia/vaultwarden.git
synced 2024-11-21 20:35:28 +03:00
Update admin interface
- Updated the admin interface dependencies. - Replace bootstrap-native with bootstrap - Added auto theme with an option to switch to dark/light - Some small color changes - Added an dev only function to always load static files from disk
This commit is contained in:
parent
f579a4154c
commit
83d5432cbf
16 changed files with 9163 additions and 7737 deletions
|
@ -14,11 +14,17 @@ use crate::{
|
||||||
pub fn routes() -> Vec<Route> {
|
pub fn routes() -> Vec<Route> {
|
||||||
// If addding more routes here, consider also adding them to
|
// If addding more routes here, consider also adding them to
|
||||||
// crate::utils::LOGGED_ROUTES to make sure they appear in the log
|
// crate::utils::LOGGED_ROUTES to make sure they appear in the log
|
||||||
|
let mut routes = routes![attachments, alive, alive_head, static_files];
|
||||||
if CONFIG.web_vault_enabled() {
|
if CONFIG.web_vault_enabled() {
|
||||||
routes![web_index, web_index_head, app_id, web_files, attachments, alive, alive_head, static_files]
|
routes.append(&mut routes![web_index, web_index_head, app_id, web_files]);
|
||||||
} else {
|
|
||||||
routes![attachments, alive, alive_head, static_files]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
if CONFIG.reload_templates() {
|
||||||
|
routes.append(&mut routes![_static_files_dev]);
|
||||||
|
}
|
||||||
|
|
||||||
|
routes
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn catchers() -> Vec<Catcher> {
|
pub fn catchers() -> Vec<Catcher> {
|
||||||
|
@ -116,7 +122,30 @@ fn alive_head(_conn: DbConn) -> EmptyResult {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/vw_static/<filename>")]
|
// This endpoint/function is used during development and development only.
|
||||||
|
// It allows to easily develop the admin interface by always loading the files from disk instead from a slice of bytes
|
||||||
|
// This will only be active during a debug build and only when `RELOAD_TEMPLATES` is set to `true`
|
||||||
|
// NOTE: Do not forget to add any new files added to the `static_files` function below!
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
#[get("/vw_static/<filename>", rank = 1)]
|
||||||
|
pub async fn _static_files_dev(filename: PathBuf) -> Option<NamedFile> {
|
||||||
|
warn!("LOADING STATIC FILES FROM DISK");
|
||||||
|
let file = filename.to_str().unwrap_or_default();
|
||||||
|
let ext = filename.extension().unwrap_or_default();
|
||||||
|
|
||||||
|
let path = if ext == "png" || ext == "svg" {
|
||||||
|
tokio::fs::canonicalize(Path::new(file!()).parent().unwrap().join("../static/images/").join(file)).await
|
||||||
|
} else {
|
||||||
|
tokio::fs::canonicalize(Path::new(file!()).parent().unwrap().join("../static/scripts/").join(file)).await
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Ok(path) = path {
|
||||||
|
return NamedFile::open(path).await.ok();
|
||||||
|
};
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
#[get("/vw_static/<filename>", rank = 2)]
|
||||||
pub fn static_files(filename: &str) -> Result<(ContentType, &'static [u8]), Error> {
|
pub fn static_files(filename: &str) -> Result<(ContentType, &'static [u8]), Error> {
|
||||||
match filename {
|
match filename {
|
||||||
"404.png" => Ok((ContentType::PNG, include_bytes!("../static/images/404.png"))),
|
"404.png" => Ok((ContentType::PNG, include_bytes!("../static/images/404.png"))),
|
||||||
|
@ -138,12 +167,12 @@ pub fn static_files(filename: &str) -> Result<(ContentType, &'static [u8]), Erro
|
||||||
Ok((ContentType::JavaScript, include_bytes!("../static/scripts/admin_diagnostics.js")))
|
Ok((ContentType::JavaScript, include_bytes!("../static/scripts/admin_diagnostics.js")))
|
||||||
}
|
}
|
||||||
"bootstrap.css" => Ok((ContentType::CSS, include_bytes!("../static/scripts/bootstrap.css"))),
|
"bootstrap.css" => Ok((ContentType::CSS, include_bytes!("../static/scripts/bootstrap.css"))),
|
||||||
"bootstrap-native.js" => Ok((ContentType::JavaScript, include_bytes!("../static/scripts/bootstrap-native.js"))),
|
"bootstrap.bundle.js" => Ok((ContentType::JavaScript, include_bytes!("../static/scripts/bootstrap.bundle.js"))),
|
||||||
"jdenticon.js" => Ok((ContentType::JavaScript, include_bytes!("../static/scripts/jdenticon.js"))),
|
"jdenticon.js" => Ok((ContentType::JavaScript, include_bytes!("../static/scripts/jdenticon.js"))),
|
||||||
"datatables.js" => Ok((ContentType::JavaScript, include_bytes!("../static/scripts/datatables.js"))),
|
"datatables.js" => Ok((ContentType::JavaScript, include_bytes!("../static/scripts/datatables.js"))),
|
||||||
"datatables.css" => Ok((ContentType::CSS, include_bytes!("../static/scripts/datatables.css"))),
|
"datatables.css" => Ok((ContentType::CSS, include_bytes!("../static/scripts/datatables.css"))),
|
||||||
"jquery-3.6.4.slim.js" => {
|
"jquery-3.7.0.slim.js" => {
|
||||||
Ok((ContentType::JavaScript, include_bytes!("../static/scripts/jquery-3.6.4.slim.js")))
|
Ok((ContentType::JavaScript, include_bytes!("../static/scripts/jquery-3.7.0.slim.js")))
|
||||||
}
|
}
|
||||||
_ => err!(format!("Static file not found: {filename}")),
|
_ => err!(format!("Static file not found: {filename}")),
|
||||||
}
|
}
|
||||||
|
|
85
src/static/scripts/admin.js
vendored
85
src/static/scripts/admin.js
vendored
|
@ -37,36 +37,107 @@ function _post(url, successMsg, errMsg, body, reload_page = true) {
|
||||||
mode: "same-origin",
|
mode: "same-origin",
|
||||||
credentials: "same-origin",
|
credentials: "same-origin",
|
||||||
headers: { "Content-Type": "application/json" }
|
headers: { "Content-Type": "application/json" }
|
||||||
}).then( resp => {
|
}).then(resp => {
|
||||||
if (resp.ok) {
|
if (resp.ok) {
|
||||||
msg(successMsg, reload_page);
|
msg(successMsg, reload_page);
|
||||||
// Abuse the catch handler by setting error to false and continue
|
// Abuse the catch handler by setting error to false and continue
|
||||||
return Promise.reject({error: false});
|
return Promise.reject({ error: false });
|
||||||
}
|
}
|
||||||
respStatus = resp.status;
|
respStatus = resp.status;
|
||||||
respStatusText = resp.statusText;
|
respStatusText = resp.statusText;
|
||||||
return resp.text();
|
return resp.text();
|
||||||
}).then( respText => {
|
}).then(respText => {
|
||||||
try {
|
try {
|
||||||
const respJson = JSON.parse(respText);
|
const respJson = JSON.parse(respText);
|
||||||
if (respJson.ErrorModel && respJson.ErrorModel.Message) {
|
if (respJson.ErrorModel && respJson.ErrorModel.Message) {
|
||||||
return respJson.ErrorModel.Message;
|
return respJson.ErrorModel.Message;
|
||||||
} else {
|
} else {
|
||||||
return Promise.reject({body:`${respStatus} - ${respStatusText}\n\nUnknown error`, error: true});
|
return Promise.reject({ body: `${respStatus} - ${respStatusText}\n\nUnknown error`, error: true });
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return Promise.reject({body:`${respStatus} - ${respStatusText}\n\n[Catch] ${e}`, error: true});
|
return Promise.reject({ body: `${respStatus} - ${respStatusText}\n\n[Catch] ${e}`, error: true });
|
||||||
}
|
}
|
||||||
}).then( apiMsg => {
|
}).then(apiMsg => {
|
||||||
msg(`${errMsg}\n${apiMsg}`, reload_page);
|
msg(`${errMsg}\n${apiMsg}`, reload_page);
|
||||||
}).catch( e => {
|
}).catch(e => {
|
||||||
if (e.error === false) { return true; }
|
if (e.error === false) { return true; }
|
||||||
else { msg(`${errMsg}\n${e.body}`, reload_page); }
|
else { msg(`${errMsg}\n${e.body}`, reload_page); }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Bootstrap Theme Selector
|
||||||
|
const getStoredTheme = () => localStorage.getItem("theme");
|
||||||
|
const setStoredTheme = theme => localStorage.setItem("theme", theme);
|
||||||
|
|
||||||
|
const getPreferredTheme = () => {
|
||||||
|
const storedTheme = getStoredTheme();
|
||||||
|
if (storedTheme) {
|
||||||
|
return storedTheme;
|
||||||
|
}
|
||||||
|
|
||||||
|
return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
|
||||||
|
};
|
||||||
|
|
||||||
|
const setTheme = theme => {
|
||||||
|
if (theme === "auto" && window.matchMedia("(prefers-color-scheme: dark)").matches) {
|
||||||
|
document.documentElement.setAttribute("data-bs-theme", "dark");
|
||||||
|
} else {
|
||||||
|
document.documentElement.setAttribute("data-bs-theme", theme);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
setTheme(getPreferredTheme());
|
||||||
|
|
||||||
|
const showActiveTheme = (theme, focus = false) => {
|
||||||
|
const themeSwitcher = document.querySelector("#bd-theme");
|
||||||
|
|
||||||
|
if (!themeSwitcher) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const themeSwitcherText = document.querySelector("#bd-theme-text");
|
||||||
|
const activeThemeIcon = document.querySelector(".theme-icon-active use");
|
||||||
|
const btnToActive = document.querySelector(`[data-bs-theme-value="${theme}"]`);
|
||||||
|
const svgOfActiveBtn = btnToActive.querySelector("span use").innerText;
|
||||||
|
|
||||||
|
document.querySelectorAll("[data-bs-theme-value]").forEach(element => {
|
||||||
|
element.classList.remove("active");
|
||||||
|
element.setAttribute("aria-pressed", "false");
|
||||||
|
});
|
||||||
|
|
||||||
|
btnToActive.classList.add("active");
|
||||||
|
btnToActive.setAttribute("aria-pressed", "true");
|
||||||
|
activeThemeIcon.innerText = svgOfActiveBtn;
|
||||||
|
const themeSwitcherLabel = `${themeSwitcherText.textContent} (${btnToActive.dataset.bsThemeValue})`;
|
||||||
|
themeSwitcher.setAttribute("aria-label", themeSwitcherLabel);
|
||||||
|
|
||||||
|
if (focus) {
|
||||||
|
themeSwitcher.focus();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", () => {
|
||||||
|
const storedTheme = getStoredTheme();
|
||||||
|
if (storedTheme !== "light" && storedTheme !== "dark") {
|
||||||
|
setTheme(getPreferredTheme());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
// onLoad events
|
// onLoad events
|
||||||
document.addEventListener("DOMContentLoaded", (/*event*/) => {
|
document.addEventListener("DOMContentLoaded", (/*event*/) => {
|
||||||
|
showActiveTheme(getPreferredTheme());
|
||||||
|
|
||||||
|
document.querySelectorAll("[data-bs-theme-value]")
|
||||||
|
.forEach(toggle => {
|
||||||
|
toggle.addEventListener("click", () => {
|
||||||
|
const theme = toggle.getAttribute("data-bs-theme-value");
|
||||||
|
setStoredTheme(theme);
|
||||||
|
setTheme(theme);
|
||||||
|
showActiveTheme(theme, true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
// get current URL path and assign "active" class to the correct nav-item
|
// get current URL path and assign "active" class to the correct nav-item
|
||||||
const pathname = window.location.pathname;
|
const pathname = window.location.pathname;
|
||||||
if (pathname === "") return;
|
if (pathname === "") return;
|
||||||
|
|
4
src/static/scripts/admin_diagnostics.js
vendored
4
src/static/scripts/admin_diagnostics.js
vendored
|
@ -1,6 +1,6 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
/* eslint-env es2017, browser */
|
/* eslint-env es2017, browser */
|
||||||
/* global BASE_URL:readable, BSN:readable */
|
/* global BASE_URL:readable, bootstrap:readable */
|
||||||
|
|
||||||
var dnsCheck = false;
|
var dnsCheck = false;
|
||||||
var timeCheck = false;
|
var timeCheck = false;
|
||||||
|
@ -135,7 +135,7 @@ function copyToClipboard(event) {
|
||||||
document.execCommand("copy");
|
document.execCommand("copy");
|
||||||
tmpCopyEl.remove();
|
tmpCopyEl.remove();
|
||||||
|
|
||||||
new BSN.Toast("#toastClipboardCopy").show();
|
new bootstrap.Toast("#toastClipboardCopy").show();
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkTimeDrift(utcTimeA, utcTimeB, statusPrefix) {
|
function checkTimeDrift(utcTimeA, utcTimeB, statusPrefix) {
|
||||||
|
|
14
src/static/scripts/admin_users.js
vendored
14
src/static/scripts/admin_users.js
vendored
|
@ -141,19 +141,20 @@ function resendUserInvite (event) {
|
||||||
const ORG_TYPES = {
|
const ORG_TYPES = {
|
||||||
"0": {
|
"0": {
|
||||||
"name": "Owner",
|
"name": "Owner",
|
||||||
"color": "orange"
|
"bg": "orange",
|
||||||
|
"font": "black"
|
||||||
},
|
},
|
||||||
"1": {
|
"1": {
|
||||||
"name": "Admin",
|
"name": "Admin",
|
||||||
"color": "blueviolet"
|
"bg": "blueviolet"
|
||||||
},
|
},
|
||||||
"2": {
|
"2": {
|
||||||
"name": "User",
|
"name": "User",
|
||||||
"color": "blue"
|
"bg": "blue"
|
||||||
},
|
},
|
||||||
"3": {
|
"3": {
|
||||||
"name": "Manager",
|
"name": "Manager",
|
||||||
"color": "green"
|
"bg": "green"
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -227,7 +228,10 @@ function initUserTable() {
|
||||||
// Color all the org buttons per type
|
// Color all the org buttons per type
|
||||||
document.querySelectorAll("button[data-vw-org-type]").forEach(function(e) {
|
document.querySelectorAll("button[data-vw-org-type]").forEach(function(e) {
|
||||||
const orgType = ORG_TYPES[e.dataset.vwOrgType];
|
const orgType = ORG_TYPES[e.dataset.vwOrgType];
|
||||||
e.style.backgroundColor = orgType.color;
|
e.style.backgroundColor = orgType.bg;
|
||||||
|
if (orgType.font !== undefined) {
|
||||||
|
e.style.color = orgType.font;
|
||||||
|
}
|
||||||
e.title = orgType.name;
|
e.title = orgType.name;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
5991
src/static/scripts/bootstrap-native.js
vendored
5991
src/static/scripts/bootstrap-native.js
vendored
File diff suppressed because it is too large
Load diff
6313
src/static/scripts/bootstrap.bundle.js
vendored
Normal file
6313
src/static/scripts/bootstrap.bundle.js
vendored
Normal file
File diff suppressed because it is too large
Load diff
2379
src/static/scripts/bootstrap.css
vendored
2379
src/static/scripts/bootstrap.css
vendored
File diff suppressed because it is too large
Load diff
47
src/static/scripts/datatables.css
vendored
47
src/static/scripts/datatables.css
vendored
|
@ -4,10 +4,10 @@
|
||||||
*
|
*
|
||||||
* To rebuild or modify this file with the latest versions of the included
|
* To rebuild or modify this file with the latest versions of the included
|
||||||
* software please visit:
|
* software please visit:
|
||||||
* https://datatables.net/download/#bs5/dt-1.13.4
|
* https://datatables.net/download/#bs5/dt-1.13.6
|
||||||
*
|
*
|
||||||
* Included libraries:
|
* Included libraries:
|
||||||
* DataTables 1.13.4
|
* DataTables 1.13.6
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@charset "UTF-8";
|
@charset "UTF-8";
|
||||||
|
@ -15,6 +15,13 @@
|
||||||
--dt-row-selected: 13, 110, 253;
|
--dt-row-selected: 13, 110, 253;
|
||||||
--dt-row-selected-text: 255, 255, 255;
|
--dt-row-selected-text: 255, 255, 255;
|
||||||
--dt-row-selected-link: 9, 10, 11;
|
--dt-row-selected-link: 9, 10, 11;
|
||||||
|
--dt-row-stripe: 0, 0, 0;
|
||||||
|
--dt-row-hover: 0, 0, 0;
|
||||||
|
--dt-column-ordering: 0, 0, 0;
|
||||||
|
--dt-html-background: white;
|
||||||
|
}
|
||||||
|
:root.dark {
|
||||||
|
--dt-html-background: rgb(33, 37, 41);
|
||||||
}
|
}
|
||||||
|
|
||||||
table.dataTable td.dt-control {
|
table.dataTable td.dt-control {
|
||||||
|
@ -22,25 +29,19 @@ table.dataTable td.dt-control {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
table.dataTable td.dt-control:before {
|
table.dataTable td.dt-control:before {
|
||||||
height: 1em;
|
|
||||||
width: 1em;
|
|
||||||
margin-top: -9px;
|
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
color: white;
|
color: rgba(0, 0, 0, 0.5);
|
||||||
border: 0.15em solid white;
|
content: "►";
|
||||||
border-radius: 1em;
|
|
||||||
box-shadow: 0 0 0.2em #444;
|
|
||||||
box-sizing: content-box;
|
|
||||||
text-align: center;
|
|
||||||
text-indent: 0 !important;
|
|
||||||
font-family: "Courier New", Courier, monospace;
|
|
||||||
line-height: 1em;
|
|
||||||
content: "+";
|
|
||||||
background-color: #31b131;
|
|
||||||
}
|
}
|
||||||
table.dataTable tr.dt-hasChild td.dt-control:before {
|
table.dataTable tr.dt-hasChild td.dt-control:before {
|
||||||
content: "-";
|
content: "▼";
|
||||||
background-color: #d33333;
|
}
|
||||||
|
|
||||||
|
html.dark table.dataTable td.dt-control:before {
|
||||||
|
color: rgba(255, 255, 255, 0.5);
|
||||||
|
}
|
||||||
|
html.dark table.dataTable tr.dt-hasChild td.dt-control:before {
|
||||||
|
color: rgba(255, 255, 255, 0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
table.dataTable thead > tr > th.sorting, table.dataTable thead > tr > th.sorting_asc, table.dataTable thead > tr > th.sorting_desc, table.dataTable thead > tr > th.sorting_asc_disabled, table.dataTable thead > tr > th.sorting_desc_disabled,
|
table.dataTable thead > tr > th.sorting, table.dataTable thead > tr > th.sorting_asc, table.dataTable thead > tr > th.sorting_desc, table.dataTable thead > tr > th.sorting_asc_disabled, table.dataTable thead > tr > th.sorting_desc_disabled,
|
||||||
|
@ -303,14 +304,14 @@ table.dataTable > tbody > tr.selected a {
|
||||||
color: rgb(var(--dt-row-selected-link));
|
color: rgb(var(--dt-row-selected-link));
|
||||||
}
|
}
|
||||||
table.dataTable.table-striped > tbody > tr.odd > * {
|
table.dataTable.table-striped > tbody > tr.odd > * {
|
||||||
box-shadow: inset 0 0 0 9999px rgba(0, 0, 0, 0.05);
|
box-shadow: inset 0 0 0 9999px rgba(var(--dt-row-stripe), 0.05);
|
||||||
}
|
}
|
||||||
table.dataTable.table-striped > tbody > tr.odd.selected > * {
|
table.dataTable.table-striped > tbody > tr.odd.selected > * {
|
||||||
box-shadow: inset 0 0 0 9999px rgba(13, 110, 253, 0.95);
|
box-shadow: inset 0 0 0 9999px rgba(13, 110, 253, 0.95);
|
||||||
box-shadow: inset 0 0 0 9999px rgba(var(--dt-row-selected), 0.95);
|
box-shadow: inset 0 0 0 9999px rgba(var(--dt-row-selected), 0.95);
|
||||||
}
|
}
|
||||||
table.dataTable.table-hover > tbody > tr:hover > * {
|
table.dataTable.table-hover > tbody > tr:hover > * {
|
||||||
box-shadow: inset 0 0 0 9999px rgba(0, 0, 0, 0.075);
|
box-shadow: inset 0 0 0 9999px rgba(var(--dt-row-hover), 0.075);
|
||||||
}
|
}
|
||||||
table.dataTable.table-hover > tbody > tr.selected:hover > * {
|
table.dataTable.table-hover > tbody > tr.selected:hover > * {
|
||||||
box-shadow: inset 0 0 0 9999px rgba(13, 110, 253, 0.975);
|
box-shadow: inset 0 0 0 9999px rgba(13, 110, 253, 0.975);
|
||||||
|
@ -441,4 +442,10 @@ div.table-responsive > div.dataTables_wrapper > div.row > div[class^=col-]:last-
|
||||||
padding-right: 0;
|
padding-right: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:root[data-bs-theme=dark] {
|
||||||
|
--dt-row-hover: 255, 255, 255;
|
||||||
|
--dt-row-stripe: 255, 255, 255;
|
||||||
|
--dt-column-ordering: 255, 255, 255;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
93
src/static/scripts/datatables.js
vendored
93
src/static/scripts/datatables.js
vendored
|
@ -4,20 +4,20 @@
|
||||||
*
|
*
|
||||||
* To rebuild or modify this file with the latest versions of the included
|
* To rebuild or modify this file with the latest versions of the included
|
||||||
* software please visit:
|
* software please visit:
|
||||||
* https://datatables.net/download/#bs5/dt-1.13.4
|
* https://datatables.net/download/#bs5/dt-1.13.6
|
||||||
*
|
*
|
||||||
* Included libraries:
|
* Included libraries:
|
||||||
* DataTables 1.13.4
|
* DataTables 1.13.6
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*! DataTables 1.13.4
|
/*! DataTables 1.13.6
|
||||||
* ©2008-2023 SpryMedia Ltd - datatables.net/license
|
* ©2008-2023 SpryMedia Ltd - datatables.net/license
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @summary DataTables
|
* @summary DataTables
|
||||||
* @description Paginate, search and order HTML tables
|
* @description Paginate, search and order HTML tables
|
||||||
* @version 1.13.4
|
* @version 1.13.6
|
||||||
* @author SpryMedia Ltd
|
* @author SpryMedia Ltd
|
||||||
* @contact www.datatables.net
|
* @contact www.datatables.net
|
||||||
* @copyright SpryMedia Ltd.
|
* @copyright SpryMedia Ltd.
|
||||||
|
@ -50,7 +50,7 @@
|
||||||
// returns a factory function that expects the window object
|
// returns a factory function that expects the window object
|
||||||
var jq = require('jquery');
|
var jq = require('jquery');
|
||||||
|
|
||||||
if (typeof window !== 'undefined') {
|
if (typeof window === 'undefined') {
|
||||||
module.exports = function (root, $) {
|
module.exports = function (root, $) {
|
||||||
if ( ! root ) {
|
if ( ! root ) {
|
||||||
// CommonJS environments without a window global must pass a
|
// CommonJS environments without a window global must pass a
|
||||||
|
@ -1396,7 +1396,7 @@
|
||||||
|
|
||||||
|
|
||||||
var _isNumber = function ( d, decimalPoint, formatted ) {
|
var _isNumber = function ( d, decimalPoint, formatted ) {
|
||||||
let type = typeof d;
|
var type = typeof d;
|
||||||
var strType = type === 'string';
|
var strType = type === 'string';
|
||||||
|
|
||||||
if ( type === 'number' || type === 'bigint') {
|
if ( type === 'number' || type === 'bigint') {
|
||||||
|
@ -1530,7 +1530,9 @@
|
||||||
|
|
||||||
|
|
||||||
var _stripHtml = function ( d ) {
|
var _stripHtml = function ( d ) {
|
||||||
return d.replace( _re_html, '' );
|
return d
|
||||||
|
.replace( _re_html, '' ) // Complete tags
|
||||||
|
.replace(/<script/i, ''); // Safety for incomplete script tag
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -1904,7 +1906,10 @@
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( data === null || data[ a[i] ] === undefined ) {
|
if (data === null || data[ a[i] ] === null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
else if ( data === undefined || data[ a[i] ] === undefined ) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2351,6 +2356,12 @@
|
||||||
oCol.aDataSort = [ oOptions.iDataSort ];
|
oCol.aDataSort = [ oOptions.iDataSort ];
|
||||||
}
|
}
|
||||||
_fnMap( oCol, oOptions, "aDataSort" );
|
_fnMap( oCol, oOptions, "aDataSort" );
|
||||||
|
|
||||||
|
// Fall back to the aria-label attribute on the table header if no ariaTitle is
|
||||||
|
// provided.
|
||||||
|
if (! oCol.ariaTitle) {
|
||||||
|
oCol.ariaTitle = th.attr("aria-label");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Cache the data get and set functions for speed */
|
/* Cache the data get and set functions for speed */
|
||||||
|
@ -4075,11 +4086,16 @@
|
||||||
settings.iDraw++;
|
settings.iDraw++;
|
||||||
_fnProcessingDisplay( settings, true );
|
_fnProcessingDisplay( settings, true );
|
||||||
|
|
||||||
|
// Keep track of drawHold state to handle scrolling after the Ajax call
|
||||||
|
var drawHold = settings._drawHold;
|
||||||
|
|
||||||
_fnBuildAjax(
|
_fnBuildAjax(
|
||||||
settings,
|
settings,
|
||||||
_fnAjaxParameters( settings ),
|
_fnAjaxParameters( settings ),
|
||||||
function(json) {
|
function(json) {
|
||||||
|
settings._drawHold = drawHold;
|
||||||
_fnAjaxUpdateDraw( settings, json );
|
_fnAjaxUpdateDraw( settings, json );
|
||||||
|
settings._drawHold = false;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -4343,7 +4359,7 @@
|
||||||
_fnThrottle( searchFn, searchDelay ) :
|
_fnThrottle( searchFn, searchDelay ) :
|
||||||
searchFn
|
searchFn
|
||||||
)
|
)
|
||||||
.on( 'mouseup', function(e) {
|
.on( 'mouseup.DT', function(e) {
|
||||||
// Edge fix! Edge 17 does not trigger anything other than mouse events when clicking
|
// Edge fix! Edge 17 does not trigger anything other than mouse events when clicking
|
||||||
// on the clear icon (Edge bug 17584515). This is safe in other browsers as `searchFn`
|
// on the clear icon (Edge bug 17584515). This is safe in other browsers as `searchFn`
|
||||||
// checks the value to see if it has changed. In other browsers it won't have.
|
// checks the value to see if it has changed. In other browsers it won't have.
|
||||||
|
@ -4409,7 +4425,7 @@
|
||||||
if ( _fnDataSource( oSettings ) != 'ssp' )
|
if ( _fnDataSource( oSettings ) != 'ssp' )
|
||||||
{
|
{
|
||||||
/* Global filter */
|
/* Global filter */
|
||||||
_fnFilter( oSettings, oInput.sSearch, iForce, fnRegex(oInput), oInput.bSmart, oInput.bCaseInsensitive, oInput.return );
|
_fnFilter( oSettings, oInput.sSearch, iForce, fnRegex(oInput), oInput.bSmart, oInput.bCaseInsensitive );
|
||||||
fnSaveFilter( oInput );
|
fnSaveFilter( oInput );
|
||||||
|
|
||||||
/* Now do the individual column filter */
|
/* Now do the individual column filter */
|
||||||
|
@ -4578,11 +4594,15 @@
|
||||||
*
|
*
|
||||||
* ^(?=.*?\bone\b)(?=.*?\btwo three\b)(?=.*?\bfour\b).*$
|
* ^(?=.*?\bone\b)(?=.*?\btwo three\b)(?=.*?\bfour\b).*$
|
||||||
*/
|
*/
|
||||||
var a = $.map( search.match( /"[^"]+"|[^ ]+/g ) || [''], function ( word ) {
|
var a = $.map( search.match( /["\u201C][^"\u201D]+["\u201D]|[^ ]+/g ) || [''], function ( word ) {
|
||||||
if ( word.charAt(0) === '"' ) {
|
if ( word.charAt(0) === '"' ) {
|
||||||
var m = word.match( /^"(.*)"$/ );
|
var m = word.match( /^"(.*)"$/ );
|
||||||
word = m ? m[1] : word;
|
word = m ? m[1] : word;
|
||||||
}
|
}
|
||||||
|
else if ( word.charAt(0) === '\u201C' ) {
|
||||||
|
var m = word.match( /^\u201C(.*)\u201D$/ );
|
||||||
|
word = m ? m[1] : word;
|
||||||
|
}
|
||||||
|
|
||||||
return word.replace('"', '');
|
return word.replace('"', '');
|
||||||
} );
|
} );
|
||||||
|
@ -9386,7 +9406,8 @@
|
||||||
* Set the jQuery or window object to be used by DataTables
|
* Set the jQuery or window object to be used by DataTables
|
||||||
*
|
*
|
||||||
* @param {*} module Library / container object
|
* @param {*} module Library / container object
|
||||||
* @param {string} type Library or container type `lib` or `win`.
|
* @param {string} [type] Library or container type `lib`, `win` or `datetime`.
|
||||||
|
* If not provided, automatic detection is attempted.
|
||||||
*/
|
*/
|
||||||
DataTable.use = function (module, type) {
|
DataTable.use = function (module, type) {
|
||||||
if (type === 'lib' || module.fn) {
|
if (type === 'lib' || module.fn) {
|
||||||
|
@ -9396,6 +9417,9 @@
|
||||||
window = module;
|
window = module;
|
||||||
document = module.document;
|
document = module.document;
|
||||||
}
|
}
|
||||||
|
else if (type === 'datetime' || module.type === 'DateTime') {
|
||||||
|
DataTable.DateTime = module;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -9755,7 +9779,9 @@
|
||||||
resolved._;
|
resolved._;
|
||||||
}
|
}
|
||||||
|
|
||||||
return resolved.replace( '%d', plural ); // nb: plural might be undefined,
|
return typeof resolved === 'string'
|
||||||
|
? resolved.replace( '%d', plural ) // nb: plural might be undefined,
|
||||||
|
: resolved;
|
||||||
} );
|
} );
|
||||||
/**
|
/**
|
||||||
* Version string for plug-ins to check compatibility. Allowed format is
|
* Version string for plug-ins to check compatibility. Allowed format is
|
||||||
|
@ -9765,7 +9791,7 @@
|
||||||
* @type string
|
* @type string
|
||||||
* @default Version number
|
* @default Version number
|
||||||
*/
|
*/
|
||||||
DataTable.version = "1.13.4";
|
DataTable.version = "1.13.6";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Private data store, containing all of the settings objects that are
|
* Private data store, containing all of the settings objects that are
|
||||||
|
@ -14189,7 +14215,7 @@
|
||||||
*
|
*
|
||||||
* @type string
|
* @type string
|
||||||
*/
|
*/
|
||||||
build:"bs5/dt-1.13.4",
|
build:"bs5/dt-1.13.6",
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -14830,7 +14856,7 @@
|
||||||
var btnDisplay, btnClass;
|
var btnDisplay, btnClass;
|
||||||
|
|
||||||
var attach = function( container, buttons ) {
|
var attach = function( container, buttons ) {
|
||||||
var i, ien, node, button, tabIndex;
|
var i, ien, node, button;
|
||||||
var disabledClass = classes.sPageButtonDisabled;
|
var disabledClass = classes.sPageButtonDisabled;
|
||||||
var clickHandler = function ( e ) {
|
var clickHandler = function ( e ) {
|
||||||
_fnPageChange( settings, e.data.action, true );
|
_fnPageChange( settings, e.data.action, true );
|
||||||
|
@ -14845,9 +14871,10 @@
|
||||||
attach( inner, button );
|
attach( inner, button );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
var disabled = false;
|
||||||
|
|
||||||
btnDisplay = null;
|
btnDisplay = null;
|
||||||
btnClass = button;
|
btnClass = button;
|
||||||
tabIndex = settings.iTabIndex;
|
|
||||||
|
|
||||||
switch ( button ) {
|
switch ( button ) {
|
||||||
case 'ellipsis':
|
case 'ellipsis':
|
||||||
|
@ -14858,8 +14885,7 @@
|
||||||
btnDisplay = lang.sFirst;
|
btnDisplay = lang.sFirst;
|
||||||
|
|
||||||
if ( page === 0 ) {
|
if ( page === 0 ) {
|
||||||
tabIndex = -1;
|
disabled = true;
|
||||||
btnClass += ' ' + disabledClass;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -14867,8 +14893,7 @@
|
||||||
btnDisplay = lang.sPrevious;
|
btnDisplay = lang.sPrevious;
|
||||||
|
|
||||||
if ( page === 0 ) {
|
if ( page === 0 ) {
|
||||||
tabIndex = -1;
|
disabled = true;
|
||||||
btnClass += ' ' + disabledClass;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -14876,8 +14901,7 @@
|
||||||
btnDisplay = lang.sNext;
|
btnDisplay = lang.sNext;
|
||||||
|
|
||||||
if ( pages === 0 || page === pages-1 ) {
|
if ( pages === 0 || page === pages-1 ) {
|
||||||
tabIndex = -1;
|
disabled = true;
|
||||||
btnClass += ' ' + disabledClass;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -14885,8 +14909,7 @@
|
||||||
btnDisplay = lang.sLast;
|
btnDisplay = lang.sLast;
|
||||||
|
|
||||||
if ( pages === 0 || page === pages-1 ) {
|
if ( pages === 0 || page === pages-1 ) {
|
||||||
tabIndex = -1;
|
disabled = true;
|
||||||
btnClass += ' ' + disabledClass;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -14899,18 +14922,20 @@
|
||||||
|
|
||||||
if ( btnDisplay !== null ) {
|
if ( btnDisplay !== null ) {
|
||||||
var tag = settings.oInit.pagingTag || 'a';
|
var tag = settings.oInit.pagingTag || 'a';
|
||||||
var disabled = btnClass.indexOf(disabledClass) !== -1;
|
|
||||||
|
if (disabled) {
|
||||||
|
btnClass += ' ' + disabledClass;
|
||||||
|
}
|
||||||
|
|
||||||
node = $('<'+tag+'>', {
|
node = $('<'+tag+'>', {
|
||||||
'class': classes.sPageButton+' '+btnClass,
|
'class': classes.sPageButton+' '+btnClass,
|
||||||
'aria-controls': settings.sTableId,
|
'aria-controls': settings.sTableId,
|
||||||
'aria-disabled': disabled ? 'true' : null,
|
'aria-disabled': disabled ? 'true' : null,
|
||||||
'aria-label': aria[ button ],
|
'aria-label': aria[ button ],
|
||||||
'aria-role': 'link',
|
'role': 'link',
|
||||||
'aria-current': btnClass === classes.sPageButtonActive ? 'page' : null,
|
'aria-current': btnClass === classes.sPageButtonActive ? 'page' : null,
|
||||||
'data-dt-idx': button,
|
'data-dt-idx': button,
|
||||||
'tabindex': tabIndex,
|
'tabindex': disabled ? -1 : settings.iTabIndex,
|
||||||
'id': idx === 0 && typeof button === 'string' ?
|
'id': idx === 0 && typeof button === 'string' ?
|
||||||
settings.sTableId +'_'+ button :
|
settings.sTableId +'_'+ button :
|
||||||
null
|
null
|
||||||
|
@ -15041,7 +15066,7 @@
|
||||||
return -Infinity;
|
return -Infinity;
|
||||||
}
|
}
|
||||||
|
|
||||||
let type = typeof d;
|
var type = typeof d;
|
||||||
|
|
||||||
if (type === 'number' || type === 'bigint') {
|
if (type === 'number' || type === 'bigint') {
|
||||||
return d;
|
return d;
|
||||||
|
@ -15415,7 +15440,7 @@
|
||||||
var __thousands = ',';
|
var __thousands = ',';
|
||||||
var __decimal = '.';
|
var __decimal = '.';
|
||||||
|
|
||||||
if (Intl) {
|
if (window.Intl !== undefined) {
|
||||||
try {
|
try {
|
||||||
var num = new Intl.NumberFormat().formatToParts(100000.1);
|
var num = new Intl.NumberFormat().formatToParts(100000.1);
|
||||||
|
|
||||||
|
@ -15718,7 +15743,7 @@
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (typeof window !== 'undefined') {
|
if (typeof window === 'undefined') {
|
||||||
module.exports = function (root, $) {
|
module.exports = function (root, $) {
|
||||||
if ( ! root ) {
|
if ( ! root ) {
|
||||||
// CommonJS environments without a window global must pass a
|
// CommonJS environments without a window global must pass a
|
||||||
|
@ -15856,10 +15881,10 @@ DataTable.ext.renderer.pageButton.bootstrap = function ( settings, host, idx, bu
|
||||||
'aria-controls': settings.sTableId,
|
'aria-controls': settings.sTableId,
|
||||||
'aria-disabled': disabled ? 'true' : null,
|
'aria-disabled': disabled ? 'true' : null,
|
||||||
'aria-label': aria[ button ],
|
'aria-label': aria[ button ],
|
||||||
'aria-role': 'link',
|
'role': 'link',
|
||||||
'aria-current': btnClass === 'active' ? 'page' : null,
|
'aria-current': btnClass === 'active' ? 'page' : null,
|
||||||
'data-dt-idx': button,
|
'data-dt-idx': button,
|
||||||
'tabindex': settings.iTabIndex,
|
'tabindex': disabled ? -1 : settings.iTabIndex,
|
||||||
'class': 'page-link'
|
'class': 'page-link'
|
||||||
} )
|
} )
|
||||||
.html( btnDisplay )
|
.html( btnDisplay )
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,5 +1,5 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en" data-bs-theme="auto">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
@ -10,17 +10,17 @@
|
||||||
<link rel="stylesheet" href="{{urlpath}}/vw_static/admin.css" />
|
<link rel="stylesheet" href="{{urlpath}}/vw_static/admin.css" />
|
||||||
<script src="{{urlpath}}/vw_static/admin.js"></script>
|
<script src="{{urlpath}}/vw_static/admin.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body class="bg-light">
|
<body>
|
||||||
<nav class="navbar navbar-expand-md navbar-dark bg-dark mb-4 shadow fixed-top">
|
<nav class="navbar navbar-expand-md navbar-dark bg-dark mb-4 shadow fixed-top">
|
||||||
<div class="container-xl">
|
<div class="container-xl">
|
||||||
<a class="navbar-brand" href="{{urlpath}}/admin"><img class="vaultwarden-icon" src="{{urlpath}}/vw_static/vaultwarden-icon.png" alt="V">aultwarden Admin</a>
|
<a class="navbar-brand" href="{{urlpath}}/admin"><img class="vaultwarden-icon" src="{{urlpath}}/vw_static/vaultwarden-icon.png" alt="V">aultwarden Admin</a>
|
||||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarCollapse"
|
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarCollapse"
|
||||||
aria-controls="navbarCollapse" aria-expanded="false" aria-label="Toggle navigation">
|
aria-controls="navbarCollapse" aria-expanded="false" aria-label="Toggle navigation">
|
||||||
<span class="navbar-toggler-icon"></span>
|
<span class="navbar-toggler-icon"></span>
|
||||||
</button>
|
</button>
|
||||||
<div class="collapse navbar-collapse" id="navbarCollapse">
|
<div class="collapse navbar-collapse" id="navbarCollapse">
|
||||||
<ul class="navbar-nav me-auto">
|
<ul class="navbar-nav me-auto">
|
||||||
{{#if logged_in}}
|
{{#if logged_in}}
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link" href="{{urlpath}}/admin">Settings</a>
|
<a class="nav-link" href="{{urlpath}}/admin">Settings</a>
|
||||||
</li>
|
</li>
|
||||||
|
@ -33,15 +33,59 @@
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link" href="{{urlpath}}/admin/diagnostics">Diagnostics</a>
|
<a class="nav-link" href="{{urlpath}}/admin/diagnostics">Diagnostics</a>
|
||||||
</li>
|
</li>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link" href="{{urlpath}}/" target="_blank" rel="noreferrer">Vault</a>
|
<a class="nav-link" href="{{urlpath}}/" target="_blank" rel="noreferrer">Vault</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
<ul class="navbar-nav">
|
||||||
|
<li class="nav-item dropdown">
|
||||||
|
<button
|
||||||
|
class="btn btn-link nav-link py-0 px-0 px-md-2 dropdown-toggle d-flex align-items-center"
|
||||||
|
id="bd-theme" type="button" aria-expanded="false" data-bs-toggle="dropdown"
|
||||||
|
data-bs-display="static" aria-label="Toggle theme (auto)">
|
||||||
|
<span class="my-1 fs-4 theme-icon-active">
|
||||||
|
<use>☯</use>
|
||||||
|
</span>
|
||||||
|
<span class="d-md-none ms-2" id="bd-theme-text">Toggle theme</span>
|
||||||
|
</button>
|
||||||
|
<ul class="dropdown-menu dropdown-menu-end" aria-labelledby="bd-theme-text">
|
||||||
|
<li>
|
||||||
|
<button type="button" class="dropdown-item d-flex align-items-center"
|
||||||
|
data-bs-theme-value="light" aria-pressed="false">
|
||||||
|
<span class="me-2 fs-4 theme-icon">
|
||||||
|
<use>☀</use>
|
||||||
|
</span>
|
||||||
|
Light
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<button type="button" class="dropdown-item d-flex align-items-center"
|
||||||
|
data-bs-theme-value="dark" aria-pressed="false">
|
||||||
|
<span class="me-2 fs-4 theme-icon">
|
||||||
|
<use>★</use>
|
||||||
|
</span>
|
||||||
|
Dark
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<button type="button" class="dropdown-item d-flex align-items-center active"
|
||||||
|
data-bs-theme-value="auto" aria-pressed="true">
|
||||||
|
<span class="me-2 fs-4 theme-icon">
|
||||||
|
<use>☯</use>
|
||||||
|
</span>
|
||||||
|
Auto
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
{{#if logged_in}}
|
{{#if logged_in}}
|
||||||
<a class="btn btn-sm btn-secondary" href="{{urlpath}}/admin/logout">Log Out</a>
|
<a class="btn btn-sm btn-secondary" href="{{urlpath}}/admin/logout">Log Out</a>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
@ -49,6 +93,6 @@
|
||||||
{{> (lookup this "page_content") }}
|
{{> (lookup this "page_content") }}
|
||||||
|
|
||||||
<!-- This script needs to be at the bottom, else it will fail! -->
|
<!-- This script needs to be at the bottom, else it will fail! -->
|
||||||
<script src="{{urlpath}}/vw_static/bootstrap-native.js"></script>
|
<script src="{{urlpath}}/vw_static/bootstrap.bundle.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<main class="container-xl">
|
<main class="container-xl">
|
||||||
<div id="diagnostics-block" class="my-3 p-3 bg-white rounded shadow">
|
<div id="diagnostics-block" class="my-3 p-3 rounded shadow">
|
||||||
<h6 class="border-bottom pb-2 mb-2">Diagnostics</h6>
|
<h6 class="border-bottom pb-2 mb-2">Diagnostics</h6>
|
||||||
|
|
||||||
<h3>Versions</h3>
|
<h3>Versions</h3>
|
||||||
|
@ -8,8 +8,8 @@
|
||||||
<dl class="row">
|
<dl class="row">
|
||||||
<dt class="col-sm-5">Server Installed
|
<dt class="col-sm-5">Server Installed
|
||||||
<span class="badge bg-success d-none" id="server-success" title="Latest version is installed.">Ok</span>
|
<span class="badge bg-success d-none" id="server-success" title="Latest version is installed.">Ok</span>
|
||||||
<span class="badge bg-warning d-none" id="server-warning" title="There seems to be an update available.">Update</span>
|
<span class="badge bg-warning text-dark d-none" id="server-warning" title="There seems to be an update available.">Update</span>
|
||||||
<span class="badge bg-info d-none" id="server-branch" title="This is a branched version.">Branched</span>
|
<span class="badge bg-info text-dark d-none" id="server-branch" title="This is a branched version.">Branched</span>
|
||||||
</dt>
|
</dt>
|
||||||
<dd class="col-sm-7">
|
<dd class="col-sm-7">
|
||||||
<span id="server-installed">{{page_data.current_release}}</span>
|
<span id="server-installed">{{page_data.current_release}}</span>
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
<main class="container-xl">
|
<main class="container-xl">
|
||||||
{{#if error}}
|
{{#if error}}
|
||||||
<div class="align-items-center p-3 mb-3 text-white-50 bg-warning rounded shadow">
|
<div class="align-items-center p-3 mb-3 text-opacity-50 text-dark bg-warning rounded shadow">
|
||||||
<div>
|
<div>
|
||||||
<h6 class="mb-0 text-white">{{error}}</h6>
|
<h6 class="mb-0 text-dark">{{error}}</h6>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
<div class="align-items-center p-3 mb-3 text-white-50 bg-danger rounded shadow">
|
<div class="align-items-center p-3 mb-3 text-opacity-75 text-light bg-danger rounded shadow">
|
||||||
<div>
|
<div>
|
||||||
<h6 class="mb-0 text-white">Authentication key needed to continue</h6>
|
<h6 class="mb-0 text-light">Authentication key needed to continue</h6>
|
||||||
<small>Please provide it below:</small>
|
<small>Please provide it below:</small>
|
||||||
|
|
||||||
<form class="form-inline" method="post" action="{{urlpath}}/admin">
|
<form class="form-inline" method="post" action="{{urlpath}}/admin">
|
||||||
|
@ -17,7 +17,7 @@
|
||||||
{{#if redirect}}
|
{{#if redirect}}
|
||||||
<input type="hidden" id="redirect" name="redirect" value="/{{redirect}}">
|
<input type="hidden" id="redirect" name="redirect" value="/{{redirect}}">
|
||||||
{{/if}}
|
{{/if}}
|
||||||
<button type="submit" class="btn btn-primary">Enter</button>
|
<button type="submit" class="btn btn-primary mt-2">Enter</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<main class="container-xl">
|
<main class="container-xl">
|
||||||
<div id="organizations-block" class="my-3 p-3 bg-white rounded shadow">
|
<div id="organizations-block" class="my-3 p-3 rounded shadow">
|
||||||
<h6 class="border-bottom pb-2 mb-3">Organizations</h6>
|
<h6 class="border-bottom pb-2 mb-3">Organizations</h6>
|
||||||
<div class="table-responsive-xl small">
|
<div class="table-responsive-xl small">
|
||||||
<table id="orgs-table" class="table table-sm table-striped table-hover">
|
<table id="orgs-table" class="table table-sm table-striped table-hover">
|
||||||
|
@ -59,7 +59,7 @@
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<link rel="stylesheet" href="{{urlpath}}/vw_static/datatables.css" />
|
<link rel="stylesheet" href="{{urlpath}}/vw_static/datatables.css" />
|
||||||
<script src="{{urlpath}}/vw_static/jquery-3.6.4.slim.js"></script>
|
<script src="{{urlpath}}/vw_static/jquery-3.7.0.slim.js"></script>
|
||||||
<script src="{{urlpath}}/vw_static/datatables.js"></script>
|
<script src="{{urlpath}}/vw_static/datatables.js"></script>
|
||||||
<script src="{{urlpath}}/vw_static/admin_organizations.js"></script>
|
<script src="{{urlpath}}/vw_static/admin_organizations.js"></script>
|
||||||
<script src="{{urlpath}}/vw_static/jdenticon.js"></script>
|
<script src="{{urlpath}}/vw_static/jdenticon.js"></script>
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
<form class="form needs-validation" id="config-form" novalidate>
|
<form class="form needs-validation" id="config-form" novalidate>
|
||||||
{{#each page_data.config}}
|
{{#each page_data.config}}
|
||||||
{{#if groupdoc}}
|
{{#if groupdoc}}
|
||||||
<div class="card bg-light mb-3">
|
<div class="card mb-3">
|
||||||
<button id="b_{{group}}" type="button" class="card-header text-start btn btn-link text-decoration-none" aria-expanded="false" aria-controls="g_{{group}}" data-bs-toggle="collapse" data-bs-target="#g_{{group}}">{{groupdoc}}</button>
|
<button id="b_{{group}}" type="button" class="card-header text-start btn btn-link text-decoration-none" aria-expanded="false" aria-controls="g_{{group}}" data-bs-toggle="collapse" data-bs-target="#g_{{group}}">{{groupdoc}}</button>
|
||||||
<div id="g_{{group}}" class="card-body collapse">
|
<div id="g_{{group}}" class="card-body collapse">
|
||||||
{{#each elements}}
|
{{#each elements}}
|
||||||
|
@ -64,7 +64,7 @@
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{/each}}
|
{{/each}}
|
||||||
|
|
||||||
<div class="card bg-light mb-3">
|
<div class="card mb-3">
|
||||||
<button id="b_readonly" type="button" class="card-header text-start btn btn-link text-decoration-none" aria-expanded="false" aria-controls="g_readonly"
|
<button id="b_readonly" type="button" class="card-header text-start btn btn-link text-decoration-none" aria-expanded="false" aria-controls="g_readonly"
|
||||||
data-bs-toggle="collapse" data-bs-target="#g_readonly">Read-Only Config</button>
|
data-bs-toggle="collapse" data-bs-target="#g_readonly">Read-Only Config</button>
|
||||||
<div id="g_readonly" class="card-body collapse">
|
<div id="g_readonly" class="card-body collapse">
|
||||||
|
@ -119,7 +119,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{#if page_data.can_backup}}
|
{{#if page_data.can_backup}}
|
||||||
<div class="card bg-light mb-3">
|
<div class="card mb-3">
|
||||||
<button id="b_database" type="button" class="card-header text-start btn btn-link text-decoration-none" aria-expanded="false" aria-controls="g_database"
|
<button id="b_database" type="button" class="card-header text-start btn btn-link text-decoration-none" aria-expanded="false" aria-controls="g_database"
|
||||||
data-bs-toggle="collapse" data-bs-target="#g_database">Backup Database</button>
|
data-bs-toggle="collapse" data-bs-target="#g_database">Backup Database</button>
|
||||||
<div id="g_database" class="card-body collapse">
|
<div id="g_database" class="card-body collapse">
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<main class="container-xl">
|
<main class="container-xl">
|
||||||
<div id="users-block" class="my-3 p-3 bg-white rounded shadow">
|
<div id="users-block" class="my-3 p-3 rounded shadow">
|
||||||
<h6 class="border-bottom pb-2 mb-3">Registered Users</h6>
|
<h6 class="border-bottom pb-2 mb-3">Registered Users</h6>
|
||||||
<div class="table-responsive-xl small">
|
<div class="table-responsive-xl small">
|
||||||
<table id="users-table" class="table table-sm table-striped table-hover">
|
<table id="users-table" class="table table-sm table-striped table-hover">
|
||||||
|
@ -30,7 +30,7 @@
|
||||||
<span class="badge bg-success me-2" title="2FA is enabled">2FA</span>
|
<span class="badge bg-success me-2" title="2FA is enabled">2FA</span>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{#case _Status 1}}
|
{{#case _Status 1}}
|
||||||
<span class="badge bg-warning me-2" title="User is invited">Invited</span>
|
<span class="badge bg-warning text-dark me-2" title="User is invited">Invited</span>
|
||||||
{{/case}}
|
{{/case}}
|
||||||
{{#if EmailVerified}}
|
{{#if EmailVerified}}
|
||||||
<span class="badge bg-success me-2" title="Email has been verified">Verified</span>
|
<span class="badge bg-success me-2" title="Email has been verified">Verified</span>
|
||||||
|
@ -140,7 +140,7 @@
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<link rel="stylesheet" href="{{urlpath}}/vw_static/datatables.css" />
|
<link rel="stylesheet" href="{{urlpath}}/vw_static/datatables.css" />
|
||||||
<script src="{{urlpath}}/vw_static/jquery-3.6.4.slim.js"></script>
|
<script src="{{urlpath}}/vw_static/jquery-3.7.0.slim.js"></script>
|
||||||
<script src="{{urlpath}}/vw_static/datatables.js"></script>
|
<script src="{{urlpath}}/vw_static/datatables.js"></script>
|
||||||
<script src="{{urlpath}}/vw_static/admin_users.js"></script>
|
<script src="{{urlpath}}/vw_static/admin_users.js"></script>
|
||||||
<script src="{{urlpath}}/vw_static/jdenticon.js"></script>
|
<script src="{{urlpath}}/vw_static/jdenticon.js"></script>
|
||||||
|
|
Loading…
Reference in a new issue