diff --git a/assets/controllers/common/dirty_form_controller.js b/assets/controllers/common/dirty_form_controller.js
index 8e560a3f..aad2e6b0 100644
--- a/assets/controllers/common/dirty_form_controller.js
+++ b/assets/controllers/common/dirty_form_controller.js
@@ -19,7 +19,8 @@
import {Controller} from "@hotwired/stimulus";
import {visit} from "@hotwired/turbo";
-import {ConfirmSwal} from "../../helpers/swal";
+import * as bootbox from "bootbox";
+import "../../css/components/bootbox_extensions.css";
import "../../css/components/dirty_form.css";
/**
@@ -206,10 +207,11 @@ export default class extends Controller {
}
_confirmNavigation(onConfirm) {
- ConfirmSwal.fire({
- titleText: this.confirmTitleValue,
- text: this.confirmMessageValue,
- }).then(({isConfirmed}) => { if (isConfirmed) onConfirm(); });
+ bootbox.confirm({
+ title: this.confirmTitleValue,
+ message: this.confirmMessageValue,
+ callback: (result) => { if (result) onConfirm(); }
+ });
}
_handleLinkClick(event) {
diff --git a/assets/controllers/elements/collection_type_controller.js b/assets/controllers/elements/collection_type_controller.js
index caeb4122..647ed5e5 100644
--- a/assets/controllers/elements/collection_type_controller.js
+++ b/assets/controllers/elements/collection_type_controller.js
@@ -19,7 +19,8 @@
import {Controller} from "@hotwired/stimulus";
-import {AlertSwal, ConfirmSwal} from "../../helpers/swal";
+import * as bootbox from "bootbox";
+import "../../css/components/bootbox_extensions.css";
import accept from "attr-accept";
export default class extends Controller {
@@ -61,7 +62,7 @@ export default class extends Controller {
if(!prototype) {
console.warn("Prototype is not set, we cannot create a new element. This is most likely due to missing permissions.");
- AlertSwal.fire({"text": "You do not have the permissions to create a new element. (No protoype element is set)"});
+ bootbox.alert("You do not have the permissions to create a new element. (No protoype element is set)");
return;
}
@@ -225,10 +226,8 @@ export default class extends Controller {
}
if(this.deleteMessageValue) {
- ConfirmSwal.fire({
- text: this.deleteMessageValue,
- }).then(({isConfirmed}) => {
- if (isConfirmed) {
+ bootbox.confirm(this.deleteMessageValue, (result) => {
+ if (result) {
del();
}
});
diff --git a/assets/controllers/elements/datatables/datatables_controller.js b/assets/controllers/elements/datatables/datatables_controller.js
index 4b84a834..d945004b 100644
--- a/assets/controllers/elements/datatables/datatables_controller.js
+++ b/assets/controllers/elements/datatables/datatables_controller.js
@@ -38,7 +38,9 @@ import 'datatables.net-colreorder-bs5';
import 'datatables.net-responsive-bs5';
import '../../../js/lib/datatables';
-import 'datatables.net-select-bs5';
+//import 'datatables.net-select-bs5';
+//Use the local version containing the fix for the select extension
+import '../../../js/lib/dataTables.select.mjs';
const EVENT_DT_LOADED = 'dt:loaded';
diff --git a/assets/controllers/elements/datatables/parts_controller.js b/assets/controllers/elements/datatables/parts_controller.js
index cfa386cc..c43fa276 100644
--- a/assets/controllers/elements/datatables/parts_controller.js
+++ b/assets/controllers/elements/datatables/parts_controller.js
@@ -20,7 +20,7 @@
import DatatablesController from "./datatables_controller.js";
import TomSelect from "tom-select";
-import {ConfirmSwal} from "../../../helpers/swal";
+import * as bootbox from "bootbox";
/**
* This is the datatables controller for parts lists
@@ -146,17 +146,15 @@ export default class extends DatatablesController {
bubbles: true, //This line is important, otherwise Turbo will not receive the event
});
- ConfirmSwal.fire({
- titleText: title,
- text: message,
- icon: "warning"
- }).then(({isConfirmed}) => {
- //If the dialog was confirmed, then submit the form.
- if (isConfirmed) {
- that._confirmed = true;
- form.dispatchEvent(that._our_event);
- } else {
- that._confirmed = false;
+ const confirm = bootbox.confirm({
+ message: message, title: title, callback: function (result) {
+ //If the dialog was confirmed, then submit the form.
+ if (result) {
+ that._confirmed = true;
+ form.dispatchEvent(that._our_event);
+ } else {
+ that._confirmed = false;
+ }
}
});
}
diff --git a/assets/controllers/elements/delete_btn_controller.js b/assets/controllers/elements/delete_btn_controller.js
index e1b37bcc..9ab15f7d 100644
--- a/assets/controllers/elements/delete_btn_controller.js
+++ b/assets/controllers/elements/delete_btn_controller.js
@@ -19,7 +19,8 @@
import {Controller} from "@hotwired/stimulus";
-import {ConfirmSwal} from "../../helpers/swal";
+import * as bootbox from "bootbox";
+import "../../css/components/bootbox_extensions.css";
export default class extends Controller
{
@@ -47,33 +48,32 @@ export default class extends Controller
const submitter = event.submitter;
const that = this;
- ConfirmSwal.fire({
- titleText: title,
- html: message, //Message contains a tag and no user injectable HTML
- }).then(({isConfirmed}) => {
- //If the dialog was confirmed, then submit the form.
- if (isConfirmed) {
- //Set a flag to prevent the dialog from popping up again and allowing turbo to submit the form
- that._confirmed = true;
+ const confirm = bootbox.confirm({
+ message: message, title: title, callback: function (result) {
+ //If the dialog was confirmed, then submit the form.
+ if (result) {
+ //Set a flag to prevent the dialog from popping up again and allowing turbo to submit the form
+ that._confirmed = true;
- //Create a submit button in the form and click it to submit the form
- //Before a submit event was dispatched, but this caused weird issues on Firefox causing the delete request being posted twice (and the second time was returning 404). See https://github.com/Part-DB/Part-DB-server/issues/273
- const submit_btn = document.createElement('button');
- submit_btn.type = 'submit';
- submit_btn.style.display = 'none';
+ //Create a submit button in the form and click it to submit the form
+ //Before a submit event was dispatched, but this caused weird issues on Firefox causing the delete request being posted twice (and the second time was returning 404). See https://github.com/Part-DB/Part-DB-server/issues/273
+ const submit_btn = document.createElement('button');
+ submit_btn.type = 'submit';
+ submit_btn.style.display = 'none';
- //If the clicked button has a value, set it on the submit button
- if (submitter.value) {
- submit_btn.value = submitter.value;
+ //If the clicked button has a value, set it on the submit button
+ if (submitter.value) {
+ submit_btn.value = submitter.value;
+ }
+ if (submitter.name) {
+ submit_btn.name = submitter.name;
+ }
+ form.appendChild(submit_btn);
+ submit_btn.click();
+ } else {
+ that._confirmed = false;
}
- if (submitter.name) {
- submit_btn.name = submitter.name;
- }
- form.appendChild(submit_btn);
- submit_btn.click();
- } else {
- that._confirmed = false;
}
});
}
-}
+}
\ No newline at end of file
diff --git a/assets/controllers/elements/link_confirm_controller.js b/assets/controllers/elements/link_confirm_controller.js
index be226517..3d59b492 100644
--- a/assets/controllers/elements/link_confirm_controller.js
+++ b/assets/controllers/elements/link_confirm_controller.js
@@ -19,7 +19,8 @@
import {Controller} from "@hotwired/stimulus";
-import {ConfirmSwal} from "../../helpers/swal";
+import * as bootbox from "bootbox";
+import "../../css/components/bootbox_extensions.css";
export default class extends Controller
{
@@ -52,19 +53,20 @@ export default class extends Controller
const that = this;
- ConfirmSwal.fire({
- titleText: this.titleValue,
- text: this.messageValue,
- }).then(({isConfirmed}) => {
- if (isConfirmed) {
- //Set a flag to prevent the dialog from popping up again and allowing turbo to submit the form
- that._confirmed = true;
+ bootbox.confirm({
+ title: this.titleValue,
+ message: this.messageValue,
+ callback: (result) => {
+ if (result) {
+ //Set a flag to prevent the dialog from popping up again and allowing turbo to submit the form
+ that._confirmed = true;
- //Click the link
- that.element.click();
- } else {
- that._confirmed = false;
+ //Click the link
+ that.element.click();
+ } else {
+ that._confirmed = false;
+ }
}
});
}
-}
+}
\ No newline at end of file
diff --git a/assets/controllers/elements/password_strength_estimate_controller.js b/assets/controllers/elements/password_strength_estimate_controller.js
index 9ad2da1c..d9cfbc87 100644
--- a/assets/controllers/elements/password_strength_estimate_controller.js
+++ b/assets/controllers/elements/password_strength_estimate_controller.js
@@ -19,14 +19,12 @@
import {Controller} from "@hotwired/stimulus";
-import { ZxcvbnFactory } from '@zxcvbn-ts/core';
+import { zxcvbn, zxcvbnOptions } from '@zxcvbn-ts/core';
import * as zxcvbnCommonPackage from '@zxcvbn-ts/language-common';
import * as zxcvbnEnPackage from '@zxcvbn-ts/language-en';
import * as zxcvbnDePackage from '@zxcvbn-ts/language-de';
import * as zxcvbnFrPackage from '@zxcvbn-ts/language-fr';
import * as zxcvbnJaPackage from '@zxcvbn-ts/language-ja';
-import * as zxcvbnItPackage from '@zxcvbn-ts/language-it';
-import * as zxcvbnPlPackage from '@zxcvbn-ts/language-pl';
import {trans} from '../../translator.js';
/* stimulusFetch: 'lazy' */
@@ -36,8 +34,6 @@ export default class extends Controller {
static targets = ["badge", "warning"]
- _zxcvbnFactory;
-
_getTranslations() {
//Get the current locale
const locale = document.documentElement.lang;
@@ -47,10 +43,6 @@ export default class extends Controller {
return zxcvbnFrPackage.translations;
} else if (locale.includes('ja')) {
return zxcvbnJaPackage.translations;
- } else if (locale.includes('it')) {
- return zxcvbnItPackage.translations;
- } else if (locale.includes('pl')) {
- return zxcvbnPlPackage.translations;
}
//Fallback to english
@@ -64,39 +56,34 @@ export default class extends Controller {
//Configure zxcvbn
const options = {
graphs: zxcvbnCommonPackage.adjacencyGraphs,
- useLevenshtein: true,
dictionary: {
...zxcvbnCommonPackage.dictionary,
// We could use the english dictionary here too, but it is very big. So we just use the common words
- ...zxcvbnEnPackage.dictionary,
- ...zxcvbnDePackage.dictionary,
-
- "partdb": ['part-db', 'partdb', 'part_db', 'part-db-symfony', 'partdb-symfony', 'part_db_symfony'],
+ //...zxcvbnEnPackage.dictionary,
},
translations: this._getTranslations(),
};
-
- this._zxcvbnFactory = new ZxcvbnFactory(options);
+ zxcvbnOptions.setOptions(options);
//Add event listener to the password input field
this._passwordInput.addEventListener('input', this._onPasswordInput.bind(this));
}
- async _onPasswordInput() {
+ _onPasswordInput() {
//Retrieve the password
const password = this._passwordInput.value;
//Estimate the password strength
- const result = await this._zxcvbnFactory.checkAsync(password);
+ const result = zxcvbn(password);
//Update the badge
this.badgeTarget.parentElement.classList.remove("d-none");
- this._setBadgeToLevel(result.score, result.crackTimes.onlineNoThrottlingXPerSecond.display);
+ this._setBadgeToLevel(result.score);
this.warningTarget.innerHTML = result.feedback.warning;
}
- _setBadgeToLevel(level, time = null) {
+ _setBadgeToLevel(level) {
let text, classes;
switch (level) {
@@ -131,11 +118,5 @@ export default class extends Controller {
//Re-add the classes
this.badgeTarget.classList.add("badge");
this.badgeTarget.classList.add(...classes.split(" "));
-
- if (time) {
- this.badgeTarget.setAttribute("title", trans("user.password_strength.crack_time", {"%time%": time}));
- } else {
- this.badgeTarget.removeAttribute("title");
- }
}
}
diff --git a/assets/controllers/pages/reelCalculator_controller.js b/assets/controllers/pages/reelCalculator_controller.js
index e0b2c4ba..a134bf9b 100644
--- a/assets/controllers/pages/reelCalculator_controller.js
+++ b/assets/controllers/pages/reelCalculator_controller.js
@@ -18,7 +18,7 @@
*/
import {Controller} from "@hotwired/stimulus";
-import {AlertSwal} from "../../helpers/swal";
+import * as bootbox from "bootbox";
export default class extends Controller {
@@ -35,12 +35,12 @@ export default class extends Controller {
const part_distance = document.getElementById('reel_part_distance').value;
if (dia_inner == "" || dia_outer == "" || tape_thickness == "") {
- AlertSwal.fire({title: this.errorMissingValuesValue});
+ bootbox.alert(this.errorMissingValuesValue);
return;
}
if (dia_outer**dia_outer < dia_inner**dia_inner) {
- AlertSwal.fire({title: this.errorOuterGreaterInnerValue});
+ bootbox.alert(this.errorOuterGreaterInnerValue);
return;
}
@@ -61,12 +61,12 @@ export default class extends Controller {
return;
}
- const parts_per_meter = 1 / (part_distance / 1000);
+ var parts_per_meter = 1 / (part_distance / 1000);
document.getElementById('result_parts_per_meter').textContent = parts_per_meter.toFixed(2) + ' 1/m';
- const parts_amount = (length / 1000) * parts_per_meter;
+ var parts_amount = (length/1000) * parts_per_meter;
- document.getElementById('result_amount').textContent = Math.floor(parts_amount).toString();
+ document.getElementById('result_amount').textContent = Math.floor(parts_amount);
}
-}
+}
\ No newline at end of file
diff --git a/assets/themes/brite.js b/assets/css/components/bootbox_extensions.css
similarity index 58%
rename from assets/themes/brite.js
rename to assets/css/components/bootbox_extensions.css
index 41b82e93..42bbd78d 100644
--- a/assets/themes/brite.js
+++ b/assets/css/components/bootbox_extensions.css
@@ -1,7 +1,7 @@
/*
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
*
- * Copyright (C) 2019 - 2026 Jan Böhmer (https://github.com/jbtronics)
+ * Copyright (C) 2019 - 2022 Jan Böhmer (https://github.com/jbtronics)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
@@ -17,4 +17,30 @@
* along with this program. If not, see .
*/
-import "bootswatch/dist/brite/bootstrap.css";
+.modal-body > .bootbox-close-button {
+ position: absolute;
+ top: 0;
+ right: 0;
+ padding: 0.5rem 0.75rem;
+ z-index: 1;
+}
+.modal .bootbox-close-button {
+ font-weight: 100;
+}
+
+button.bootbox-close-button {
+ padding: 0;
+ background-color: transparent;
+ border: 0;
+ -webkit-appearance: none;
+}
+
+.bootbox-close-button {
+ /* float: right; */
+ font-size: 1.40625rem;
+ font-weight: 600;
+ line-height: 1;
+ color: #000;
+ text-shadow: none;
+ opacity: .5;
+}
\ No newline at end of file
diff --git a/assets/css/components/swal.css b/assets/css/components/swal.css
deleted file mode 100644
index 4c2302a9..00000000
--- a/assets/css/components/swal.css
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
- *
- * Copyright (C) 2019 - 2026 Jan Böhmer (https://github.com/jbtronics)
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published
- * by the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see .
- */
-
-/**
- * Respect the dark mode of Bootstrap 5 set via data-bs-theme="dark" on the element. This is done by overriding the CSS variables of the bootstrap-5 theme of SweetAlert2.
- */
-
-html[data-bs-theme="dark"] [data-swal2-theme='bootstrap-5'] {
- /* POPUP */
- --swal2-background: #212529;
- --swal2-color: #fff;
- --swal2-border: 1px solid #495057;
-
- /* INPUT */
- --swal2-input-background: #2b3035;
- --swal2-input-border: 1px solid #495057;
- --swal2-input-focus-border: 1px solid #86b7fe;
- --swal2-input-focus-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.075), 0 0 0 0.25rem rgba(13, 110, 253, 0.25);
-
- /* VALIDATION MESSAGE */
- --swal2-validation-message-background: #2c0b0e;
- --swal2-validation-message-color: #ea868f;
-
- /* FOOTER */
- --swal2-footer-border-color: #495057;
- --swal2-footer-background: #343a40;
- --swal2-footer-color: #adb5bd;
-
- /* CLOSE BUTTON */
- --swal2-close-button-color: #fff;
-
- /* TOASTS */
- --swal2-toast-border: 1px solid #495057;
-}
diff --git a/assets/helpers/swal.js b/assets/helpers/swal.js
deleted file mode 100644
index e370a9ed..00000000
--- a/assets/helpers/swal.js
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
- *
- * Copyright (C) 2019 - 2022 Jan Böhmer (https://github.com/jbtronics)
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published
- * by the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see .
- */
-
-import Swal from 'sweetalert2';
-import 'sweetalert2/themes/bootstrap-5.css';
-import '../css/components/swal.css'
-import { trans } from '../translator';
-
-const BaseSwal = Swal.mixin({
- position: "top",
- theme: "bootstrap-5",
- confirmButtonText: trans('dialog.btn.ok'),
- cancelButtonText: trans('dialog.btn.cancel'),
- denyButtonText: trans('dialog.btn.deny'),
-});
-
-const ConfirmSwal = BaseSwal.mixin({
- showCancelButton: true,
- showCloseButton: true,
- icon: "warning",
-});
-
-const AlertSwal = BaseSwal.mixin({
- showCloseButton: true,
- icon: "info",
-});
-
-export { ConfirmSwal, AlertSwal, BaseSwal, BaseSwal as default,};
diff --git a/assets/js/app.js b/assets/js/app.js
index 355fe919..4dd39581 100644
--- a/assets/js/app.js
+++ b/assets/js/app.js
@@ -30,21 +30,21 @@ import '../css/app/images.css';
// start the Stimulus application
import '../stimulus_bootstrap';
-import $ from 'jquery';
+// Need jQuery? Install it with "yarn add jquery", then uncomment to require it.
+const $ = require('jquery');
//Only include javascript
import '@fortawesome/fontawesome-free/css/all.css'
-import 'bootstrap';
+require('bootstrap');
import "./error_handler";
import "./tab_remember";
import "./register_events";
import "./tristate_checkboxes";
-// Expose jQuery globally so legacy plugins and Bootstrap's jQuery integration
-// can find it on window at runtime.
-global.$ = global.jQuery = $;
+//Define jquery globally
+global.$ = global.jQuery = require("jquery");
//Use the local WASM file for the ZXing library
import {
diff --git a/assets/js/error_handler.js b/assets/js/error_handler.js
index 67695fb9..7f047af9 100644
--- a/assets/js/error_handler.js
+++ b/assets/js/error_handler.js
@@ -17,7 +17,7 @@
* along with this program. If not, see .
*/
-import Swal from "../helpers/swal";
+import * as bootbox from "bootbox";
/**
* If this class is imported the user is shown an error dialog if he calls an page via Turbo and an error is responded.
@@ -40,6 +40,21 @@ class ErrorHandlerHelper {
_showAlert(statusText, statusCode, location, responseHTML)
{
const httpStatusToText = {
+ '200': 'OK',
+ '201': 'Created',
+ '202': 'Accepted',
+ '203': 'Non-Authoritative Information',
+ '204': 'No Content',
+ '205': 'Reset Content',
+ '206': 'Partial Content',
+ '300': 'Multiple Choices',
+ '301': 'Moved Permanently',
+ '302': 'Found',
+ '303': 'See Other',
+ '304': 'Not Modified',
+ '305': 'Use Proxy',
+ '306': 'Unused',
+ '307': 'Temporary Redirect',
'400': 'Bad Request',
'401': 'Unauthorized',
'402': 'Payment Required',
@@ -68,67 +83,49 @@ class ErrorHandlerHelper {
'505': 'HTTP Version Not Supported',
};
- const userFriendlyMessages = {
- '400': 'The request was invalid or malformed.',
- '401': 'You need to log in to access this resource.',
- '403': 'You don\'t have permission to access this resource.',
- '404': 'The requested page or resource could not be found.',
- '408': 'The request timed out. Please check your connection and try again.',
- '409': 'There was a conflict with the current state of the resource.',
- '429': 'Too many requests sent. Please wait a moment and try again.',
- '500': 'An internal server error occurred. This is not your fault.',
- '502': 'The server received an invalid response from an upstream service.',
- '503': 'The service is temporarily unavailable. Please try again later.',
- '504': 'The server did not respond in time. Please try again later.',
- };
-
+ //If the statusText is empty, we use the status code as text
if (!statusText) {
- statusText = httpStatusToText[String(statusCode)] ?? 'Unknown Error';
+ statusText = httpStatusToText[statusCode];
}
- const title = `${statusText} (HTTP ${statusCode}) `;
- const friendlyMsg = userFriendlyMessages[String(statusCode)]
- ?? 'An unexpected error occurred. Please try again or contact the administrator.';
+ //Create error text
+ const title = statusText + ' (Status ' + statusCode + ')';
- const short_location = location.length > 80
- ? location.substring(0, 80) + '…'
- : location;
+ let trimString = function (string, length) {
+ return string.length > length ?
+ string.substring(0, length) + '...' :
+ string;
+ };
- const msg = `
-
${friendlyMsg}
- If this error keeps happening, please contact your administrator.
-
- Technical details
-
-
-
-
`;
+ const short_location = trimString(location, 50);
- const footer = `Error while loading: ${short_location} `;
+ const alert = bootbox.alert(
+ {
+ size: 'large',
+ message: function() {
+ let url = location;
+ let msg = `Error calling ${short_location} . `;
+ msg += 'Try to reload the page or contact the administrator if this error persists. ';
- Swal.fire({
- icon: 'error',
- title: title,
- html: msg,
- footer: footer,
- width: '90%',
- confirmButtonText: ' Reload page',
- showCancelButton: true,
- cancelButtonText: 'Close',
- showCloseButton: true,
- reverseButtons: true,
- didOpen: () => {
- const dstFrame = document.getElementById('error-iframe');
- //@ts-ignore
- const dstDoc = dstFrame.contentDocument || dstFrame.contentWindow.document;
- dstDoc.write(responseHTML);
- dstDoc.close();
- },
- }).then((result) => {
- document.getElementById('content').classList.remove('loading-content');
- if (result.isConfirmed) {
- window.location.reload();
- }
+ msg += '' + 'View details' + " ";
+ msg += "
";
+
+ return msg;
+ },
+ title: title,
+ callback: function () {
+ //Remove blur
+ $('#content').removeClass('loading-content');
+ }
+
+ });
+
+ alert.init(function (){
+ var dstFrame = document.getElementById('error-iframe');
+ //@ts-ignore
+ var dstDoc = dstFrame.contentDocument || dstFrame.contentWindow.document;
+ dstDoc.write(responseHTML)
+ dstDoc.close();
});
}
@@ -174,4 +171,4 @@ class ErrorHandlerHelper {
}
}
-export default new ErrorHandlerHelper();
+export default new ErrorHandlerHelper();
\ No newline at end of file
diff --git a/assets/js/lib/dataTables.select.mjs b/assets/js/lib/dataTables.select.mjs
new file mode 100644
index 00000000..bba97692
--- /dev/null
+++ b/assets/js/lib/dataTables.select.mjs
@@ -0,0 +1,1538 @@
+/*********************
+ * This is the fixed version of the select extension for DataTables with the fix for the issue with the select extension
+ * (https://github.com/DataTables/Select/issues/51)
+ * We use this instead of the yarn version until the PR (https://github.com/DataTables/Select/pull/52) is merged and released
+ * /*******************/
+
+
+/*! Select for DataTables 2.0.0
+ * © SpryMedia Ltd - datatables.net/license/mit
+ */
+
+import jQuery from 'jquery';
+import DataTable from 'datatables.net';
+
+// Allow reassignment of the $ variable
+let $ = jQuery;
+
+
+// Version information for debugger
+DataTable.select = {};
+
+DataTable.select.version = '2.0.0';
+
+DataTable.select.init = function (dt) {
+ var ctx = dt.settings()[0];
+
+ if (!DataTable.versionCheck('2')) {
+ throw 'Warning: Select requires DataTables 2 or newer';
+ }
+
+ if (ctx._select) {
+ return;
+ }
+
+ var savedSelected = dt.state.loaded();
+
+ var selectAndSave = function (e, settings, data) {
+ if (data === null || data.select === undefined) {
+ return;
+ }
+
+ // Clear any currently selected rows, before restoring state
+ // None will be selected on first initialisation
+ if (dt.rows({ selected: true }).any()) {
+ dt.rows().deselect();
+ }
+ if (data.select.rows !== undefined) {
+ dt.rows(data.select.rows).select();
+ }
+
+ if (dt.columns({ selected: true }).any()) {
+ dt.columns().deselect();
+ }
+ if (data.select.columns !== undefined) {
+ dt.columns(data.select.columns).select();
+ }
+
+ if (dt.cells({ selected: true }).any()) {
+ dt.cells().deselect();
+ }
+ if (data.select.cells !== undefined) {
+ for (var i = 0; i < data.select.cells.length; i++) {
+ dt.cell(data.select.cells[i].row, data.select.cells[i].column).select();
+ }
+ }
+
+ dt.state.save();
+ };
+
+ dt.on('stateSaveParams', function (e, settings, data) {
+ data.select = {};
+ data.select.rows = dt.rows({ selected: true }).ids(true).toArray();
+ data.select.columns = dt.columns({ selected: true })[0];
+ data.select.cells = dt.cells({ selected: true })[0].map(function (coords) {
+ return { row: dt.row(coords.row).id(true), column: coords.column };
+ });
+ })
+ .on('stateLoadParams', selectAndSave)
+ .one('init', function () {
+ selectAndSave(undefined, undefined, savedSelected);
+ });
+
+ var init = ctx.oInit.select;
+ var defaults = DataTable.defaults.select;
+ var opts = init === undefined ? defaults : init;
+
+ // Set defaults
+ var items = 'row';
+ var style = 'api';
+ var blurable = false;
+ var toggleable = true;
+ var info = true;
+ var selector = 'td, th';
+ var className = 'selected';
+ var headerCheckbox = true;
+ var setStyle = false;
+
+ ctx._select = {
+ infoEls: []
+ };
+
+ // Initialisation customisations
+ if (opts === true) {
+ style = 'os';
+ setStyle = true;
+ }
+ else if (typeof opts === 'string') {
+ style = opts;
+ setStyle = true;
+ }
+ else if ($.isPlainObject(opts)) {
+ if (opts.blurable !== undefined) {
+ blurable = opts.blurable;
+ }
+
+ if (opts.toggleable !== undefined) {
+ toggleable = opts.toggleable;
+ }
+
+ if (opts.info !== undefined) {
+ info = opts.info;
+ }
+
+ if (opts.items !== undefined) {
+ items = opts.items;
+ }
+
+ if (opts.style !== undefined) {
+ style = opts.style;
+ setStyle = true;
+ }
+ else {
+ style = 'os';
+ setStyle = true;
+ }
+
+ if (opts.selector !== undefined) {
+ selector = opts.selector;
+ }
+
+ if (opts.className !== undefined) {
+ className = opts.className;
+ }
+
+ if (opts.headerCheckbox !== undefined) {
+ headerCheckbox = opts.headerCheckbox;
+ }
+ }
+
+ dt.select.selector(selector);
+ dt.select.items(items);
+ dt.select.style(style);
+ dt.select.blurable(blurable);
+ dt.select.toggleable(toggleable);
+ dt.select.info(info);
+ ctx._select.className = className;
+
+ // If the init options haven't enabled select, but there is a selectable
+ // class name, then enable
+ if (!setStyle && $(dt.table().node()).hasClass('selectable')) {
+ dt.select.style('os');
+ }
+
+ // Insert a checkbox into the header if needed - might need to wait
+ // for init complete, or it might already be done
+ if (headerCheckbox) {
+ initCheckboxHeader(dt);
+
+ dt.on('init', function () {
+ initCheckboxHeader(dt);
+ });
+ }
+};
+
+/*
+
+Select is a collection of API methods, event handlers, event emitters and
+buttons (for the `Buttons` extension) for DataTables. It provides the following
+features, with an overview of how they are implemented:
+
+## Selection of rows, columns and cells. Whether an item is selected or not is
+ stored in:
+
+* rows: a `_select_selected` property which contains a boolean value of the
+ DataTables' `aoData` object for each row
+* columns: a `_select_selected` property which contains a boolean value of the
+ DataTables' `aoColumns` object for each column
+* cells: a `_selected_cells` property which contains an array of boolean values
+ of the `aoData` object for each row. The array is the same length as the
+ columns array, with each element of it representing a cell.
+
+This method of using boolean flags allows Select to operate when nodes have not
+been created for rows / cells (DataTables' defer rendering feature).
+
+## API methods
+
+A range of API methods are available for triggering selection and de-selection
+of rows. Methods are also available to configure the selection events that can
+be triggered by an end user (such as which items are to be selected). To a large
+extent, these of API methods *is* Select. It is basically a collection of helper
+functions that can be used to select items in a DataTable.
+
+Configuration of select is held in the object `_select` which is attached to the
+DataTables settings object on initialisation. Select being available on a table
+is not optional when Select is loaded, but its default is for selection only to
+be available via the API - so the end user wouldn't be able to select rows
+without additional configuration.
+
+The `_select` object contains the following properties:
+
+```
+{
+ items:string - Can be `rows`, `columns` or `cells`. Defines what item
+ will be selected if the user is allowed to activate row
+ selection using the mouse.
+ style:string - Can be `none`, `single`, `multi` or `os`. Defines the
+ interaction style when selecting items
+ blurable:boolean - If row selection can be cleared by clicking outside of
+ the table
+ toggleable:boolean - If row selection can be cancelled by repeated clicking
+ on the row
+ info:boolean - If the selection summary should be shown in the table
+ information elements
+ infoEls:element[] - List of HTML elements with info elements for a table
+}
+```
+
+In addition to the API methods, Select also extends the DataTables selector
+options for rows, columns and cells adding a `selected` option to the selector
+options object, allowing the developer to select only selected items or
+unselected items.
+
+## Mouse selection of items
+
+Clicking on items can be used to select items. This is done by a simple event
+handler that will select the items using the API methods.
+
+ */
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Local functions
+ */
+
+/**
+ * Add one or more cells to the selection when shift clicking in OS selection
+ * style cell selection.
+ *
+ * Cell range is more complicated than row and column as we want to select
+ * in the visible grid rather than by index in sequence. For example, if you
+ * click first in cell 1-1 and then shift click in 2-2 - cells 1-2 and 2-1
+ * should also be selected (and not 1-3, 1-4. etc)
+ *
+ * @param {DataTable.Api} dt DataTable
+ * @param {object} idx Cell index to select to
+ * @param {object} last Cell index to select from
+ * @private
+ */
+function cellRange(dt, idx, last) {
+ var indexes;
+ var columnIndexes;
+ var rowIndexes;
+ var selectColumns = function (start, end) {
+ if (start > end) {
+ var tmp = end;
+ end = start;
+ start = tmp;
+ }
+
+ var record = false;
+ return dt
+ .columns(':visible')
+ .indexes()
+ .filter(function (i) {
+ if (i === start) {
+ record = true;
+ }
+
+ if (i === end) {
+ // not else if, as start might === end
+ record = false;
+ return true;
+ }
+
+ return record;
+ });
+ };
+
+ var selectRows = function (start, end) {
+ var indexes = dt.rows({ search: 'applied' }).indexes();
+
+ // Which comes first - might need to swap
+ if (indexes.indexOf(start) > indexes.indexOf(end)) {
+ var tmp = end;
+ end = start;
+ start = tmp;
+ }
+
+ var record = false;
+ return indexes.filter(function (i) {
+ if (i === start) {
+ record = true;
+ }
+
+ if (i === end) {
+ record = false;
+ return true;
+ }
+
+ return record;
+ });
+ };
+
+ if (!dt.cells({ selected: true }).any() && !last) {
+ // select from the top left cell to this one
+ columnIndexes = selectColumns(0, idx.column);
+ rowIndexes = selectRows(0, idx.row);
+ }
+ else {
+ // Get column indexes between old and new
+ columnIndexes = selectColumns(last.column, idx.column);
+ rowIndexes = selectRows(last.row, idx.row);
+ }
+
+ indexes = dt.cells(rowIndexes, columnIndexes).flatten();
+
+ if (!dt.cells(idx, { selected: true }).any()) {
+ // Select range
+ dt.cells(indexes).select();
+ }
+ else {
+ // Deselect range
+ dt.cells(indexes).deselect();
+ }
+}
+
+/**
+ * Disable mouse selection by removing the selectors
+ *
+ * @param {DataTable.Api} dt DataTable to remove events from
+ * @private
+ */
+function disableMouseSelection(dt) {
+ var ctx = dt.settings()[0];
+ var selector = ctx._select.selector;
+
+ $(dt.table().container())
+ .off('mousedown.dtSelect', selector)
+ .off('mouseup.dtSelect', selector)
+ .off('click.dtSelect', selector);
+
+ $('body').off('click.dtSelect' + _safeId(dt.table().node()));
+}
+
+/**
+ * Attach mouse listeners to the table to allow mouse selection of items
+ *
+ * @param {DataTable.Api} dt DataTable to remove events from
+ * @private
+ */
+function enableMouseSelection(dt) {
+ var container = $(dt.table().container());
+ var ctx = dt.settings()[0];
+ var selector = ctx._select.selector;
+ var matchSelection;
+
+ container
+ .on('mousedown.dtSelect', selector, function (e) {
+ // Disallow text selection for shift clicking on the table so multi
+ // element selection doesn't look terrible!
+ if (e.shiftKey || e.metaKey || e.ctrlKey) {
+ container
+ .css('-moz-user-select', 'none')
+ .one('selectstart.dtSelect', selector, function () {
+ return false;
+ });
+ }
+
+ if (window.getSelection) {
+ matchSelection = window.getSelection();
+ }
+ })
+ .on('mouseup.dtSelect', selector, function () {
+ // Allow text selection to occur again, Mozilla style (tested in FF
+ // 35.0.1 - still required)
+ container.css('-moz-user-select', '');
+ })
+ .on('click.dtSelect', selector, function (e) {
+ var items = dt.select.items();
+ var idx;
+
+ // If text was selected (click and drag), then we shouldn't change
+ // the row's selected state
+ if (matchSelection) {
+ var selection = window.getSelection();
+
+ // If the element that contains the selection is not in the table, we can ignore it
+ // This can happen if the developer selects text from the click event
+ if (
+ !selection.anchorNode ||
+ $(selection.anchorNode).closest('table')[0] === dt.table().node()
+ ) {
+ if (selection !== matchSelection) {
+ return;
+ }
+ }
+ }
+
+ var ctx = dt.settings()[0];
+ var container = dt.table().container();
+
+ // Ignore clicks inside a sub-table
+ if ($(e.target).closest('div.dt-container')[0] != container) {
+ return;
+ }
+
+ var cell = dt.cell($(e.target).closest('td, th'));
+
+ // Check the cell actually belongs to the host DataTable (so child
+ // rows, etc, are ignored)
+ if (!cell.any()) {
+ return;
+ }
+
+ var event = $.Event('user-select.dt');
+ eventTrigger(dt, event, [items, cell, e]);
+
+ if (event.isDefaultPrevented()) {
+ return;
+ }
+
+ var cellIndex = cell.index();
+ if (items === 'row') {
+ idx = cellIndex.row;
+ typeSelect(e, dt, ctx, 'row', idx);
+ }
+ else if (items === 'column') {
+ idx = cell.index().column;
+ typeSelect(e, dt, ctx, 'column', idx);
+ }
+ else if (items === 'cell') {
+ idx = cell.index();
+ typeSelect(e, dt, ctx, 'cell', idx);
+ }
+
+ ctx._select_lastCell = cellIndex;
+ });
+
+ // Blurable
+ $('body').on('click.dtSelect' + _safeId(dt.table().node()), function (e) {
+ if (ctx._select.blurable) {
+ // If the click was inside the DataTables container, don't blur
+ if ($(e.target).parents().filter(dt.table().container()).length) {
+ return;
+ }
+
+ // Ignore elements which have been removed from the DOM (i.e. paging
+ // buttons)
+ if ($(e.target).parents('html').length === 0) {
+ return;
+ }
+
+ // Don't blur in Editor form
+ if ($(e.target).parents('div.DTE').length) {
+ return;
+ }
+
+ var event = $.Event('select-blur.dt');
+ eventTrigger(dt, event, [e.target, e]);
+
+ if (event.isDefaultPrevented()) {
+ return;
+ }
+
+ clear(ctx, true);
+ }
+ });
+}
+
+/**
+ * Trigger an event on a DataTable
+ *
+ * @param {DataTable.Api} api DataTable to trigger events on
+ * @param {boolean} selected true if selected, false if deselected
+ * @param {string} type Item type acting on
+ * @param {boolean} any Require that there are values before
+ * triggering
+ * @private
+ */
+function eventTrigger(api, type, args, any) {
+ if (any && !api.flatten().length) {
+ return;
+ }
+
+ if (typeof type === 'string') {
+ type = type + '.dt';
+ }
+
+ args.unshift(api);
+
+ $(api.table().node()).trigger(type, args);
+}
+
+/**
+ * Update the information element of the DataTable showing information about the
+ * items selected. This is done by adding tags to the existing text
+ *
+ * @param {DataTable.Api} api DataTable to update
+ * @private
+ */
+function info(api, node) {
+ if (api.select.style() === 'api' || api.select.info() === false) {
+ return;
+ }
+
+ var rows = api.rows({ selected: true }).flatten().length;
+ var columns = api.columns({ selected: true }).flatten().length;
+ var cells = api.cells({ selected: true }).flatten().length;
+
+ var add = function (el, name, num) {
+ el.append(
+ $(' ').append(
+ api.i18n(
+ 'select.' + name + 's',
+ { _: '%d ' + name + 's selected', 0: '', 1: '1 ' + name + ' selected' },
+ num
+ )
+ )
+ );
+ };
+
+ var el = $(node);
+ var output = $(' ');
+
+ add(output, 'row', rows);
+ add(output, 'column', columns);
+ add(output, 'cell', cells);
+
+ var existing = el.children('span.select-info');
+
+ if (existing.length) {
+ existing.remove();
+ }
+
+ if (output.text() !== '') {
+ el.append(output);
+ }
+}
+
+/**
+ * Add a checkbox to the header for checkbox columns, allowing all rows to
+ * be selected, deselected or just to show the state.
+ *
+ * @param {*} dt API
+ */
+function initCheckboxHeader( dt ) {
+ // Find any checkbox column(s)
+ dt.columns('.dt-select').every(function () {
+ var header = this.header();
+
+ if (! $('input', header).length) {
+ // If no checkbox yet, insert one
+ var input = $(' ')
+ .attr({
+ class: 'dt-select-checkbox',
+ type: 'checkbox',
+ 'aria-label': dt.i18n('select.aria.headerCheckbox') || 'Select all rows'
+ })
+ .appendTo(header)
+ .on('change', function () {
+ if (this.checked) {
+ dt.rows({search: 'applied'}).select();
+ }
+ else {
+ dt.rows({selected: true}).deselect();
+ }
+ })
+ .on('click', function (e) {
+ e.stopPropagation();
+ });
+
+ // Update the header checkbox's state when the selection in the
+ // table changes
+ dt.on('draw select deselect', function (e, pass, type) {
+ if (type === 'row' || ! type) {
+ var count = dt.rows({selected: true}).count();
+ var search = dt.rows({search: 'applied', selected: true}).count();
+ var available = dt.rows({search: 'applied'}).count();
+
+ if (search && search <= count && search === available) {
+ input
+ .prop('checked', true)
+ .prop('indeterminate', false);
+ }
+ else if (search === 0 && count === 0) {
+ input
+ .prop('checked', false)
+ .prop('indeterminate', false);
+ }
+ else {
+ input
+ .prop('checked', false)
+ .prop('indeterminate', true);
+ }
+ }
+ });
+ }
+ });
+}
+
+/**
+ * Initialisation of a new table. Attach event handlers and callbacks to allow
+ * Select to operate correctly.
+ *
+ * This will occur _after_ the initial DataTables initialisation, although
+ * before Ajax data is rendered, if there is ajax data
+ *
+ * @param {DataTable.settings} ctx Settings object to operate on
+ * @private
+ */
+function init(ctx) {
+ var api = new DataTable.Api(ctx);
+ ctx._select_init = true;
+
+ // Row callback so that classes can be added to rows and cells if the item
+ // was selected before the element was created. This will happen with the
+ // `deferRender` option enabled.
+ //
+ // This method of attaching to `aoRowCreatedCallback` is a hack until
+ // DataTables has proper events for row manipulation If you are reviewing
+ // this code to create your own plug-ins, please do not do this!
+ ctx.aoRowCreatedCallback.push(function (row, data, index) {
+ var i, ien;
+ var d = ctx.aoData[index];
+
+ // Row
+ if (d._select_selected) {
+ $(row).addClass(ctx._select.className);
+ }
+
+ // Cells and columns - if separated out, we would need to do two
+ // loops, so it makes sense to combine them into a single one
+ for (i = 0, ien = ctx.aoColumns.length; i < ien; i++) {
+ if (
+ ctx.aoColumns[i]._select_selected ||
+ (d._selected_cells && d._selected_cells[i])
+ ) {
+ $(d.anCells[i]).addClass(ctx._select.className);
+ }
+ }
+ }
+ );
+
+ // On Ajax reload we want to reselect all rows which are currently selected,
+ // if there is an rowId (i.e. a unique value to identify each row with)
+ api.on('preXhr.dt.dtSelect', function (e, settings) {
+ if (settings !== api.settings()[0]) {
+ // Not triggered by our DataTable!
+ return;
+ }
+
+ // note that column selection doesn't need to be cached and then
+ // reselected, as they are already selected
+ var rows = api
+ .rows({ selected: true })
+ .ids(true)
+ .filter(function (d) {
+ return d !== undefined;
+ });
+
+ var cells = api
+ .cells({ selected: true })
+ .eq(0)
+ .map(function (cellIdx) {
+ var id = api.row(cellIdx.row).id(true);
+ return id ? { row: id, column: cellIdx.column } : undefined;
+ })
+ .filter(function (d) {
+ return d !== undefined;
+ });
+
+ // On the next draw, reselect the currently selected items
+ api.one('draw.dt.dtSelect', function () {
+ api.rows(rows).select();
+
+ // `cells` is not a cell index selector, so it needs a loop
+ if (cells.any()) {
+ cells.each(function (id) {
+ api.cells(id.row, id.column).select();
+ });
+ }
+ });
+ });
+
+ // Update the table information element with selected item summary
+ api.on('info.dt', function (e, ctx, node) {
+ // Store the info node for updating on select / deselect
+ if (!ctx._select.infoEls.includes(node)) {
+ ctx._select.infoEls.push(node);
+ }
+
+ info(api, node);
+ });
+
+ api.on('select.dtSelect.dt deselect.dtSelect.dt', function () {
+ ctx._select.infoEls.forEach(function (el) {
+ info(api, el);
+ });
+
+ api.state.save();
+ });
+
+ // Clean up and release
+ api.on('destroy.dtSelect', function () {
+ // Remove class directly rather than calling deselect - which would trigger events
+ $(api.rows({ selected: true }).nodes()).removeClass(api.settings()[0]._select.className);
+
+ disableMouseSelection(api);
+ api.off('.dtSelect');
+ $('body').off('.dtSelect' + _safeId(api.table().node()));
+ });
+}
+
+/**
+ * Add one or more items (rows or columns) to the selection when shift clicking
+ * in OS selection style
+ *
+ * @param {DataTable.Api} dt DataTable
+ * @param {string} type Row or column range selector
+ * @param {object} idx Item index to select to
+ * @param {object} last Item index to select from
+ * @private
+ */
+function rowColumnRange(dt, type, idx, last) {
+ // Add a range of rows from the last selected row to this one
+ var indexes = dt[type + 's']({ search: 'applied' }).indexes();
+ var idx1 = indexes.indexOf(last);
+ var idx2 = indexes.indexOf(idx);
+
+ if (!dt[type + 's']({ selected: true }).any() && idx1 === -1) {
+ // select from top to here - slightly odd, but both Windows and Mac OS
+ // do this
+ indexes.splice(indexes.indexOf(idx) + 1, indexes.length);
+ }
+ else {
+ // reverse so we can shift click 'up' as well as down
+ if (idx1 > idx2) {
+ var tmp = idx2;
+ idx2 = idx1;
+ idx1 = tmp;
+ }
+
+ indexes.splice(idx2 + 1, indexes.length);
+ indexes.splice(0, idx1);
+ }
+
+ if (!dt[type](idx, { selected: true }).any()) {
+ // Select range
+ dt[type + 's'](indexes).select();
+ }
+ else {
+ // Deselect range - need to keep the clicked on row selected
+ indexes.splice(indexes.indexOf(idx), 1);
+ dt[type + 's'](indexes).deselect();
+ }
+}
+
+/**
+ * Clear all selected items
+ *
+ * @param {DataTable.settings} ctx Settings object of the host DataTable
+ * @param {boolean} [force=false] Force the de-selection to happen, regardless
+ * of selection style
+ * @private
+ */
+function clear(ctx, force) {
+ if (force || ctx._select.style === 'single') {
+ var api = new DataTable.Api(ctx);
+
+ api.rows({ selected: true }).deselect();
+ api.columns({ selected: true }).deselect();
+ api.cells({ selected: true }).deselect();
+ }
+}
+
+/**
+ * Select items based on the current configuration for style and items.
+ *
+ * @param {object} e Mouse event object
+ * @param {DataTables.Api} dt DataTable
+ * @param {DataTable.settings} ctx Settings object of the host DataTable
+ * @param {string} type Items to select
+ * @param {int|object} idx Index of the item to select
+ * @private
+ */
+function typeSelect(e, dt, ctx, type, idx) {
+ var style = dt.select.style();
+ var toggleable = dt.select.toggleable();
+ var isSelected = dt[type](idx, { selected: true }).any();
+
+ if (isSelected && !toggleable) {
+ return;
+ }
+
+ if (style === 'os') {
+ if (e.ctrlKey || e.metaKey) {
+ // Add or remove from the selection
+ dt[type](idx).select(!isSelected);
+ }
+ else if (e.shiftKey) {
+ if (type === 'cell') {
+ cellRange(dt, idx, ctx._select_lastCell || null);
+ }
+ else {
+ rowColumnRange(
+ dt,
+ type,
+ idx,
+ ctx._select_lastCell ? ctx._select_lastCell[type] : null
+ );
+ }
+ }
+ else {
+ // No cmd or shift click - deselect if selected, or select
+ // this row only
+ var selected = dt[type + 's']({ selected: true });
+
+ if (isSelected && selected.flatten().length === 1) {
+ dt[type](idx).deselect();
+ }
+ else {
+ selected.deselect();
+ dt[type](idx).select();
+ }
+ }
+ }
+ else if (style == 'multi+shift') {
+ if (e.shiftKey) {
+ if (type === 'cell') {
+ cellRange(dt, idx, ctx._select_lastCell || null);
+ }
+ else {
+ rowColumnRange(
+ dt,
+ type,
+ idx,
+ ctx._select_lastCell ? ctx._select_lastCell[type] : null
+ );
+ }
+ }
+ else {
+ dt[type](idx).select(!isSelected);
+ }
+ }
+ else {
+ dt[type](idx).select(!isSelected);
+ }
+}
+
+function _safeId(node) {
+ return node.id.replace(/[^a-zA-Z0-9\-\_]/g, '-');
+}
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * DataTables selectors
+ */
+
+// row and column are basically identical just assigned to different properties
+// and checking a different array, so we can dynamically create the functions to
+// reduce the code size
+$.each(
+ [
+ { type: 'row', prop: 'aoData' },
+ { type: 'column', prop: 'aoColumns' }
+ ],
+ function (i, o) {
+ DataTable.ext.selector[o.type].push(function (settings, opts, indexes) {
+ var selected = opts.selected;
+ var data;
+ var out = [];
+
+ if (selected !== true && selected !== false) {
+ return indexes;
+ }
+
+ for (var i = 0, ien = indexes.length; i < ien; i++) {
+ data = settings[o.prop][indexes[i]];
+
+ if (
+ data && (
+ (selected === true && data._select_selected === true) ||
+ (selected === false && !data._select_selected)
+ )
+ ) {
+ out.push(indexes[i]);
+ }
+ }
+
+ return out;
+ });
+ }
+);
+
+DataTable.ext.selector.cell.push(function (settings, opts, cells) {
+ var selected = opts.selected;
+ var rowData;
+ var out = [];
+
+ if (selected === undefined) {
+ return cells;
+ }
+
+ for (var i = 0, ien = cells.length; i < ien; i++) {
+ rowData = settings.aoData[cells[i].row];
+
+ if (
+ rowData && (
+ (selected === true &&
+ rowData._selected_cells &&
+ rowData._selected_cells[cells[i].column] === true) ||
+ (selected === false &&
+ (!rowData._selected_cells || !rowData._selected_cells[cells[i].column]))
+ )
+ ) {
+ out.push(cells[i]);
+ }
+ }
+
+ return out;
+});
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * DataTables API
+ *
+ * For complete documentation, please refer to the docs/api directory or the
+ * DataTables site
+ */
+
+// Local variables to improve compression
+var apiRegister = DataTable.Api.register;
+var apiRegisterPlural = DataTable.Api.registerPlural;
+
+apiRegister('select()', function () {
+ return this.iterator('table', function (ctx) {
+ DataTable.select.init(new DataTable.Api(ctx));
+ });
+});
+
+apiRegister('select.blurable()', function (flag) {
+ if (flag === undefined) {
+ return this.context[0]._select.blurable;
+ }
+
+ return this.iterator('table', function (ctx) {
+ ctx._select.blurable = flag;
+ });
+});
+
+apiRegister('select.toggleable()', function (flag) {
+ if (flag === undefined) {
+ return this.context[0]._select.toggleable;
+ }
+
+ return this.iterator('table', function (ctx) {
+ ctx._select.toggleable = flag;
+ });
+});
+
+apiRegister('select.info()', function (flag) {
+ if (flag === undefined) {
+ return this.context[0]._select.info;
+ }
+
+ return this.iterator('table', function (ctx) {
+ ctx._select.info = flag;
+ });
+});
+
+apiRegister('select.items()', function (items) {
+ if (items === undefined) {
+ return this.context[0]._select.items;
+ }
+
+ return this.iterator('table', function (ctx) {
+ ctx._select.items = items;
+
+ eventTrigger(new DataTable.Api(ctx), 'selectItems', [items]);
+ });
+});
+
+// Takes effect from the _next_ selection. None disables future selection, but
+// does not clear the current selection. Use the `deselect` methods for that
+apiRegister('select.style()', function (style) {
+ if (style === undefined) {
+ return this.context[0]._select.style;
+ }
+
+ return this.iterator('table', function (ctx) {
+ if (!ctx._select) {
+ DataTable.select.init(new DataTable.Api(ctx));
+ }
+
+ if (!ctx._select_init) {
+ init(ctx);
+ }
+
+ ctx._select.style = style;
+
+ // Add / remove mouse event handlers. They aren't required when only
+ // API selection is available
+ var dt = new DataTable.Api(ctx);
+ disableMouseSelection(dt);
+
+ if (style !== 'api') {
+ enableMouseSelection(dt);
+ }
+
+ eventTrigger(new DataTable.Api(ctx), 'selectStyle', [style]);
+ });
+});
+
+apiRegister('select.selector()', function (selector) {
+ if (selector === undefined) {
+ return this.context[0]._select.selector;
+ }
+
+ return this.iterator('table', function (ctx) {
+ disableMouseSelection(new DataTable.Api(ctx));
+
+ ctx._select.selector = selector;
+
+ if (ctx._select.style !== 'api') {
+ enableMouseSelection(new DataTable.Api(ctx));
+ }
+ });
+});
+
+apiRegister('select.last()', function (set) {
+ let ctx = this.context[0];
+
+ if (set) {
+ ctx._select_lastCell = set;
+ return this;
+ }
+
+ return ctx._select_lastCell;
+});
+
+apiRegisterPlural('rows().select()', 'row().select()', function (select) {
+ var api = this;
+
+ if (select === false) {
+ return this.deselect();
+ }
+
+ this.iterator('row', function (ctx, idx) {
+ clear(ctx);
+
+ // There is a good amount of knowledge of DataTables internals in
+ // this function. It _could_ be done without that, but it would hurt
+ // performance (or DT would need new APIs for this work)
+ var dtData = ctx.aoData[idx];
+ var dtColumns = ctx.aoColumns;
+
+ $(dtData.nTr).addClass(ctx._select.className);
+ dtData._select_selected = true;
+
+ for (var i=0 ; i 0);
+ });
+
+ this.disable();
+ },
+ destroy: function (dt, node, config) {
+ dt.off(config._eventNamespace);
+ }
+ },
+ showSelected: {
+ text: i18n('showSelected', 'Show only selected'),
+ className: 'buttons-show-selected',
+ action: function (e, dt) {
+ if (dt.search.fixed('dt-select')) {
+ // Remove existing function
+ dt.search.fixed('dt-select', null);
+
+ this.active(false);
+ }
+ else {
+ // Use a fixed filtering function to match on selected rows
+ // This needs to reference the internal aoData since that is
+ // where Select stores its reference for the selected state
+ var dataSrc = dt.settings()[0].aoData;
+
+ dt.search.fixed('dt-select', function (text, data, idx) {
+ // _select_selected is set by Select on the data object for the row
+ return dataSrc[idx]._select_selected;
+ });
+
+ this.active(true);
+ }
+
+ dt.draw();
+ }
+ }
+});
+
+$.each(['Row', 'Column', 'Cell'], function (i, item) {
+ var lc = item.toLowerCase();
+
+ DataTable.ext.buttons['select' + item + 's'] = {
+ text: i18n('select' + item + 's', 'Select ' + lc + 's'),
+ className: 'buttons-select-' + lc + 's',
+ action: function () {
+ this.select.items(lc);
+ },
+ init: function (dt) {
+ var that = this;
+
+ dt.on('selectItems.dt.DT', function (e, ctx, items) {
+ that.active(items === lc);
+ });
+ }
+ };
+});
+
+DataTable.type('select-checkbox', {
+ className: 'dt-select',
+ detect: function (data) {
+ // Rendering function will tell us if it is a checkbox type
+ return data === 'select-checkbox' ? data : false;
+ },
+ order: {
+ pre: function (d) {
+ return d === 'X' ? -1 : 0;
+ }
+ }
+});
+
+$.extend(true, DataTable.defaults.oLanguage, {
+ select: {
+ aria: {
+ rowCheckbox: 'Select row'
+ }
+ }
+});
+
+DataTable.render.select = function (valueProp, nameProp) {
+ var valueFn = valueProp ? DataTable.util.get(valueProp) : null;
+ var nameFn = nameProp ? DataTable.util.get(nameProp) : null;
+
+ return function (data, type, row, meta) {
+ var dtRow = meta.settings.aoData[meta.row];
+ var selected = dtRow._select_selected;
+ var ariaLabel = meta.settings.oLanguage.select.aria.rowCheckbox;
+
+ if (type === 'display') {
+ return $(' ')
+ .attr({
+ 'aria-label': ariaLabel,
+ class: 'dt-select-checkbox',
+ name: nameFn ? nameFn(row) : null,
+ type: 'checkbox',
+ value: valueFn ? valueFn(row) : null,
+ checked: selected
+ })[0];
+ }
+ else if (type === 'type') {
+ return 'select-checkbox';
+ }
+ else if (type === 'filter') {
+ return '';
+ }
+
+ return selected ? 'X' : '';
+ }
+}
+
+// Legacy checkbox ordering
+DataTable.ext.order['select-checkbox'] = function (settings, col) {
+ return this.api()
+ .column(col, { order: 'index' })
+ .nodes()
+ .map(function (td) {
+ if (settings._select.items === 'row') {
+ return $(td).parent().hasClass(settings._select.className);
+ }
+ else if (settings._select.items === 'cell') {
+ return $(td).hasClass(settings._select.className);
+ }
+ return false;
+ });
+};
+
+$.fn.DataTable.select = DataTable.select;
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Initialisation
+ */
+
+// DataTables creation - check if select has been defined in the options. Note
+// this required that the table be in the document! If it isn't then something
+// needs to trigger this method unfortunately. The next major release of
+// DataTables will rework the events and address this.
+$(document).on('preInit.dt.dtSelect', function (e, ctx) {
+ if (e.namespace !== 'dt') {
+ return;
+ }
+
+ DataTable.select.init(new DataTable.Api(ctx));
+});
+
+
+export default DataTable;
diff --git a/assets/js/register_events.js b/assets/js/register_events.js
index 1c6ed09b..547742ea 100644
--- a/assets/js/register_events.js
+++ b/assets/js/register_events.js
@@ -19,14 +19,15 @@
'use strict';
-import {Dropdown, Modal, Tooltip} from "bootstrap";
+import {Dropdown} from "bootstrap";
import ClipboardJS from "clipboard";
+import {Modal} from "bootstrap";
class RegisterEventHelper {
constructor() {
this.registerTooltips();
this.configureDropdowns();
-
+
// Only register special character input if enabled in configuration
const keybindingsEnabled = document.body.dataset.keybindingsSpecialCharacters !== 'false';
if (keybindingsEnabled) {
@@ -39,6 +40,8 @@ class RegisterEventHelper {
});
this.registerModalDropRemovalOnFormSubmit();
+
+
}
registerModalDropRemovalOnFormSubmit() {
@@ -80,17 +83,11 @@ class RegisterEventHelper {
registerTooltips() {
const handler = () => {
- document.querySelectorAll('.tooltip').forEach(el => el.remove());
-
+ $(".tooltip").remove();
//Exclude dropdown buttons from tooltips, otherwise we run into endless errors from bootstrap (bootstrap.esm.js:614 Bootstrap doesn't allow more than one instance per element. Bound instance: bs.dropdown.)
- const tooltipSelector = 'a[title], label[title], button[title]:not([data-bs-toggle="dropdown"]), p[title], span[title], h6[title], h3[title], i[title], small[title]';
- document.querySelectorAll(tooltipSelector).forEach(el => {
- const existing = Tooltip.getInstance(el);
- if (existing) {
- existing.dispose();
- }
- new Tooltip(el, {container: 'body', placement: 'auto', boundary: 'window'});
- });
+ $('a[title], label[title], button[title]:not([data-bs-toggle="dropdown"]), p[title], span[title], h6[title], h3[title], i[title], small[title]')
+ //@ts-ignore
+ .tooltip("hide").tooltip({container: "body", placement: "auto", boundary: 'window'});
};
this.registerLoadHandler(handler);
@@ -98,240 +95,242 @@ class RegisterEventHelper {
}
registerSpecialCharInput() {
- const keydownHandler = function(event) {
- let use_special_char = event.altKey;
-
- let greek_char = "";
- if (use_special_char){
- //Use the key property to determine the greek letter (as it is independent of the keyboard layout)
- switch(event.key) {
- //Greek letters
- case "a": //Alpha (lowercase)
- greek_char = "α";
- break;
- case "A": //Alpha (uppercase)
- greek_char = "Α";
- break;
- case "b": //Beta (lowercase)
- greek_char = "β";
- break;
- case "B": //Beta (uppercase)
- greek_char = "Β";
- break;
- case "g": //Gamma (lowercase)
- greek_char = "γ";
- break;
- case "G": //Gamma (uppercase)
- greek_char = "Γ";
- break;
- case "d": //Delta (lowercase)
- greek_char = "δ";
- break;
- case "D": //Delta (uppercase)
- greek_char = "Δ";
- break;
- case "e": //Epsilon (lowercase)
- greek_char = "ε";
- break;
- case "E": //Epsilon (uppercase)
- greek_char = "Ε";
- break;
- case "z": //Zeta (lowercase)
- greek_char = "ζ";
- break;
- case "Z": //Zeta (uppercase)
- greek_char = "Ζ";
- break;
- case "h": //Eta (lowercase)
- greek_char = "η";
- break;
- case "H": //Eta (uppercase)
- greek_char = "Η";
- break;
- case "q": //Theta (lowercase)
- greek_char = "θ";
- break;
- case "Q": //Theta (uppercase)
- greek_char = "Θ";
- break;
- case "i": //Iota (lowercase)
- greek_char = "ι";
- break;
- case "I": //Iota (uppercase)
- greek_char = "Ι";
- break;
- case "k": //Kappa (lowercase)
- greek_char = "κ";
- break;
- case "K": //Kappa (uppercase)
- greek_char = "Κ";
- break;
- case "l": //Lambda (lowercase)
- greek_char = "λ";
- break;
- case "L": //Lambda (uppercase)
- greek_char = "Λ";
- break;
- case "m": //Mu (lowercase)
- greek_char = "μ";
- break;
- case "M": //Mu (uppercase)
- greek_char = "Μ";
- break;
- case "n": //Nu (lowercase)
- greek_char = "ν";
- break;
- case "N": //Nu (uppercase)
- greek_char = "Ν";
- break;
- case "x": //Xi (lowercase)
- greek_char = "ξ";
- break;
- case "X": //Xi (uppercase)
- greek_char = "Ξ";
- break;
- case "o": //Omicron (lowercase)
- greek_char = "ο";
- break;
- case "O": //Omicron (uppercase)
- greek_char = "Ο";
- break;
- case "p": //Pi (lowercase)
- greek_char = "π";
- break;
- case "P": //Pi (uppercase)
- greek_char = "Π";
- break;
- case "r": //Rho (lowercase)
- greek_char = "ρ";
- break;
- case "R": //Rho (uppercase)
- greek_char = "Ρ";
- break;
- case "s": //Sigma (lowercase)
- greek_char = "σ";
- break;
- case "S": //Sigma (uppercase)
- greek_char = "Σ";
- break;
- case "t": //Tau (lowercase)
- greek_char = "τ";
- break;
- case "T": //Tau (uppercase)
- greek_char = "Τ";
- break;
- case "u": //Upsilon (lowercase)
- greek_char = "υ";
- break;
- case "U": //Upsilon (uppercase)
- greek_char = "Υ";
- break;
- case "f": //Phi (lowercase)
- greek_char = "φ";
- break;
- case "F": //Phi (uppercase)
- greek_char = "Φ";
- break;
- case "c": //Chi (lowercase)
- greek_char = "χ";
- break;
- case "C": //Chi (uppercase)
- greek_char = "Χ";
- break;
- case "y": //Psi (lowercase)
- greek_char = "ψ";
- break;
- case "Y": //Psi (uppercase)
- greek_char = "Ψ";
- break;
- case "w": //Omega (lowercase)
- greek_char = "ω";
- break;
- case "W": //Omega (uppercase)
- greek_char = "Ω";
- break;
- }
-
- //Use keycodes for special characters as the shift char on the number keys are layout dependent
- switch (event.keyCode) {
- case 49: //1 key
- //Product symbol on shift, sum on no shift
- greek_char = event.shiftKey ? "∏" : "∑";
- break;
- case 50: //2 key
- //Integral on no shift, partial derivative on shift
- greek_char = event.shiftKey ? "∂" : "∫";
- break;
- case 51: //3 key
- //Less than or equal on no shift, greater than or equal on shift
- greek_char = event.shiftKey ? "≥" : "≤";
- break;
- case 52: //4 key
- //Empty set on shift, infinity on no shift
- greek_char = event.shiftKey ? "∅" : "∞";
- break;
- case 53: //5 key
- //Not equal on shift, approx equal on no shift
- greek_char = event.shiftKey ? "≠" : "≈";
- break;
- case 54: //6 key
- //Element of on no shift, not element of on shift
- greek_char = event.shiftKey ? "∉" : "∈";
- break;
- case 55: //7 key
- //And on shift, or on no shift
- greek_char = event.shiftKey ? "∧" : "∨";
- break;
- case 56: //8 key
- //Proportional to on shift, angle on no shift
- greek_char = event.shiftKey ? "∝" : "∠";
- break;
- case 57: //9 key
- //Cube root on shift, square root on no shift
- greek_char = event.shiftKey ? "∛" : "√";
- break;
- case 48: //0 key
- //Minus-Plus on shift, plus-minus on no shift
- greek_char = event.shiftKey ? "∓" : "±";
- break;
-
- //Special characters
- case 219: //hyphen (or ß on german layout)
- //Copyright on no shift, TM on shift
- greek_char = event.shiftKey ? "™" : "©";
- break;
- case 191: //forward slash (or # on german layout)
- //Generic currency on no shift, paragraph on shift
- greek_char = event.shiftKey ? "¶" : "¤";
- break;
-
- //Currency symbols
- case 192: //: or (ö on german layout)
- //Euro on no shift, pound on shift
- greek_char = event.shiftKey ? "£" : "€";
- break;
- case 221: //; or (ä on german layout)
- //Yen on no shift, dollar on shift
- greek_char = event.shiftKey ? "$" : "¥";
- break;
- }
-
- if(greek_char=="") return;
-
- const txt = event.currentTarget;
- const caretPos = txt.selectionStart;
- const textAreaTxt = txt.value;
- txt.value = textAreaTxt.substring(0, caretPos) + greek_char + textAreaTxt.substring(caretPos);
- }
- };
-
this.registerLoadHandler(() => {
- document.querySelectorAll('input[type=text], input[type=search]').forEach(input => {
- input.removeEventListener('keydown', keydownHandler);
- input.addEventListener('keydown', keydownHandler);
+ //@ts-ignore
+ $("input[type=text], input[type=search]").unbind("keydown").keydown(function (event) {
+ let use_special_char = event.altKey;
+
+ let greek_char = "";
+ if (use_special_char){
+ //Use the key property to determine the greek letter (as it is independent of the keyboard layout)
+ switch(event.key) {
+ //Greek letters
+ case "a": //Alpha (lowercase)
+ greek_char = "\u03B1";
+ break;
+ case "A": //Alpha (uppercase)
+ greek_char = "\u0391";
+ break;
+ case "b": //Beta (lowercase)
+ greek_char = "\u03B2";
+ break;
+ case "B": //Beta (uppercase)
+ greek_char = "\u0392";
+ break;
+ case "g": //Gamma (lowercase)
+ greek_char = "\u03B3";
+ break;
+ case "G": //Gamma (uppercase)
+ greek_char = "\u0393";
+ break;
+ case "d": //Delta (lowercase)
+ greek_char = "\u03B4";
+ break;
+ case "D": //Delta (uppercase)
+ greek_char = "\u0394";
+ break;
+ case "e": //Epsilon (lowercase)
+ greek_char = "\u03B5";
+ break;
+ case "E": //Epsilon (uppercase)
+ greek_char = "\u0395";
+ break;
+ case "z": //Zeta (lowercase)
+ greek_char = "\u03B6";
+ break;
+ case "Z": //Zeta (uppercase)
+ greek_char = "\u0396";
+ break;
+ case "h": //Eta (lowercase)
+ greek_char = "\u03B7";
+ break;
+ case "H": //Eta (uppercase)
+ greek_char = "\u0397";
+ break;
+ case "q": //Theta (lowercase)
+ greek_char = "\u03B8";
+ break;
+ case "Q": //Theta (uppercase)
+ greek_char = "\u0398";
+ break;
+ case "i": //Iota (lowercase)
+ greek_char = "\u03B9";
+ break;
+ case "I": //Iota (uppercase)
+ greek_char = "\u0399";
+ break;
+ case "k": //Kappa (lowercase)
+ greek_char = "\u03BA";
+ break;
+ case "K": //Kappa (uppercase)
+ greek_char = "\u039A";
+ break;
+ case "l": //Lambda (lowercase)
+ greek_char = "\u03BB";
+ break;
+ case "L": //Lambda (uppercase)
+ greek_char = "\u039B";
+ break;
+ case "m": //Mu (lowercase)
+ greek_char = "\u03BC";
+ break;
+ case "M": //Mu (uppercase)
+ greek_char = "\u039C";
+ break;
+ case "n": //Nu (lowercase)
+ greek_char = "\u03BD";
+ break;
+ case "N": //Nu (uppercase)
+ greek_char = "\u039D";
+ break;
+ case "x": //Xi (lowercase)
+ greek_char = "\u03BE";
+ break;
+ case "X": //Xi (uppercase)
+ greek_char = "\u039E";
+ break;
+ case "o": //Omicron (lowercase)
+ greek_char = "\u03BF";
+ break;
+ case "O": //Omicron (uppercase)
+ greek_char = "\u039F";
+ break;
+ case "p": //Pi (lowercase)
+ greek_char = "\u03C0";
+ break;
+ case "P": //Pi (uppercase)
+ greek_char = "\u03A0";
+ break;
+ case "r": //Rho (lowercase)
+ greek_char = "\u03C1";
+ break;
+ case "R": //Rho (uppercase)
+ greek_char = "\u03A1";
+ break;
+ case "s": //Sigma (lowercase)
+ greek_char = "\u03C3";
+ break;
+ case "S": //Sigma (uppercase)
+ greek_char = "\u03A3";
+ break;
+ case "t": //Tau (lowercase)
+ greek_char = "\u03C4";
+ break;
+ case "T": //Tau (uppercase)
+ greek_char = "\u03A4";
+ break;
+ case "u": //Upsilon (lowercase)
+ greek_char = "\u03C5";
+ break;
+ case "U": //Upsilon (uppercase)
+ greek_char = "\u03A5";
+ break;
+ case "f": //Phi (lowercase)
+ greek_char = "\u03C6";
+ break;
+ case "F": //Phi (uppercase)
+ greek_char = "\u03A6";
+ break;
+ case "c": //Chi (lowercase)
+ greek_char = "\u03C7";
+ break;
+ case "C": //Chi (uppercase)
+ greek_char = "\u03A7";
+ break;
+ case "y": //Psi (lowercase)
+ greek_char = "\u03C8";
+ break;
+ case "Y": //Psi (uppercase)
+ greek_char = "\u03A8";
+ break;
+ case "w": //Omega (lowercase)
+ greek_char = "\u03C9";
+ break;
+ case "W": //Omega (uppercase)
+ greek_char = "\u03A9";
+ break;
+ }
+
+ //Use keycodes for special characters as the shift char on the number keys are layout dependent
+ switch (event.keyCode) {
+ case 49: //1 key
+ //Product symbol on shift, sum on no shift
+ greek_char = event.shiftKey ? "\u220F" : "\u2211";
+ break;
+ case 50: //2 key
+ //Integral on no shift, partial derivative on shift
+ greek_char = event.shiftKey ? "\u2202" : "\u222B";
+ break;
+ case 51: //3 key
+ //Less than or equal on no shift, greater than or equal on shift
+ greek_char = event.shiftKey ? "\u2265" : "\u2264";
+ break;
+ case 52: //4 key
+ //Empty set on shift, infinity on no shift
+ greek_char = event.shiftKey ? "\u2205" : "\u221E";
+ break;
+ case 53: //5 key
+ //Not equal on shift, approx equal on no shift
+ greek_char = event.shiftKey ? "\u2260" : "\u2248";
+ break;
+ case 54: //6 key
+ //Element of on no shift, not element of on shift
+ greek_char = event.shiftKey ? "\u2209" : "\u2208";
+ break;
+ case 55: //7 key
+ //And on shift, or on no shift
+ greek_char = event.shiftKey ? "\u2227" : "\u2228";
+ break;
+ case 56: //8 key
+ //Proportional to on shift, angle on no shift
+ greek_char = event.shiftKey ? "\u221D" : "\u2220";
+ break;
+ case 57: //9 key
+ //Cube root on shift, square root on no shift
+ greek_char = event.shiftKey ? "\u221B" : "\u221A";
+ break;
+ case 48: //0 key
+ //Minus-Plus on shift, plus-minus on no shift
+ greek_char = event.shiftKey ? "\u2213" : "\u00B1";
+ break;
+
+ //Special characters
+ case 219: //hyphen (or ß on german layout)
+ //Copyright on no shift, TM on shift
+ greek_char = event.shiftKey ? "\u2122" : "\u00A9";
+ break;
+ case 191: //forward slash (or # on german layout)
+ //Generic currency on no shift, paragraph on shift
+ greek_char = event.shiftKey ? "\u00B6" : "\u00A4";
+ break;
+
+ //Currency symbols
+ case 192: //: or (ö on german layout)
+ //Euro on no shift, pound on shift
+ greek_char = event.shiftKey ? "\u00A3" : "\u20AC";
+ break;
+ case 221: //; or (ä on german layout)
+ //Yen on no shift, dollar on shift
+ greek_char = event.shiftKey ? "\u0024" : "\u00A5";
+ break;
+
+
+ }
+
+ if(greek_char=="") return;
+
+ let $txt = $(this);
+ //@ts-ignore
+ let caretPos = $txt[0].selectionStart;
+ let textAreaTxt = $txt.val().toString();
+ $txt.val(textAreaTxt.substring(0, caretPos) + greek_char + textAreaTxt.substring(caretPos) );
+
+ }
});
- });
+ //@ts-ignore
+ this.greek_once = true;
+ })
}
}
-export default new RegisterEventHelper();
+export default new RegisterEventHelper();
\ No newline at end of file
diff --git a/config/parameters.yaml b/config/parameters.yaml
index e654a9b5..b1aa5314 100644
--- a/config/parameters.yaml
+++ b/config/parameters.yaml
@@ -53,7 +53,6 @@ parameters:
# Themes commented here by default, are not really usable, because of display problems. Enable them at your own risk!
partdb.available_themes:
- bootstrap
- - brite
- cerulean
- cosmo
- cyborg
diff --git a/package.json b/package.json
index f906d814..f846f1d1 100644
--- a/package.json
+++ b/package.json
@@ -13,7 +13,7 @@
"bootstrap": "^5.1.3",
"core-js": "^3.38.0",
"intl-messageformat": "^10.5.11",
- "jquery": "^4.0.0",
+ "jquery": "^3.5.1",
"popper.js": "^1.14.7",
"regenerator-runtime": "^0.14.1",
"webpack": "^5.74.0",
@@ -38,21 +38,20 @@
"@algolia/autocomplete-theme-classic": "^1.17.0",
"@jbtronics/bs-treeview": "^1.0.1",
"@part-db/html5-qrcode": "^4.0.0",
- "@zxcvbn-ts/core": "^4.1.2",
- "@zxcvbn-ts/language-common": "^4.1.2",
- "@zxcvbn-ts/language-de": "^4.1.1",
- "@zxcvbn-ts/language-en": "^4.1.1",
- "@zxcvbn-ts/language-fr": "^4.1.1",
- "@zxcvbn-ts/language-it": "^4.1.1",
- "@zxcvbn-ts/language-ja": "^4.1.1",
- "@zxcvbn-ts/language-pl": "^4.1.1",
+ "@zxcvbn-ts/core": "^3.0.2",
+ "@zxcvbn-ts/language-common": "^3.0.3",
+ "@zxcvbn-ts/language-de": "^3.0.1",
+ "@zxcvbn-ts/language-en": "^3.0.1",
+ "@zxcvbn-ts/language-fr": "^3.0.1",
+ "@zxcvbn-ts/language-ja": "^3.0.1",
"attr-accept": "^2.2.5",
"barcode-detector": "^3.0.5",
+ "bootbox": "^6.0.0",
"bootswatch": "^5.1.3",
"bs-custom-file-input": "^1.3.4",
"ckeditor5": "^48.0.0",
"clipboard": "^2.0.4",
- "compression-webpack-plugin": "^12.0.0",
+ "compression-webpack-plugin": "^11.1.0",
"datatables.net": "^2.0.0",
"datatables.net-bs5": "^2.0.0",
"datatables.net-buttons-bs5": "^3.0.0",
@@ -70,12 +69,11 @@
"marked-mangle": "^1.0.1",
"pdfmake": "^0.3.7",
"stimulus-use": "^0.52.0",
- "sweetalert2": "^11.26.25",
"tom-select": "^2.1.0",
"ts-loader": "^9.2.6",
"typescript": "^6.0.2"
},
"resolutions": {
- "jquery": "^4.0.0"
+ "jquery": "^3.5.1"
}
}
diff --git a/translations/frontend.cs.xlf b/translations/frontend.cs.xlf
index 6417033b..4ba1f913 100644
--- a/translations/frontend.cs.xlf
+++ b/translations/frontend.cs.xlf
@@ -55,23 +55,5 @@
Jdi!
-
-
- dialog.btn.ok
- OK
-
-
-
-
- dialog.btn.cancel
- Zrušit
-
-
-
-
- dialog.btn.deny
- Ne
-
-
diff --git a/translations/frontend.da.xlf b/translations/frontend.da.xlf
index 817c703f..4b6a15b9 100644
--- a/translations/frontend.da.xlf
+++ b/translations/frontend.da.xlf
@@ -55,23 +55,5 @@
Kom nu!
-
-
- dialog.btn.ok
- OK
-
-
-
-
- dialog.btn.cancel
- Annuller
-
-
-
-
- dialog.btn.deny
- Nej
-
-
diff --git a/translations/frontend.de.xlf b/translations/frontend.de.xlf
index 6a4e7786..9ebd0d32 100644
--- a/translations/frontend.de.xlf
+++ b/translations/frontend.de.xlf
@@ -55,23 +55,5 @@
Los!
-
-
- dialog.btn.ok
- OK
-
-
-
-
- dialog.btn.cancel
- Abbrechen
-
-
-
-
- dialog.btn.deny
- Nein
-
-
diff --git a/translations/frontend.el.xlf b/translations/frontend.el.xlf
index fff724d2..bab41358 100644
--- a/translations/frontend.el.xlf
+++ b/translations/frontend.el.xlf
@@ -7,23 +7,5 @@
Αναζήτηση
-
-
- dialog.btn.ok
- OK
-
-
-
-
- dialog.btn.cancel
- Ακύρωση
-
-
-
-
- dialog.btn.deny
- Όχι
-
-
\ No newline at end of file
diff --git a/translations/frontend.en.xlf b/translations/frontend.en.xlf
index 7f68558a..91617f79 100644
--- a/translations/frontend.en.xlf
+++ b/translations/frontend.en.xlf
@@ -55,29 +55,5 @@
Go!
-
-
- user.password_strength.crack_time
- Estimated time to crack: %time%
-
-
-
-
- dialog.btn.ok
- OK
-
-
-
-
- dialog.btn.cancel
- Cancel
-
-
-
-
- dialog.btn.deny
- No
-
-
diff --git a/translations/frontend.es.xlf b/translations/frontend.es.xlf
index 02c52715..7d339959 100644
--- a/translations/frontend.es.xlf
+++ b/translations/frontend.es.xlf
@@ -55,23 +55,5 @@
¡Vamos!
-
-
- dialog.btn.ok
- OK
-
-
-
-
- dialog.btn.cancel
- Cancelar
-
-
-
-
- dialog.btn.deny
- No
-
-
diff --git a/translations/frontend.fr.xlf b/translations/frontend.fr.xlf
index 2a459052..5ebfca51 100644
--- a/translations/frontend.fr.xlf
+++ b/translations/frontend.fr.xlf
@@ -55,23 +55,5 @@
Rechercher !
-
-
- dialog.btn.ok
- OK
-
-
-
-
- dialog.btn.cancel
- Annuler
-
-
-
-
- dialog.btn.deny
- Non
-
-
diff --git a/translations/frontend.hu.xlf b/translations/frontend.hu.xlf
index 7724ce66..c303dedc 100644
--- a/translations/frontend.hu.xlf
+++ b/translations/frontend.hu.xlf
@@ -55,23 +55,5 @@
Indítás!
-
-
- dialog.btn.ok
- OK
-
-
-
-
- dialog.btn.cancel
- Mégse
-
-
-
-
- dialog.btn.deny
- Nem
-
-
diff --git a/translations/frontend.it.xlf b/translations/frontend.it.xlf
index c13ab47a..f163e3e2 100644
--- a/translations/frontend.it.xlf
+++ b/translations/frontend.it.xlf
@@ -55,23 +55,5 @@
Cerca!
-
-
- dialog.btn.ok
- OK
-
-
-
-
- dialog.btn.cancel
- Annulla
-
-
-
-
- dialog.btn.deny
- No
-
-
diff --git a/translations/frontend.ja.xlf b/translations/frontend.ja.xlf
index d8612e5b..90ffdf5f 100644
--- a/translations/frontend.ja.xlf
+++ b/translations/frontend.ja.xlf
@@ -19,23 +19,5 @@
検索
-
-
- dialog.btn.ok
- OK
-
-
-
-
- dialog.btn.cancel
- キャンセル
-
-
-
-
- dialog.btn.deny
- いいえ
-
-
\ No newline at end of file
diff --git a/translations/frontend.nl.xlf b/translations/frontend.nl.xlf
index 4c90e933..d14f5a81 100644
--- a/translations/frontend.nl.xlf
+++ b/translations/frontend.nl.xlf
@@ -55,23 +55,5 @@
Ga!
-
-
- dialog.btn.ok
- OK
-
-
-
-
- dialog.btn.cancel
- Annuleren
-
-
-
-
- dialog.btn.deny
- Nee
-
-
diff --git a/translations/frontend.pl.xlf b/translations/frontend.pl.xlf
index e748286c..fface684 100644
--- a/translations/frontend.pl.xlf
+++ b/translations/frontend.pl.xlf
@@ -55,23 +55,5 @@
Idź!
-
-
- dialog.btn.ok
- OK
-
-
-
-
- dialog.btn.cancel
- Anuluj
-
-
-
-
- dialog.btn.deny
- Nie
-
-
diff --git a/translations/frontend.pt_BR.xlf b/translations/frontend.pt_BR.xlf
index 9053c8c3..fb2f2335 100644
--- a/translations/frontend.pt_BR.xlf
+++ b/translations/frontend.pt_BR.xlf
@@ -55,23 +55,5 @@
Vá!
-
-
- dialog.btn.ok
- OK
-
-
-
-
- dialog.btn.cancel
- Cancelar
-
-
-
-
- dialog.btn.deny
- Não
-
-
diff --git a/translations/frontend.ru.xlf b/translations/frontend.ru.xlf
index 6e1879d8..f4665a74 100644
--- a/translations/frontend.ru.xlf
+++ b/translations/frontend.ru.xlf
@@ -55,23 +55,5 @@
Поехали!
-
-
- dialog.btn.ok
- ОК
-
-
-
-
- dialog.btn.cancel
- Отмена
-
-
-
-
- dialog.btn.deny
- Нет
-
-
diff --git a/translations/frontend.uk.xlf b/translations/frontend.uk.xlf
index a28941fa..fee1b03e 100644
--- a/translations/frontend.uk.xlf
+++ b/translations/frontend.uk.xlf
@@ -55,23 +55,5 @@
Почати!
-
-
- dialog.btn.ok
- ОК
-
-
-
-
- dialog.btn.cancel
- Скасувати
-
-
-
-
- dialog.btn.deny
- Ні
-
-
diff --git a/translations/frontend.zh.xlf b/translations/frontend.zh.xlf
index 7425b1e8..8bb063b8 100644
--- a/translations/frontend.zh.xlf
+++ b/translations/frontend.zh.xlf
@@ -55,23 +55,5 @@
GO!
-
-
- dialog.btn.ok
- 确定
-
-
-
-
- dialog.btn.cancel
- 取消
-
-
-
-
- dialog.btn.deny
- 否
-
-
diff --git a/translations/messages.en.xlf b/translations/messages.en.xlf
index fe219869..117e529b 100644
--- a/translations/messages.en.xlf
+++ b/translations/messages.en.xlf
@@ -490,7 +490,7 @@ The user will have to set up all two-factor authentication methods again and pri
entity.delete.confirm_title
- Do you really want to delete %name%?
+ You really want to delete %name%?
diff --git a/webpack.config.js b/webpack.config.js
index 259803fa..60ea145f 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -119,14 +119,7 @@ Encore
// requires WebpackEncoreBundle 1.4 or higher
.enableIntegrityHashes(Encore.isProduction())
- // Force all jquery imports to the UMD build so webpack always receives the
- // jQuery function directly instead of an ESM namespace object. Without this,
- // webpack's ESM interop wraps jquery.module.js in a namespace
- // { default, jQuery, $ } which has no .fn, crashing Bootstrap's
- // defineJQueryPlugin when it tries to access $.fn.alert.
- .addAliases({
- 'jquery': path.resolve(__dirname, 'node_modules/jquery/dist/jquery.js')
- })
+ // uncomment if you're having problems with a jQuery plugin
.autoProvidejQuery()
@@ -149,7 +142,7 @@ Encore
;
//These are all the themes that are available in bootswatch
-const AVAILABLE_THEMES = ['bootstrap', 'brite', 'cerulean', 'cosmo', 'cyborg', 'darkly', 'flatly', 'journal',
+const AVAILABLE_THEMES = ['bootstrap', 'cerulean', 'cosmo', 'cyborg', 'darkly', 'flatly', 'journal',
'litera', 'lumen', 'lux', 'materia', 'minty', 'morph', 'pulse', 'quartz', 'sandstone', 'simplex', 'sketchy', 'slate', 'solar',
'spacelab', 'superhero', 'united', 'vapor', 'yeti', 'zephyr'];
diff --git a/yarn.lock b/yarn.lock
index 7589ce13..19e9716e 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2071,66 +2071,37 @@
resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d"
integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==
-"@zxcvbn-ts/core@^4.1.2":
- version "4.1.2"
- resolved "https://registry.yarnpkg.com/@zxcvbn-ts/core/-/core-4.1.2.tgz#2d280f3d1a558201cf34080c4d7de335afd4cc4a"
- integrity sha512-RQmxWB3AMI+HGQErQdUv6Aq32aQhp6xOxrfgCP0+T9MsLZoP3xtLHuT8O8VojsUxdmQVZfJlYkYb1A0wOwIS+Q==
+"@zxcvbn-ts/core@^3.0.2":
+ version "3.0.4"
+ resolved "https://registry.yarnpkg.com/@zxcvbn-ts/core/-/core-3.0.4.tgz#c5bde72235eb6c273cec78b672bb47c0d7045cad"
+ integrity sha512-aQeiT0F09FuJaAqNrxynlAwZ2mW/1MdXakKWNmGM1Qp/VaY6CnB/GfnMS2T8gB2231Esp1/maCWd8vTG4OuShw==
dependencies:
fastest-levenshtein "1.0.16"
-"@zxcvbn-ts/dictionary-compression@^3.0.1":
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/@zxcvbn-ts/dictionary-compression/-/dictionary-compression-3.0.1.tgz#f357ad46e08fff8ba92f6f163d6b38b9533fc849"
- integrity sha512-p3KyPzxGc3vWSap5hHA6SllbUCmh7s+NtpGyC3qEWrxYJT9t9TUAzjPm48Okipo+UUyPQfDlIvTcs9JRShBFiQ==
+"@zxcvbn-ts/language-common@^3.0.3":
+ version "3.0.4"
+ resolved "https://registry.yarnpkg.com/@zxcvbn-ts/language-common/-/language-common-3.0.4.tgz#fa1d2a42f8c8a589555859795da90d6b8027b7c4"
+ integrity sha512-viSNNnRYtc7ULXzxrQIVUNwHAPSXRtoIwy/Tq4XQQdIknBzw4vz36lQLF6mvhMlTIlpjoN/Z1GFu/fwiAlUSsw==
-"@zxcvbn-ts/language-common@^4.1.2":
- version "4.1.2"
- resolved "https://registry.yarnpkg.com/@zxcvbn-ts/language-common/-/language-common-4.1.2.tgz#c38c52500865d3a2ab7fa1193d747dafc4f2b995"
- integrity sha512-uJlBzhC9/KjPImqdnc1/lPxmdn4xKbkruN5p1mASWkXA0gli+GZ5LrVL+dqscA8Pcf4OfudE56TtCWeHljJOvA==
- dependencies:
- "@zxcvbn-ts/dictionary-compression" "^3.0.1"
+"@zxcvbn-ts/language-de@^3.0.1":
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/@zxcvbn-ts/language-de/-/language-de-3.0.2.tgz#fbd0d1be9454e308bbd63bf5487d4c17670094f0"
+ integrity sha512-CPl2314qWtnJl4EkeEqFbL4unP6yEAHO976ER+df8CQcKsF4FxdZYEahkleWU66dhNI2VKnmJKNMzq8QtHQKcw==
-"@zxcvbn-ts/language-de@^4.1.1":
- version "4.1.1"
- resolved "https://registry.yarnpkg.com/@zxcvbn-ts/language-de/-/language-de-4.1.1.tgz#c6a91f43119fdedefe35b7049c8e4f7af9dd88fa"
- integrity sha512-ig4zeCxg4yp5VU4/Iuq5CCHLJtbmHjczK87HKw/K2jYkpk1s7C4jRi+n3XgcPNRP71nvTxGhpPWWlsziCnm5xA==
- dependencies:
- "@zxcvbn-ts/dictionary-compression" "^3.0.1"
+"@zxcvbn-ts/language-en@^3.0.1":
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/@zxcvbn-ts/language-en/-/language-en-3.0.2.tgz#162ada6b2b556444efd5a7700e70845cfde6d6ec"
+ integrity sha512-Zp+zL+I6Un2Bj0tRXNs6VUBq3Djt+hwTwUz4dkt2qgsQz47U0/XthZ4ULrT/RxjwJRl5LwiaKOOZeOtmixHnjg==
-"@zxcvbn-ts/language-en@^4.1.1":
- version "4.1.1"
- resolved "https://registry.yarnpkg.com/@zxcvbn-ts/language-en/-/language-en-4.1.1.tgz#20ca499affb4d6972d777ec04bb0c786d33add73"
- integrity sha512-6UdzuBd3Uex8TKubohcn+uXRVAH34Zjs2eCfT4hQVo9zeTy7AkQRQfdV4OnHR5hQfW/XBrK/AGTZk7VBWh7wwQ==
- dependencies:
- "@zxcvbn-ts/dictionary-compression" "^3.0.1"
+"@zxcvbn-ts/language-fr@^3.0.1":
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/@zxcvbn-ts/language-fr/-/language-fr-3.0.2.tgz#79c5f0475fd388502f04f5560456db37dc0dde35"
+ integrity sha512-Tj9jS/Z8mNBAD21pn8Mp4O86CPrwImysO1fM3DG+fsfk8W79/MDzqpFDBHiqpu69Uo3LPPctMHEEteakFWt4Qg==
-"@zxcvbn-ts/language-fr@^4.1.1":
- version "4.1.1"
- resolved "https://registry.yarnpkg.com/@zxcvbn-ts/language-fr/-/language-fr-4.1.1.tgz#7d1eccaad7b4dbfe31efe018e9239893bdc33bc8"
- integrity sha512-5LW8KMiXLWKG6fTv/BdQbe76sa2EjYmvd59sM3Re+hZMGYEPOdjnAT5qFChQ2Zj8WIaU3P197Y6A0X8OgfoiqQ==
- dependencies:
- "@zxcvbn-ts/dictionary-compression" "^3.0.1"
-
-"@zxcvbn-ts/language-it@^4.1.1":
- version "4.1.1"
- resolved "https://registry.yarnpkg.com/@zxcvbn-ts/language-it/-/language-it-4.1.1.tgz#b6fda40099e85a4fc1c5d14d75c9de8a304dd061"
- integrity sha512-YxKCBO1rKuCMPYRyOxfUZA+3ju8OO8W9Qx8h/vHrHvuGIavK7L+fgXTUrhjHU8M+zE0pQZxS4wOdfgLFZaP57w==
- dependencies:
- "@zxcvbn-ts/dictionary-compression" "^3.0.1"
-
-"@zxcvbn-ts/language-ja@^4.1.1":
- version "4.1.1"
- resolved "https://registry.yarnpkg.com/@zxcvbn-ts/language-ja/-/language-ja-4.1.1.tgz#acd36abe4f6083dceda22771148d0948e0e421d9"
- integrity sha512-ZDFUZfm7hlmuiHOMLq7p85wE3Pa7s1WXixU6X+POTuRTjGwXi4LMtiS9wli7zXTEvxSUMdVWBx5ZgyIF6D0S8A==
- dependencies:
- "@zxcvbn-ts/dictionary-compression" "^3.0.1"
-
-"@zxcvbn-ts/language-pl@^4.1.1":
- version "4.1.1"
- resolved "https://registry.yarnpkg.com/@zxcvbn-ts/language-pl/-/language-pl-4.1.1.tgz#627d4c365a69e3f78d3e2b6e9667d1b57b6cc1ff"
- integrity sha512-hF6Qu9cyHx7sSEzNOQrJQntq8geoincsGvlOC0wkD43LnUVSTR49MKxdsifsemlQgtxR7aUKDgK/e/RFHOljoQ==
- dependencies:
- "@zxcvbn-ts/dictionary-compression" "^3.0.1"
+"@zxcvbn-ts/language-ja@^3.0.1":
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/@zxcvbn-ts/language-ja/-/language-ja-3.0.2.tgz#299bb6f5465f99405577491b1b31352058540c76"
+ integrity sha512-YjQyt+eMe3EdpeJiSt81AMF8HfEXXCary/VRoG+0erZBzRjfJ1U3JdSiu9wFFxiEF8Cb5FEmTQ6nQPyraezH6Q==
acorn-import-phases@^1.0.3:
version "1.0.4"
@@ -2271,6 +2242,11 @@ boolbase@^1.0.0:
resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e"
integrity sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==
+bootbox@^6.0.0:
+ version "6.0.4"
+ resolved "https://registry.yarnpkg.com/bootbox/-/bootbox-6.0.4.tgz#005f12d712da5d5723a13a0495e5fc4ad2cc1472"
+ integrity sha512-LoOT8WbiH6YjlhIxzJ3nZHK1p9tlcoa6QNILSGJMx9ihydzFk+DVzNVWNpHk8MZLOkizey1XhFu1dhoqk77xVg==
+
bootstrap@^5.1.3:
version "5.3.8"
resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-5.3.8.tgz#6401a10057a22752d21f4e19055508980656aeed"
@@ -2531,13 +2507,13 @@ commander@^8.3.0:
resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66"
integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==
-compression-webpack-plugin@^12.0.0:
- version "12.0.0"
- resolved "https://registry.yarnpkg.com/compression-webpack-plugin/-/compression-webpack-plugin-12.0.0.tgz#6842bb3720407afb0686500411c765c37f37164d"
- integrity sha512-LR4mS19Jqq41XfA3xVMLrtzVNzqJbUHdzPeLRfQoLiAS9s87f0021fDuU89xxVQFcB6d20ufBkv4j1rQ4OowHw==
+compression-webpack-plugin@^11.1.0:
+ version "11.1.0"
+ resolved "https://registry.yarnpkg.com/compression-webpack-plugin/-/compression-webpack-plugin-11.1.0.tgz#ee340d2029cf99ccecdea9ad1410b377d15b48b3"
+ integrity sha512-zDOQYp10+upzLxW+VRSjEpRRwBXJdsb5lBMlRxx1g8hckIFBpe3DTI0en2w7h+beuq89576RVzfiXrkdPGrHhA==
dependencies:
schema-utils "^4.2.0"
- serialize-javascript "^7.0.3"
+ serialize-javascript "^6.0.2"
consola@^3.2.3:
version "3.4.2"
@@ -3451,10 +3427,10 @@ jest-worker@^30.0.5:
merge-stream "^2.0.0"
supports-color "^8.1.1"
-jquery@>=1.7, jquery@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/jquery/-/jquery-4.0.0.tgz#95c33ac29005ff72ec444c5ba1cf457e61404fbb"
- integrity sha512-TXCHVR3Lb6TZdtw1l3RTLf8RBWVGexdxL6AC8/e0xZKEpBflBsjh9/8LXw+dkNFuOyW9B7iB3O1sP7hS0Kiacg==
+jquery@>=1.7, jquery@^3.5.1:
+ version "3.7.1"
+ resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.7.1.tgz#083ef98927c9a6a74d05a6af02806566d16274de"
+ integrity sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg==
js-md5@^0.8.3:
version "0.8.3"
@@ -4506,6 +4482,13 @@ property-information@^7.0.0:
resolved "https://registry.yarnpkg.com/property-information/-/property-information-7.2.0.tgz#0809b34264e995c0bfcd3227028a1e35210af80a"
integrity sha512-IAtzIB6sUiWaJYrX9smp3V46pBGbBeLFRGdh25kg1334VcBlD8HzhPeNIWQH9zhGmo2itIe25EHt9dQP7G5hmg==
+randombytes@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a"
+ integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==
+ dependencies:
+ safe-buffer "^5.1.0"
+
readable-stream@~2.3.6:
version "2.3.8"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b"
@@ -4714,6 +4697,11 @@ restructure@^3.0.0:
resolved "https://registry.yarnpkg.com/restructure/-/restructure-3.0.2.tgz#e6b2fad214f78edee21797fa8160fef50eb9b49a"
integrity sha512-gSfoiOEA0VPE6Tukkrr7I0RBdE0s7H1eFCDBk05l1KIQT1UIKNc5JZy6jdyW6eYH3aR3g5b3PuL77rq0hvwtAw==
+safe-buffer@^5.1.0:
+ version "5.2.1"
+ resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
+ integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
+
safe-buffer@~5.1.0, safe-buffer@~5.1.1:
version "5.1.2"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
@@ -4749,6 +4737,13 @@ semver@^7.3.2, semver@^7.3.4, semver@^7.6.3:
resolved "https://registry.yarnpkg.com/semver/-/semver-7.8.5.tgz#39b646037dd50c14fb451e7e4cac58ed8b863f69"
integrity sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==
+serialize-javascript@^6.0.2:
+ version "6.0.2"
+ resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.2.tgz#defa1e055c83bf6d59ea805d8da862254eb6a6c2"
+ integrity sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==
+ dependencies:
+ randombytes "^2.1.0"
+
serialize-javascript@^7.0.3:
version "7.0.6"
resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-7.0.6.tgz#f2f20c8af0757e4d8fa329d0210636da0682ddef"
@@ -4911,11 +4906,6 @@ svgo@^4.0.1:
picocolors "^1.1.1"
sax "^1.5.0"
-sweetalert2@^11.26.25:
- version "11.26.25"
- resolved "https://registry.yarnpkg.com/sweetalert2/-/sweetalert2-11.26.25.tgz#ba24ffb79c67648ac51f834620baa15866a56e35"
- integrity sha512-+hunCOJdJ6FLj04T9YSLvvZXRjsvIkTeTKP2e4VF8CaBias961BTnWiSFAy7F/CM5eq3QK2Rraoc5Gzftslvkg==
-
tagged-tag@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/tagged-tag/-/tagged-tag-1.0.0.tgz#a0b5917c2864cba54841495abfa3f6b13edcf4d6"