diff --git a/src/package-lock.json b/src/package-lock.json
--- a/src/package-lock.json
+++ b/src/package-lock.json
@@ -3550,6 +3550,12 @@
"fastq": "^1.6.0"
}
},
+ "@popperjs/core": {
+ "version": "2.9.2",
+ "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.9.2.tgz",
+ "integrity": "sha512-VZMYa7+fXHdwIq1TDhSXoVmSPEGM/aa+6Aiq3nVVJ9bXr24zScr+NlKFKC3iPljA7ho/GAZr+d2jOf5GIRC30Q==",
+ "dev": true
+ },
"@stylelint/postcss-css-in-js": {
"version": "0.37.2",
"resolved": "https://registry.npmjs.org/@stylelint/postcss-css-in-js/-/postcss-css-in-js-0.37.2.tgz",
@@ -4555,9 +4561,9 @@
"dev": true
},
"bootstrap": {
- "version": "4.6.0",
- "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.6.0.tgz",
- "integrity": "sha512-Io55IuQY3kydzHtbGvQya3H+KorS/M9rSNyfCGCg9WZ4pyT/lCxIlpJgG1GXW/PswzC84Tr2fBYi+7+jFVQQBw==",
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.0.2.tgz",
+ "integrity": "sha512-1Ge963tyEQWJJ+8qtXFU6wgmAVj9gweEjibUdbmcCEYsn38tVwRk8107rk2vzt6cfQcRr3SlZ8aQBqaD8aqf+Q==",
"dev": true
},
"brace-expansion": {
@@ -4789,6 +4795,12 @@
"integrity": "sha512-JUdjWpcxfJ9IPamy2f5JaRDCaqJOxDzOSKtbdx4rH9VivMd1vIzoPumsJa9LoMIi4Fx2BV2KZOxWhNkBjaYivQ==",
"dev": true
},
+ "cash-dom": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/cash-dom/-/cash-dom-8.1.0.tgz",
+ "integrity": "sha512-QTa50rFuPaX8klEDEbwLr+jVutwpvZEBQ0NpMMyng+je7gNe9Bz/JsOLHIG24tvNSSSIN/Q1QD0bnF6PQzWKHA==",
+ "dev": true
+ },
"chalk": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz",
@@ -7662,12 +7674,6 @@
}
}
},
- "jquery": {
- "version": "3.6.0",
- "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.6.0.tgz",
- "integrity": "sha512-JVzAR/AjBvVt2BmYhxRCSYysDsPcssdmTFnzyLEts9qNwmjmu4JTAMYubEfwVOSwpQ1I1sKKFcxhZCI2buerfw==",
- "dev": true
- },
"js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@@ -9280,12 +9286,6 @@
"integrity": "sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==",
"dev": true
},
- "popper.js": {
- "version": "1.16.1",
- "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1.tgz",
- "integrity": "sha1-KiI8s9x7YhPXQOQDcr5A3kPmWxs=",
- "dev": true
- },
"portfinder": {
"version": "1.0.28",
"resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.28.tgz",
diff --git a/src/package.json b/src/package.json
--- a/src/package.json
+++ b/src/package.json
@@ -17,17 +17,17 @@
"@fortawesome/free-regular-svg-icons": "^5.15.3",
"@fortawesome/free-solid-svg-icons": "^5.15.3",
"@fortawesome/vue-fontawesome": "^0.1.10",
+ "@popperjs/core": "^2.9.2",
"anchorme": "^2.1.2",
"axios": "^0.21.1",
- "bootstrap": "^4.6.0",
+ "bootstrap": "^5.0.0",
+ "cash-dom": "^8.1.0",
"cross-env": "^7.0.3",
"eslint": "^7.26.0",
"eslint-plugin-vue": "^7.9.0",
"frappe-charts": "^1.5.8",
- "jquery": "^3.6.0",
"laravel-mix": "^6.0.27",
"openvidu-browser": "^2.18.0",
- "popper.js": "^1.16.0",
"postcss": "^8.3.6",
"resolve-url-loader": "^4.0.0",
"sass": "^1.32.8",
diff --git a/src/resources/js/app.js b/src/resources/js/app.js
--- a/src/resources/js/app.js
+++ b/src/resources/js/app.js
@@ -10,9 +10,10 @@
import MenuComponent from '../vue/Widgets/Menu'
import SupportForm from '../vue/Widgets/SupportForm'
import store from './store'
+import { Tab } from 'bootstrap'
import { loadLangAsync, i18n } from './locale'
-const loader = '
'
+const loader = ''
let isLoading = 0
@@ -177,8 +178,14 @@
return ``
},
// Display "loading" overlay inside of the specified element
- addLoader(elem, small = true) {
- $(elem).css({position: 'relative'}).append(small ? $(loader).addClass('small') : $(loader))
+ addLoader(elem, small = true, style = null) {
+ if (style) {
+ $(elem).css(style)
+ } else {
+ $(elem).css('position', 'relative')
+ }
+
+ $(elem).append(small ? $(loader).addClass('small') : $(loader))
},
// Remove loader element added in addLoader()
removeLoader(elem) {
@@ -191,7 +198,7 @@
},
tab(e) {
e.preventDefault()
- $(e.target).tab('show')
+ new Tab(e.target).show()
},
errorPage(code, msg, hint) {
// Until https://github.com/vuejs/vue-router/issues/977 is implemented
@@ -267,10 +274,7 @@
},
clickRecord(event) {
if (!/^(a|button|svg|path)$/i.test(event.target.nodeName)) {
- let link = $(event.target).closest('tr').find('a')[0]
- if (link) {
- link.click()
- }
+ $(event.target).closest('tr').find('a').trigger('click')
}
},
domainStatusClass(domain) {
@@ -350,21 +354,19 @@
return page ? page : '404'
},
supportDialog(container) {
- let dialog = $('#support-dialog')
+ let dialog = $('#support-dialog')[0]
- // FIXME: Find a nicer way of doing this
- if (!dialog.length) {
+ if (!dialog) {
+ // FIXME: Find a nicer way of doing this
SupportForm.i18n = i18n
let form = new Vue(SupportForm)
form.$mount($('').appendTo(container)[0])
form.$root = this
form.$toast = this.$toast
- dialog = $(form.$el)
+ dialog = form.$el
}
- dialog.on('shown.bs.modal', () => {
- dialog.find('input').first().focus()
- }).modal()
+ dialog.__vue__.showDialog()
},
userStatusClass(user) {
if (user.isDeleted) {
@@ -464,7 +466,7 @@
// Create an error message
// API responses can use a string, array or object
let msg_text = ''
- if ($.type(msg) !== 'string') {
+ if (typeof(msg) !== 'string') {
$.each(msg, (index, str) => {
msg_text += str + ' '
})
diff --git a/src/resources/js/bootstrap.js b/src/resources/js/bootstrap.js
--- a/src/resources/js/bootstrap.js
+++ b/src/resources/js/bootstrap.js
@@ -1,18 +1,22 @@
/**
- * We'll load jQuery and the Bootstrap jQuery plugin which provides support
- * for JavaScript based Bootstrap features such as modals and tabs. This
- * code may be modified to fit the specific needs of your application.
+ * Import Cash (jQuery replacement)
*/
-window.Popper = require('popper.js').default
-window.$ = window.jQuery = require('jquery')
+import $ from 'cash-dom'
+window.$ = $
-require('bootstrap')
+$.fn.focus = function() {
+ if (this.length && this[0].focus) {
+ this[0].focus()
+ }
+ return this
+}
/**
- * We'll load Vue, VueRouter and global components
+ * Load Vue, VueRouter and global components
*/
+import { Tooltip } from 'bootstrap'
import FontAwesomeIcon from './fontawesome'
import Vue from 'vue'
import VueRouter from 'vue-router'
@@ -24,26 +28,26 @@
Vue.component('SvgIcon', FontAwesomeIcon)
const vTooltip = (el, binding) => {
- const t = []
+ let t = []
if (binding.modifiers.focus) t.push('focus')
if (binding.modifiers.hover) t.push('hover')
if (binding.modifiers.click) t.push('click')
- if (!t.length) t.push('hover')
+ if (!t.length) t.push('click')
- $(el).tooltip({
+ el.tooltip = new Tooltip(el, {
title: binding.value,
placement: binding.arg || 'top',
trigger: t.join(' '),
- html: !!binding.modifiers.html,
- });
+ html: !!binding.modifiers.html
+ })
}
Vue.directive('tooltip', {
bind: vTooltip,
update: vTooltip,
unbind (el) {
- $(el).tooltip('dispose')
+ el.tooltip.dispose()
}
})
@@ -70,7 +74,7 @@
})
/**
- * We'll load the axios HTTP library which allows us to easily issue requests
+ * Load the axios HTTP library which allows us to easily issue requests
* to our Laravel back-end. This library automatically handles sending the
* CSRF token as a header based on the value of the "XSRF" token cookie.
*/
diff --git a/src/resources/js/meet/app.js b/src/resources/js/meet/app.js
--- a/src/resources/js/meet/app.js
+++ b/src/resources/js/meet/app.js
@@ -1,4 +1,5 @@
import anchorme from 'anchorme'
+import { Dropdown } from 'bootstrap'
import { library } from '@fortawesome/fontawesome-svg-core'
import { OpenVidu } from 'openvidu-browser'
@@ -1033,7 +1034,7 @@
}
if (params.isSelf) {
- wrapper.find('.link-setup').removeClass('hidden').click(() => sessionData.onMediaSetup())
+ wrapper.find('.link-setup').removeClass('hidden').on('click', () => sessionData.onMediaSetup())
} else {
let volumeInput = wrapper.find('.volume input')
let audioButton = wrapper.find('.link-audio')
@@ -1284,19 +1285,19 @@
+ '
'
+ '
'
+ ''
- + '
'
+ '
'
+ '
'
+ ''
- + '