mirror of
https://github.com/dani-garcia/vaultwarden.git
synced 2025-09-12 11:35:57 +03:00
Improve sync speed and updated dep. versions
Improved sync speed by resolving the N+1 query issues. Solves #1402 and Solves #1453 With this change there is just one query done to retreive all the important data, and matching is done in-code/memory. With a very large database the sync time went down about 3 times. Also updated misc crates and Github Actions versions.
This commit is contained in:
216
src/static/scripts/bootstrap-native.js
vendored
216
src/static/scripts/bootstrap-native.js
vendored
@@ -1,5 +1,5 @@
|
||||
/*!
|
||||
* Native JavaScript for Bootstrap v4.1.0 (https://thednp.github.io/bootstrap.native/)
|
||||
* Native JavaScript for Bootstrap v4.1.2 (https://thednp.github.io/bootstrap.native/)
|
||||
* Copyright 2015-2022 © dnp_theme
|
||||
* Licensed under MIT (https://github.com/thednp/bootstrap.native/blob/master/LICENSE)
|
||||
*/
|
||||
@@ -545,7 +545,7 @@
|
||||
return normalOps;
|
||||
}
|
||||
|
||||
var version = "4.1.0";
|
||||
var version = "4.1.2";
|
||||
|
||||
const Version = version;
|
||||
|
||||
@@ -2814,6 +2814,29 @@
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a shortie for `document.createElement` method
|
||||
* which allows you to create a new `HTMLElement` for a given `tagName`
|
||||
* or based on an object with specific non-readonly attributes:
|
||||
* `id`, `className`, `textContent`, `style`, etc.
|
||||
* @see https://developer.mozilla.org/en-US/docs/Web/API/Document/createElement
|
||||
*
|
||||
* @param {Record<string, string> | string} param `tagName` or object
|
||||
* @return {HTMLElement | Element} a new `HTMLElement` or `Element`
|
||||
*/
|
||||
function createElement(param) {
|
||||
if (typeof param === 'string') {
|
||||
return getDocument().createElement(param);
|
||||
}
|
||||
|
||||
const { tagName } = param;
|
||||
const attr = { ...param };
|
||||
const newElement = createElement(tagName);
|
||||
delete attr.tagName;
|
||||
ObjectAssign(newElement, attr);
|
||||
return newElement;
|
||||
}
|
||||
|
||||
/** @type {string} */
|
||||
const offcanvasString = 'offcanvas';
|
||||
|
||||
@@ -2824,7 +2847,7 @@
|
||||
const offcanvasActiveSelector = `.${offcanvasString}.${showClass}`;
|
||||
|
||||
// any document would suffice
|
||||
const overlay = getDocument().createElement('div');
|
||||
const overlay = createElement('div');
|
||||
|
||||
/**
|
||||
* Returns the current active modal / offcancas element.
|
||||
@@ -2863,8 +2886,10 @@
|
||||
* Shows the overlay to the user.
|
||||
*/
|
||||
function showOverlay() {
|
||||
addClass(overlay, showClass);
|
||||
reflow(overlay);
|
||||
if (!hasClass(overlay, showClass)) {
|
||||
addClass(overlay, showClass);
|
||||
reflow(overlay);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2949,7 +2974,7 @@
|
||||
|
||||
if (!modalOverflow && scrollbarWidth) {
|
||||
const pad = isRTL(element) ? 'paddingLeft' : 'paddingRight';
|
||||
// @ts-ignore
|
||||
// @ts-ignore -- cannot use `setElementStyle`
|
||||
element.style[pad] = `${scrollbarWidth}px`;
|
||||
}
|
||||
setScrollbar(element, (modalOverflow || clientHeight !== scrollHeight));
|
||||
@@ -2989,15 +3014,16 @@
|
||||
* @param {Modal} self the `Modal` instance
|
||||
*/
|
||||
function afterModalHide(self) {
|
||||
const { triggers, element } = self;
|
||||
const { triggers, element, relatedTarget } = self;
|
||||
removeOverlay(element);
|
||||
// @ts-ignore
|
||||
element.style.paddingRight = '';
|
||||
setElementStyle(element, { paddingRight: '' });
|
||||
toggleModalDismiss(self);
|
||||
|
||||
if (triggers.length) {
|
||||
const visibleTrigger = triggers.find((x) => isVisible(x));
|
||||
if (visibleTrigger) focus(visibleTrigger);
|
||||
}
|
||||
const focusElement = showModalEvent.relatedTarget || triggers.find(isVisible);
|
||||
if (focusElement) focus(focusElement);
|
||||
|
||||
hiddenModalEvent.relatedTarget = relatedTarget;
|
||||
dispatchEvent(element, hiddenModalEvent);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3019,12 +3045,11 @@
|
||||
*/
|
||||
function beforeModalShow(self) {
|
||||
const { element, hasFade } = self;
|
||||
// @ts-ignore
|
||||
element.style.display = 'block';
|
||||
setElementStyle(element, { display: 'block' });
|
||||
|
||||
setModalScrollbar(self);
|
||||
if (!getCurrentOpen(element)) {
|
||||
getDocumentBody(element).style.overflow = 'hidden';
|
||||
setElementStyle(getDocumentBody(element), { overflow: 'hidden' });
|
||||
}
|
||||
|
||||
addClass(element, showClass);
|
||||
@@ -3042,11 +3067,10 @@
|
||||
*/
|
||||
function beforeModalHide(self, force) {
|
||||
const {
|
||||
element, options, relatedTarget, hasFade,
|
||||
element, options, hasFade,
|
||||
} = self;
|
||||
|
||||
// @ts-ignore
|
||||
element.style.display = '';
|
||||
setElementStyle(element, { display: '' });
|
||||
|
||||
// force can also be the transitionEvent object, we wanna make sure it's not
|
||||
// call is not forced and overlay is visible
|
||||
@@ -3057,11 +3081,6 @@
|
||||
} else {
|
||||
afterModalHide(self);
|
||||
}
|
||||
|
||||
toggleModalDismiss(self);
|
||||
|
||||
hiddenModalEvent.relatedTarget = relatedTarget;
|
||||
dispatchEvent(element, hiddenModalEvent);
|
||||
}
|
||||
|
||||
// MODAL EVENT HANDLERS
|
||||
@@ -3243,14 +3262,15 @@
|
||||
}
|
||||
|
||||
if (backdrop) {
|
||||
if (!currentOpen && !hasClass(overlay, showClass)) {
|
||||
if (!container.contains(overlay)) {
|
||||
appendOverlay(container, hasFade, true);
|
||||
} else {
|
||||
toggleOverlayType(true);
|
||||
}
|
||||
|
||||
overlayDelay = getElementTransitionDuration(overlay);
|
||||
|
||||
if (!hasClass(overlay, showClass)) showOverlay();
|
||||
showOverlay();
|
||||
setTimeout(() => beforeModalShow(self), overlayDelay);
|
||||
} else {
|
||||
beforeModalShow(self);
|
||||
@@ -3398,13 +3418,12 @@
|
||||
|
||||
if (!options.scroll) {
|
||||
setOffCanvasScrollbar(self);
|
||||
getDocumentBody(element).style.overflow = 'hidden';
|
||||
setElementStyle(getDocumentBody(element), { overflow: 'hidden' });
|
||||
}
|
||||
|
||||
addClass(element, offcanvasTogglingClass);
|
||||
addClass(element, showClass);
|
||||
// @ts-ignore
|
||||
element.style.visibility = 'visible';
|
||||
setElementStyle(element, { visibility: 'visible' });
|
||||
|
||||
emulateTransitionEnd(element, () => showOffcanvasComplete(self));
|
||||
}
|
||||
@@ -3509,17 +3528,13 @@
|
||||
* @param {Offcanvas} self the `Offcanvas` instance
|
||||
*/
|
||||
function showOffcanvasComplete(self) {
|
||||
const { element, triggers } = self;
|
||||
const { element } = self;
|
||||
removeClass(element, offcanvasTogglingClass);
|
||||
|
||||
removeAttribute(element, ariaHidden);
|
||||
setAttribute(element, ariaModal, 'true');
|
||||
setAttribute(element, 'role', 'dialog');
|
||||
|
||||
if (triggers.length) {
|
||||
triggers.forEach((btn) => setAttribute(btn, ariaExpanded, 'true'));
|
||||
}
|
||||
|
||||
dispatchEvent(element, shownOffcanvasEvent);
|
||||
|
||||
toggleOffCanvasDismiss(self, true);
|
||||
@@ -3537,14 +3552,10 @@
|
||||
setAttribute(element, ariaHidden, 'true');
|
||||
removeAttribute(element, ariaModal);
|
||||
removeAttribute(element, 'role');
|
||||
// @ts-ignore
|
||||
element.style.visibility = '';
|
||||
setElementStyle(element, { visibility: '' });
|
||||
|
||||
if (triggers.length) {
|
||||
triggers.forEach((btn) => setAttribute(btn, ariaExpanded, 'false'));
|
||||
const visibleTrigger = triggers.find((x) => isVisible(x));
|
||||
if (visibleTrigger) focus(visibleTrigger);
|
||||
}
|
||||
const visibleTrigger = showOffcanvasEvent.relatedTarget || triggers.find((x) => isVisible(x));
|
||||
if (visibleTrigger) focus(visibleTrigger);
|
||||
|
||||
removeOverlay(element);
|
||||
|
||||
@@ -3634,13 +3645,14 @@
|
||||
}
|
||||
|
||||
if (options.backdrop) {
|
||||
if (!currentOpen) {
|
||||
if (!container.contains(overlay)) {
|
||||
appendOverlay(container, true);
|
||||
} else {
|
||||
toggleOverlayType();
|
||||
}
|
||||
|
||||
overlayDelay = getElementTransitionDuration(overlay);
|
||||
if (!hasClass(overlay, showClass)) showOverlay();
|
||||
showOverlay();
|
||||
|
||||
setTimeout(() => beforeOffcanvasShow(self), overlayDelay);
|
||||
} else {
|
||||
@@ -4055,7 +4067,8 @@
|
||||
*/
|
||||
const mousehoverEvent = 'hover';
|
||||
|
||||
let elementUID = 1;
|
||||
let elementUID = 0;
|
||||
let elementMapUID = 0;
|
||||
const elementIDMap = new Map();
|
||||
|
||||
/**
|
||||
@@ -4066,27 +4079,25 @@
|
||||
* @returns {number} an existing or new unique ID
|
||||
*/
|
||||
function getUID(element, key) {
|
||||
elementUID += 1;
|
||||
let elMap = elementIDMap.get(element);
|
||||
let result = elementUID;
|
||||
let result = key ? elementUID : elementMapUID;
|
||||
|
||||
if (key && key.length) {
|
||||
if (elMap) {
|
||||
const elMapId = elMap.get(key);
|
||||
if (!Number.isNaN(elMapId)) {
|
||||
result = elMapId;
|
||||
} else {
|
||||
elMap.set(key, result);
|
||||
}
|
||||
} else {
|
||||
elementIDMap.set(element, new Map());
|
||||
elMap = elementIDMap.get(element);
|
||||
elMap.set(key, result);
|
||||
if (key) {
|
||||
const elID = getUID(element);
|
||||
const elMap = elementIDMap.get(elID) || new Map();
|
||||
if (!elementIDMap.has(elID)) {
|
||||
elementIDMap.set(elID, elMap);
|
||||
}
|
||||
} else if (!Number.isNaN(elMap)) {
|
||||
result = elMap;
|
||||
if (!elMap.has(key)) {
|
||||
elMap.set(key, result);
|
||||
elementUID += 1;
|
||||
} else result = elMap.get(key);
|
||||
} else {
|
||||
elementIDMap.set(element, result);
|
||||
const elkey = element.id || element;
|
||||
|
||||
if (!elementIDMap.has(elkey)) {
|
||||
elementIDMap.set(elkey, result);
|
||||
elementMapUID += 1;
|
||||
} else result = elementIDMap.get(elkey);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -5098,6 +5109,8 @@
|
||||
const hiddenTabEvent = OriginalEvent(`hidden.bs.${tabString}`);
|
||||
|
||||
/**
|
||||
* Stores the current active tab and its content
|
||||
* for a given `.nav` element.
|
||||
* @type {Map<(HTMLElement | Element), any>}
|
||||
*/
|
||||
const tabPrivate = new Map();
|
||||
@@ -5111,7 +5124,7 @@
|
||||
function triggerTabEnd(self) {
|
||||
const { tabContent, nav } = self;
|
||||
|
||||
if (tabContent) {
|
||||
if (tabContent && hasClass(tabContent, collapsingClass)) {
|
||||
// @ts-ignore
|
||||
tabContent.style.height = '';
|
||||
removeClass(tabContent, collapsingClass);
|
||||
@@ -5125,11 +5138,13 @@
|
||||
* @param {Tab} self the `Tab` instance
|
||||
*/
|
||||
function triggerTabShow(self) {
|
||||
const { element, tabContent, nav } = self;
|
||||
const { currentHeight, nextHeight } = tabPrivate.get(element);
|
||||
const {
|
||||
element, tabContent, content: nextContent, nav,
|
||||
} = self;
|
||||
const { tab } = nav && tabPrivate.get(nav);
|
||||
|
||||
if (tabContent) { // height animation
|
||||
if (tabContent && hasClass(nextContent, fadeClass)) { // height animation
|
||||
const { currentHeight, nextHeight } = tabPrivate.get(element);
|
||||
if (currentHeight === nextHeight) {
|
||||
triggerTabEnd(self);
|
||||
} else {
|
||||
@@ -5141,6 +5156,7 @@
|
||||
}, 50);
|
||||
}
|
||||
} else if (nav) Timer.clear(nav);
|
||||
|
||||
shownTabEvent.relatedTarget = tab;
|
||||
dispatchEvent(element, shownTabEvent);
|
||||
}
|
||||
@@ -5156,9 +5172,11 @@
|
||||
const { tab, content } = nav && tabPrivate.get(nav);
|
||||
let currentHeight = 0;
|
||||
|
||||
if (tabContent) {
|
||||
[content, nextContent].forEach((c) => addClass(c, 'overflow-hidden'));
|
||||
currentHeight = content.scrollHeight;
|
||||
if (tabContent && hasClass(nextContent, fadeClass)) {
|
||||
[content, nextContent].forEach((c) => {
|
||||
addClass(c, 'overflow-hidden');
|
||||
});
|
||||
currentHeight = content.scrollHeight || 0;
|
||||
}
|
||||
|
||||
// update relatedTarget and dispatch event
|
||||
@@ -5170,7 +5188,7 @@
|
||||
addClass(nextContent, activeClass);
|
||||
removeClass(content, activeClass);
|
||||
|
||||
if (tabContent) {
|
||||
if (tabContent && hasClass(nextContent, fadeClass)) {
|
||||
const nextHeight = nextContent.scrollHeight;
|
||||
tabPrivate.set(element, { currentHeight, nextHeight });
|
||||
|
||||
@@ -5178,7 +5196,9 @@
|
||||
// @ts-ignore -- height animation
|
||||
tabContent.style.height = `${currentHeight}px`;
|
||||
reflow(tabContent);
|
||||
[content, nextContent].forEach((c) => removeClass(c, 'overflow-hidden'));
|
||||
[content, nextContent].forEach((c) => {
|
||||
removeClass(c, 'overflow-hidden');
|
||||
});
|
||||
}
|
||||
|
||||
if (nextContent && hasClass(nextContent, fadeClass)) {
|
||||
@@ -5187,8 +5207,11 @@
|
||||
emulateTransitionEnd(nextContent, () => {
|
||||
triggerTabShow(self);
|
||||
});
|
||||
}, 17);
|
||||
} else { triggerTabShow(self); }
|
||||
}, 1);
|
||||
} else {
|
||||
addClass(nextContent, showClass);
|
||||
triggerTabShow(self);
|
||||
}
|
||||
|
||||
dispatchEvent(tab, hiddenTabEvent);
|
||||
}
|
||||
@@ -5217,6 +5240,16 @@
|
||||
return { tab, content };
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a parent dropdown.
|
||||
* @param {HTMLElement | Element} element the `Tab` element
|
||||
* @returns {(HTMLElement | Element)?} the parent dropdown
|
||||
*/
|
||||
function getParentDropdown(element) {
|
||||
const dropdown = closest(element, `.${dropdownMenuClasses.join(',.')}`);
|
||||
return dropdown ? querySelector(`.${dropdownMenuClasses[0]}-toggle`, dropdown) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles on/off the `click` event listener.
|
||||
* @param {Tab} self the `Tab` instance
|
||||
@@ -5273,7 +5306,22 @@
|
||||
|
||||
// event targets
|
||||
/** @type {(HTMLElement | Element)?} */
|
||||
self.dropdown = nav && querySelector(`.${dropdownMenuClasses[0]}-toggle`, nav);
|
||||
self.dropdown = getParentDropdown(element);
|
||||
|
||||
// show first Tab instance of none is shown
|
||||
// suggested on #432
|
||||
const { tab } = getActiveTab(self);
|
||||
if (nav && !tab) {
|
||||
const firstTab = querySelector(tabSelector, nav);
|
||||
const firstTabContent = firstTab && getTargetElement(firstTab);
|
||||
|
||||
if (firstTabContent) {
|
||||
addClass(firstTab, activeClass);
|
||||
addClass(firstTabContent, showClass);
|
||||
addClass(firstTabContent, activeClass);
|
||||
setAttribute(element, ariaSelected, 'true');
|
||||
}
|
||||
}
|
||||
|
||||
// add event listener
|
||||
toggleTabHandler(self, true);
|
||||
@@ -5301,20 +5349,24 @@
|
||||
|
||||
// update relatedTarget and dispatch
|
||||
hideTabEvent.relatedTarget = element;
|
||||
|
||||
dispatchEvent(tab, hideTabEvent);
|
||||
if (hideTabEvent.defaultPrevented) return;
|
||||
|
||||
if (nav) Timer.set(nav, () => {}, 17);
|
||||
removeClass(tab, activeClass);
|
||||
setAttribute(tab, ariaSelected, 'false');
|
||||
addClass(element, activeClass);
|
||||
setAttribute(element, ariaSelected, 'true');
|
||||
|
||||
if (dropdown) {
|
||||
// @ts-ignore
|
||||
if (!hasClass(element.parentNode, dropdownMenuClass)) {
|
||||
if (hasClass(dropdown, activeClass)) removeClass(dropdown, activeClass);
|
||||
} else if (!hasClass(dropdown, activeClass)) addClass(dropdown, activeClass);
|
||||
const activeDropdown = getParentDropdown(tab);
|
||||
if (activeDropdown && hasClass(activeDropdown, activeClass)) {
|
||||
removeClass(activeDropdown, activeClass);
|
||||
}
|
||||
|
||||
if (nav) {
|
||||
Timer.set(nav, () => {
|
||||
removeClass(tab, activeClass);
|
||||
setAttribute(tab, ariaSelected, 'false');
|
||||
if (dropdown && !hasClass(dropdown, activeClass)) addClass(dropdown, activeClass);
|
||||
}, 1);
|
||||
}
|
||||
|
||||
if (hasClass(content, fadeClass)) {
|
||||
|
4
src/static/scripts/datatables.css
vendored
4
src/static/scripts/datatables.css
vendored
@@ -4,10 +4,10 @@
|
||||
*
|
||||
* To rebuild or modify this file with the latest versions of the included
|
||||
* software please visit:
|
||||
* https://datatables.net/download/#bs5/dt-1.11.4
|
||||
* https://datatables.net/download/#bs5/dt-1.11.5
|
||||
*
|
||||
* Included libraries:
|
||||
* DataTables 1.11.4
|
||||
* DataTables 1.11.5
|
||||
*/
|
||||
|
||||
@charset "UTF-8";
|
||||
|
10899
src/static/scripts/datatables.js
vendored
10899
src/static/scripts/datatables.js
vendored
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user