diff --git a/assets/app.js b/assets/app.js index 61545143..b0da188a 100644 --- a/assets/app.js +++ b/assets/app.js @@ -11,7 +11,20 @@ global.$ = global.jQuery = $; require('bootstrap-sass'); require('jquery-slimscroll'); -require('bootstrap-select'); +require('select2'); +require('select2/dist/js/i18n/ar'); +require('select2/dist/js/i18n/cs'); +require('select2/dist/js/i18n/de'); +require('select2/dist/js/i18n/es'); +require('select2/dist/js/i18n/fr'); +require('select2/dist/js/i18n/hu'); +require('select2/dist/js/i18n/it'); +require('select2/dist/js/i18n/ja'); +require('select2/dist/js/i18n/ko'); +require('select2/dist/js/i18n/pt-BR'); +require('select2/dist/js/i18n/ru'); +require('select2/dist/js/i18n/sk'); +require('select2/dist/js/i18n/sv'); const Moment = require('moment'); global.moment = Moment; @@ -32,7 +45,7 @@ require('moment/locale/sv'); require('daterangepicker'); // ------ AdminLTE framework ------ -require('../vendor/kevinpapst/adminlte-bundle/Resources/assets/admin-lte.scss'); +require('./sass/admin-lte.scss'); require('admin-lte/dist/css/AdminLTE.min.css'); require('admin-lte/dist/css/skins/_all-skins.css'); require('../vendor/kevinpapst/adminlte-bundle/Resources/assets/admin-lte-extensions.scss'); diff --git a/assets/js/plugins/KimaiFormSelect.js b/assets/js/plugins/KimaiFormSelect.js index 083562f7..363a723f 100644 --- a/assets/js/plugins/KimaiFormSelect.js +++ b/assets/js/plugins/KimaiFormSelect.js @@ -26,13 +26,19 @@ export default class KimaiFormSelect extends KimaiPlugin { activateSelectPicker(selector, container) { let options = {}; if (container !== undefined) { - options = {container: container}; + options = { + dropdownParent: $(container), + }; } - jQuery(selector + ' ' + this.selector).selectpicker(options); + options = {...options, ...{ + language: this.getContainer().getConfiguration().get('locale'), + theme: "bootstrap" + }}; + jQuery(selector + ' ' + this.selector).select2(options); } destroySelectPicker(selector) { - jQuery(selector + ' ' + this.selector).selectpicker('destroy'); + jQuery(selector + ' ' + this.selector).select2('destroy'); } updateOptions(selectIdentifier, data) { @@ -71,7 +77,7 @@ export default class KimaiFormSelect extends KimaiPlugin { // if the beta test kimai.theme.select_type is active, this will tell the selects to refresh if (select.hasClass('selectpicker')) { - select.selectpicker('refresh'); + select.trigger('change.select2'); } } } diff --git a/assets/js/plugins/KimaiToolbar.js b/assets/js/plugins/KimaiToolbar.js index f6746f1d..f799e315 100644 --- a/assets/js/plugins/KimaiToolbar.js +++ b/assets/js/plugins/KimaiToolbar.js @@ -35,43 +35,25 @@ export default class KimaiToolbar extends KimaiPlugin { this._registerSearchButtons(formSelector); jQuery('body') - // prevent that the dropdown closes, when a form input is changed - eg. a select option was clicked + // prevent that the dropdown closes, when a form input is changed - eg. a select option was clicked .on('click', formSelector + ' .dropdown-menu', function (event) { - const parent = jQuery(event.target).parents('.bootstrap-select'); - if (parent.length === 0) { - event.stopPropagation(); - jQuery(".bootstrap-select").removeClass("open"); - } - }) - // trying to emulate the normal behaviour fo the bootstrap-select, as using its default implementation - // leads to closing the surrounding dropdown menu - .on('click', formSelector + ' .bootstrap-select', function (event) { - const current = jQuery(this); - if (current.hasClass("open")){ - jQuery(".bootstrap-select").removeClass("open"); - } else { - jQuery(".bootstrap-select").not('.bs-container').each(function(index, element) { - var tmp = jQuery(element); - if (tmp.is(current)) { - return; - } - if (tmp.hasClass('open')) { - tmp.removeClass("open"); - // the shown dropdown list will not be closed, using toggle hides all other lists BUT closes the containing search-dropdown - // tmp.find('select.selectpicker').selectpicker('toggle'); - } - }); - current.addClass("open"); - } event.stopPropagation(); }) - // close bootstrap-select if a click happened outside (and none of the other clickHandler were called) - // if the click happened inside a bootstrap-select, we ignore this - .on('click', function(event) { - const parent = jQuery(event.target).parents('.bootstrap-select'); - if (parent.length === 0) { - jQuery(".bootstrap-select").removeClass("open"); - } + // prevent that a click into the search field will close the dropdown + .on('click', '.select2-search__field', function (event) { + event.stopPropagation(); + }) + // prevent that the dropdown closes when a optgroup header is clicked + .on('click', '.select2-results__group', function (event) { + event.stopPropagation(); + }) + // prevent that a click into a daterangepicker will close the dropdown + .on('click', '.daterangepicker', function (event) { + event.stopPropagation(); + }) + // prevent that clicks in the dropdown elements, but outside of elements will close the dropdown (eg border besides the search field) + .on('click', '.select2-container', function (event) { + event.stopPropagation(); }) ; diff --git a/assets/sass/admin-lte.scss b/assets/sass/admin-lte.scss new file mode 100644 index 00000000..aacead1d --- /dev/null +++ b/assets/sass/admin-lte.scss @@ -0,0 +1,10 @@ + +$icon-font-path: "~bootstrap-sass/assets/fonts/bootstrap/"; +$fa-font-path: "~@fortawesome/fontawesome-free/webfonts/"; + +@import '~bootstrap-sass/assets/stylesheets/bootstrap'; +@import '~@fortawesome/fontawesome-free/scss/fontawesome'; +@import '~@fortawesome/fontawesome-free/scss/regular'; +@import '~@fortawesome/fontawesome-free/scss/solid'; +@import '~@fortawesome/fontawesome-free/scss/brands'; +@import '~daterangepicker/daterangepicker.css'; diff --git a/assets/sass/app.scss b/assets/sass/app.scss index 17ba8023..fa057c4f 100644 --- a/assets/sass/app.scss +++ b/assets/sass/app.scss @@ -5,7 +5,6 @@ * file that was distributed with this source code. */ -@import "~bootstrap-sass/assets/stylesheets/bootstrap/variables"; @import 'variables'; @import 'error-page'; @import 'print'; @@ -24,3 +23,4 @@ @import 'skins'; @import 'sweetalert'; @import 'autocomplete'; +@import 'selectpicker'; diff --git a/assets/sass/selectpicker.scss b/assets/sass/selectpicker.scss new file mode 100644 index 00000000..eb8fdc7f --- /dev/null +++ b/assets/sass/selectpicker.scss @@ -0,0 +1,23 @@ +@import '~select2/dist/css/select2.min.css'; +@import '~select2-bootstrap-theme/dist/select2-bootstrap.min.css'; + +/* some labels were placed incorrect due to a margin-top: -4px */ +.select2-container .select2-selection--single .select2-selection__rendered { + margin-top: 0; +} +/* make sure the border looks like all other form elements */ +.select2-container--bootstrap .select2-selection { + border-radius: 0; +} +/* placeholder in multi-selects were cut off */ +.select2-search.select2-search--inline .select2-search__field { + width: 100% !important; +} +/* make sure that elements are padded, to allow visual difference to global activities */ +.select2-container--bootstrap .select2-results__options.select2-results__options--nested li.select2-results__option { + padding-left: 30px; +} +/* empty