From 073ce045b95e5838e5c8e93f5308fd02646d3d84 Mon Sep 17 00:00:00 2001 From: Luca Haid Date: Mon, 4 Aug 2025 12:15:21 +0200 Subject: [PATCH] improved performance of vue modules --- Layout/default/VueViews/Vue.php | 6 - Layout/default/footer.php | 4 + Layout/default/vueHeader.php | 120 +++---- .../WarehouseShippingNoteController.php | 1 - composer.json | 3 +- .../assets/images/the-tool-logo-top.max.png | Bin 0 -> 10046 bytes public/assets/images/the-tool-logo-top.png | Bin 10046 -> 2556 bytes public/cssbundler.php | 53 +++ .../vue/tt-components/css/tt-table.css | 2 +- .../vue/tt-components/tt-autocomplete.js | 324 ++++++++---------- public/plugins/vue/tt-components/tt-button.js | 59 ++-- .../vue/tt-components/tt-datepicker.js | 178 ++++------ public/plugins/vue/tt-components/tt-table.js | 12 +- 13 files changed, 365 insertions(+), 397 deletions(-) create mode 100644 public/assets/images/the-tool-logo-top.max.png create mode 100644 public/cssbundler.php diff --git a/Layout/default/VueViews/Vue.php b/Layout/default/VueViews/Vue.php index 23f7bd02e..c6bab7c16 100644 --- a/Layout/default/VueViews/Vue.php +++ b/Layout/default/VueViews/Vue.php @@ -19,12 +19,6 @@ if (is_dir($vueViewPath)) { $additionalCSS = [ ...$additionalCSS, - 'plugins/daterangepicker/daterangepicker.css', - 'plugins/vue/tt-components/css/tt-table.css', - 'plugins/vue/tt-components/css/tt-tooltip.css', - 'plugins/vue/tt-components/css/tt-loader.css', - 'plugins/vue/tt-components/css/tt-file-gallery.css', - 'plugins/vue/tt-components/css/tt-position-manager.css', ]; /** diff --git a/Layout/default/footer.php b/Layout/default/footer.php index 2fa965d51..1ccb6c055 100644 --- a/Layout/default/footer.php +++ b/Layout/default/footer.php @@ -22,6 +22,10 @@ - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + +
- - +
- - -
-
+
+
\ No newline at end of file diff --git a/application/WarehouseShippingNote/WarehouseShippingNoteController.php b/application/WarehouseShippingNote/WarehouseShippingNoteController.php index 7af7302a1..19009f358 100644 --- a/application/WarehouseShippingNote/WarehouseShippingNoteController.php +++ b/application/WarehouseShippingNote/WarehouseShippingNoteController.php @@ -30,7 +30,6 @@ class WarehouseShippingNoteController extends TTCrud { protected array $defaultOrder = ['key' => 'create', 'order' => 'DESC']; protected array $additionalJSVariables = ['WAREHOUSE_ADMIN' => true]; - protected array $additionalJS = ['js/pages/WarehouseArticle/WarehouseArticleModal.js']; protected array $additionalHead = ['']; protected array $infoMessages = ['create' => 'Lieferschein wurde erstellt.', diff --git a/composer.json b/composer.json index 32e59f052..151670a4a 100644 --- a/composer.json +++ b/composer.json @@ -9,6 +9,7 @@ "phpseclib/phpseclib": "^3.0", "stomp-php/stomp-php": "^5", "phpmailer/phpmailer": "^6.9", - "pear2/net_routeros": "dev-develop@dev" + "pear2/net_routeros": "dev-develop@dev", + "matthiasmullie/minify": "^1.3" } } diff --git a/public/assets/images/the-tool-logo-top.max.png b/public/assets/images/the-tool-logo-top.max.png new file mode 100644 index 0000000000000000000000000000000000000000..a2d33a43381c9609c23cb082734c18a2f6c82e64 GIT binary patch literal 10046 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 UxA%qfF#rGn07*qoM6N<$g3f&iT>t<8 literal 0 HcmV?d00001 diff --git a/public/assets/images/the-tool-logo-top.png b/public/assets/images/the-tool-logo-top.png index a2d33a43381c9609c23cb082734c18a2f6c82e64..4a6cb311758d289cbcec88e7078cb98f73aac043 100644 GIT binary patch delta 2538 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 UxA%qfF#rGn07*qoM6N<$g3f&iT>t<8 diff --git a/public/cssbundler.php b/public/cssbundler.php new file mode 100644 index 000000000..1fcea1f65 --- /dev/null +++ b/public/cssbundler.php @@ -0,0 +1,53 @@ +add($file); + } else { + // Handle missing files gracefully + header("HTTP/1.1 404 Not Found"); + echo "/* File not found: $file */"; + exit; + } + } + + // Return the minified content + return $minifier->minify(); +} + +// Define the array of CSS files to be combined and minified +$cssFiles = [ + 'plugins/daterangepicker/daterangepicker.css', + 'assets/css/bootstrap.min.css', + 'assets/css/app.min.css', + 'plugins/notification/notify.min.css', + 'assets/css/thetool.css', + 'plugins/vue/tt-components/css/tt-table.css', + 'plugins/vue/tt-components/css/tt-tooltip.css', + 'plugins/vue/tt-components/css/tt-loader.css', + 'plugins/vue/tt-components/css/tt-file-gallery.css', + 'plugins/vue/tt-components/css/tt-position-manager.css', +]; + +// Output the combined and minified CSS +echo combineAndMinifyCSS($cssFiles); + +?> \ No newline at end of file diff --git a/public/plugins/vue/tt-components/css/tt-table.css b/public/plugins/vue/tt-components/css/tt-table.css index d52c9e9a9..8598c2012 100644 --- a/public/plugins/vue/tt-components/css/tt-table.css +++ b/public/plugins/vue/tt-components/css/tt-table.css @@ -13,7 +13,7 @@ right: 0; bottom: 0; background-color: rgba(0, 0, 0, 0.1); - background-image: url(data:image/gif;base64,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); + background-image: url(/assets/images/loader-big.gif); background-position: center; background-repeat: no-repeat; background-size: 50px 50px; diff --git a/public/plugins/vue/tt-components/tt-autocomplete.js b/public/plugins/vue/tt-components/tt-autocomplete.js index 291b77531..b77297973 100644 --- a/public/plugins/vue/tt-components/tt-autocomplete.js +++ b/public/plugins/vue/tt-components/tt-autocomplete.js @@ -1,211 +1,181 @@ -//TODO: if autocomplete is focus and the input has not a single character still show "Bitte mindestens 3 Zeichen eingeben" -//TODO: fix the fetchSuggestions function to not show a loading spinner when the input gets cleared -//TODO: fix so we can use arrow keys to navigate the suggestions -// TODO: Implement giving the option without the need of an API || need to use computed property to filter the items -// TODO: Fix the weirdness with timeout and selecting the suggestion - Vue.component('tt-autocomplete', { template: ` -
+ + +
+ + + + + +
+
+ `, props: { - value: {type: [String, Number]}, - label: {type: String, required: false}, - apiUrl: String, - placeholder: {type: String, default: ''}, - items: {type: Array, default: () => []}, - sm: {type: Boolean, default: true}, - row: {type: Boolean, default: false}, - returnText: {type: Boolean, default: false}, - emitDisplayValue: {type: Boolean, default: false}, + value: {type: [String, Number]}, + label: {type: String, required: false}, + apiUrl: String, + placeholder: {type: String, default: ''}, + items: {type: Array, default: () => []}, + sm: {type: Boolean, default: true}, + row: {type: Boolean, default: false}, + returnText: {type: Boolean, default: false}, caseInsensitive: {type: Boolean, default: false}, - }, data() { + }, + data() { return { - window, - displayingItems: [], - oldDisplayValue: '', - displayValue: '', - isLoading: false, - showSuggestions: false, - cursor: -1, + displayValue: '', + displayingItems: [], + isLoading: false, + showSuggestions: false, fetchSuggestionsDebounceTimer: null, - disableIDFetch: false + disableValueWatcher: false, + cursor: -1, }; }, - async mounted() { - this.updateDisplayValue().then(); + watch: { + value: { + handler(newValue) { + if (this.disableValueWatcher) return; + this.updateDisplayValue(newValue); + }, + immediate: true + }, + apiUrl: { + handler: 'fetchSuggestions', + immediate: true + }, }, methods: { - setOldDisplayValue(newValue, oldValue) { - if (this.emitDisplayValue && newValue && typeof this.value !== 'number') { - this.$emit('displayValue', newValue); - } - this.oldDisplayValue = oldValue; - }, - async updateDisplayValue(newValue, oldValue) { - if (this.disableIDFetch) { - this.disableIDFetch = false; + async updateDisplayValue(id) { + if (!id) { + this.displayValue = ''; return; } - if (newValue) { - this.$emit('input', newValue); - this.value = newValue; - } - if (oldValue && !newValue) { - this.$emit('input', ''); - this.displayValue = ''; + if (this.returnText && isNaN(id)) { + this.displayValue = id; + return; } - - if (this.value && this.apiUrl) { - if (this.returnText && isNaN(this.value)) { - this.displayValue = this.value; - return; - } - const response = await axios.get(`${this.apiUrl}${this.apiUrl.includes('?') ? '&' : '?'}autocomplete=1&searchedID=${this.value}`); - this.displayValue = response.data[0].text; - } else if (this.value) { - const selectedItem = this.caseInsensitive ? - this.items.find(item => item.value.toLowerCase() === this.value.toLowerCase()) : this.items.find(item => item.value === this.value) - ; - this.displayValue = selectedItem ? selectedItem.text : this.displayValue; + if (this.apiUrl) { + const response = await axios.get(`${this.apiUrl}${this.apiUrl.includes('?') ? '&' : '?'}autocomplete=1&searchedID=${id}`); + if (response.data[0]) this.displayValue = response.data[0].text; } else { - if (this.returnText === false && !(typeof this.value === 'undefined' || this.value === '')) this.$emit('input', ''); - this.displayValue = this.displayValue.replace(this.oldDisplayValue, ''); + const selectedItem = this.items.find(item => + this.caseInsensitive ? String(item.value).toLowerCase() === String(id).toLowerCase() : item.value === id + ); + if (selectedItem) this.displayValue = selectedItem.text; } }, - onInput(event) { - this.displayValue = event.target.value; + onInput() { if (this.returnText) this.$emit('input', this.displayValue); this.fetchSuggestions(); - }, onFocus() { + }, + onFocus() { this.showSuggestions = true; - }, onBlur() { - setTimeout(() => { - this.showSuggestions = false; - }, 200); - }, fetchSuggestions() { - this.$set(this, 'displayingItems', []); - if (this.displayValue.length < 3) return; - - if (!this.apiUrl) { - - const isNegated = this.displayValue.startsWith('!'); - const substrings = (isNegated ? this.displayValue.slice(1) : this.displayValue).split(' ').map(s => s.toLowerCase()); - this.displayingItems = this.items.filter(item => { - let substringMatch = true; - for (var k = 0, klen = substrings.length; k < klen; ++k) { - if (!item.text.toLowerCase().includes(substrings[k])) { - substringMatch = false; - break; - } - } - return (isNegated && !substringMatch) || (!isNegated && substringMatch); - }) - - return + this.fetchSuggestions(); + }, + onBlur() { + setTimeout(() => this.showSuggestions = false, 200); + }, + fetchSuggestions() { + clearTimeout(this.fetchSuggestionsDebounceTimer); + if (this.displayValue.length < 3) { + this.displayingItems = []; + this.isLoading = false; + return; } - this.isLoading = true; - clearTimeout(this.fetchSuggestionsDebounceTimer); - this.fetchSuggestionsDebounceTimer = setTimeout(() => { - setTimeout(async () => { - if (this.displayValue.length < 3) { - this.displayingItems = []; - this.isLoading = false; - return; - } + this.isLoading = true; + this.cursor = -1; - const response = await axios.get(`${this.apiUrl}${this.apiUrl.includes('?') ? '&' : '?'}autocomplete=1&q=${encodeURIComponent(this.displayValue)}`); - if (response.data?.status === 'error') { - this.displayingItems = []; - } else { - this.displayingItems = response.data - if (response.data.length === 1 && response.data[0].text === this.displayValue) this.selectSuggestion(response.data[0]); - } + if (!this.apiUrl) { + const searchTerms = this.displayValue.toLowerCase().split(' ').filter(s => s); + this.displayingItems = this.items.filter(item => { + const itemText = item.text.toLowerCase(); + return searchTerms.every(term => itemText.includes(term)); + }); this.isLoading = false; + return; + } - this.fetchSuggestionsDebounceTimer = null; - }, 100); - }, 300); // Adjust the 300ms debounce time as needed - }, selectSuggestion(item) { - this.disableIDFetch = true; - this.$emit('input', item.value); + axios.get(`${this.apiUrl}${this.apiUrl.includes('?') ? '&' : '?'}autocomplete=1&q=${encodeURIComponent(this.displayValue)}`) + .then(response => { + this.displayingItems = response.data?.status === 'error' ? [] : response.data; + if (this.displayingItems.length === 1 && this.displayingItems[0].text === this.displayValue) { + this.selectSuggestion(this.displayingItems[0]); + } + }) + .finally(() => this.isLoading = false); + }, 300); + }, + selectSuggestion(item) { + this.disableValueWatcher = true; this.displayValue = item.text; + this.$emit('input', item.value); this.showSuggestions = false; - }, clear() { + this.$nextTick(() => this.disableValueWatcher = false); + }, + selectOnEnter() { + if (this.cursor >= 0 && this.displayingItems[this.cursor]) + this.selectSuggestion(this.displayingItems[this.cursor]); + }, + navigate(direction) { + const itemCount = this.displayingItems.slice(0, 10).length; + if (!itemCount) return; + this.cursor = (this.cursor + direction + itemCount) % itemCount; + }, + clear() { this.displayValue = ''; this.$emit('input', ''); + this.displayingItems = []; } - }, - watch: { - displayValue: {handler: 'setOldDisplayValue', immediate: true}, - value: {handler: 'updateDisplayValue', immediate: true}, - apiUrl: {handler: 'fetchSuggestions', immediate: true}, } -}); +}); \ No newline at end of file diff --git a/public/plugins/vue/tt-components/tt-button.js b/public/plugins/vue/tt-components/tt-button.js index c88220236..a3e15848b 100644 --- a/public/plugins/vue/tt-components/tt-button.js +++ b/public/plugins/vue/tt-components/tt-button.js @@ -1,25 +1,18 @@ -// noinspection JSCheckFunctionSignatures Vue.component('tt-button', { //language=Vue template: ` - - - - - + + + + `, props: { sm: {type: Boolean, default: false}, @@ -32,26 +25,20 @@ Vue.component('tt-button', { }, computed: { buttonClasses() { - const classes = { - 'btn-sm': this.sm, - 'btn-loading': this.loading - } - - if (this.additionalClass) { - this.additionalClass.split(' ').forEach(className => { - classes[className] = true - }) - } - - return classes + const classes = []; + if (this.sm) classes.push('btn-sm'); + if (this.loading) classes.push('btn-loading'); + if (this.additionalClass) classes.push(...this.additionalClass.split(' ')); + return classes; } }, methods: { handleClick(event) { - if (this.loading) return event.preventDefault(); - if (typeof this.confirmText === 'string' && !confirm(this.confirmText)) return event.preventDefault(); - - this.$emit('click', event) + if (this.loading || (this.confirmText && !confirm(this.confirmText))) { + event.preventDefault(); + return; + } + this.$emit('click', event); } } -}) +}); \ No newline at end of file diff --git a/public/plugins/vue/tt-components/tt-datepicker.js b/public/plugins/vue/tt-components/tt-datepicker.js index 1feafd0b4..736af899a 100644 --- a/public/plugins/vue/tt-components/tt-datepicker.js +++ b/public/plugins/vue/tt-components/tt-datepicker.js @@ -12,141 +12,111 @@ Vue.component('tt-date-picker', { dateRange: { type: Boolean, default: true }, }, template: ` -
- - - - {{ hint }} -
- `, +
+ + + + {{ hint }} +
+ `, data() { return { - inputValue: '', isInitialized: false, moment: window.moment, locale: { - // ... (keep your existing locale object) + format: 'DD.MM.YYYY HH:mm', + separator: ' - ', + applyLabel: 'Übernehmen', + cancelLabel: 'Abbrechen', + fromLabel: 'Von', + toLabel: 'Bis', + customRangeLabel: 'Benutzerdef.', + weekLabel: 'W', + daysOfWeek: ['So', 'Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa'], + monthNames: ['Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember'], + firstDay: 1 }, } }, - mounted() { - this.isInitialized = true; - const datePickerOptions = { - autoUpdateInput: true, + async mounted() { + const loadScript = (src, check) => new Promise((resolve, reject) => { + if (check()) return resolve(); + const script = document.createElement('script'); + script.src = src; + script.onload = resolve; + script.onerror = () => reject(new Error(`Failed to load script: ${src}`)); + document.head.appendChild(script); + }); + + await loadScript('/js/jquery.min.js', () => typeof jQuery !== 'undefined'); + await loadScript('/plugins/daterangepicker/daterangepicker.js', () => typeof $?.fn?.daterangepicker !== 'undefined'); + + const pickerOptions = { + autoUpdateInput: false, singleDatePicker: !this.dateRange, timePicker: true, timePicker24Hour: true, locale: this.locale, + startDate: this.dateRange ? (this.value?.from ? this.moment.unix(this.value.from) : this.moment()) : (this.value ? this.moment.unix(this.value) : this.moment()), + endDate: this.dateRange ? (this.value?.to ? this.moment.unix(this.value.to) : this.moment()) : (this.value ? this.moment.unix(this.value) : this.moment()), }; - if (this.dateRange) { - datePickerOptions.startDate = this.value?.from ? this.moment.unix(this.value.from) : undefined; - datePickerOptions.endDate = this.value?.to ? this.moment.unix(this.value.to) : undefined; - } else { - datePickerOptions.startDate = this.value ? this.moment.unix(this.value) : undefined; - } + const $input = $(this.$refs.input); + $input.daterangepicker(pickerOptions); + this.updateInputValue(this.value); - $(this.$refs.input).daterangepicker(datePickerOptions); - - const _this = this; - $(this.$refs.input).on('apply.daterangepicker', function (ev, picker) { - if (_this.dateRange) { - _this.$emit('input', { - from: picker.startDate.unix(), - to: picker.endDate.unix() - }); - $(_this.$refs.input).val(picker.startDate.format(_this.locale.format) + _this.locale.separator + picker.endDate.format(_this.locale.format)); - } else { - _this.$emit('input', picker.startDate.unix()); - $(_this.$refs.input).val(picker.startDate.format(_this.locale.format)); - } + $input.on('apply.daterangepicker', (ev, picker) => { + const val = this.dateRange + ? { from: picker.startDate.unix(), to: picker.endDate.unix() } + : picker.startDate.unix(); + this.$emit('input', val); + this.updateInputValue(val); }); - function checkIfAppliedElseClear() { - if (_this.dateRange) { - if (_this.value && _this.value.from && _this.value.to) return; - } else { - if (_this.value) return; - } - $(_this.$refs.input).val(''); - } + $input.on('cancel.daterangepicker', () => { + this.$emit('input', undefined); + this.updateInputValue(undefined); + }); - function clearIfCancelled() { - _this.$emit('input', _this.dateRange ? {from: null, to: null} : null); - $(_this.$refs.input).val(''); - } - - $(this.$refs.input).on('cancel.daterangepicker', clearIfCancelled); - $(this.$refs.input).on('hide.daterangepicker', checkIfAppliedElseClear.bind(this)); - - // Clear input field if value is not set - if (_this.dateRange) { - if (!this.value || this.value.from === null || this.value.to === null) { - $(_this.$refs.input).val(''); - } - } else { - if (!this.value) { - $(_this.$refs.input).val(''); - } - } - - // Add click event listener to the document - document.addEventListener('click', this.handleOutsideClick); + this.isInitialized = true; }, methods: { - handleOutsideClick(event) { - const datepicker = document.querySelector('.daterangepicker'); - const input = this.$refs.input; - - if (datepicker && !datepicker.contains(event.target) && event.target !== input) { - if (input.parentElement.tagName.toLowerCase() === 'div' && input.parentElement.classList.contains('form-group')) { - return; - } - $(this.$refs.input).data('daterangepicker').hide(); + updateInputValue(val) { + const $input = $(this.$refs.input); + if (this.dateRange) { + if (val?.from && val?.to) { + const from = this.moment.unix(val.from).format(this.locale.format); + const to = this.moment.unix(val.to).format(this.locale.format); + $input.val(from + this.locale.separator + to); + } else $input.val(''); + } else { + if (val) $input.val(this.moment.unix(val).format(this.locale.format)); + else $input.val(''); } }, - setStartDate(date) { - $(this.$refs.input).data('daterangepicker').setStartDate(date); - } + setStartDate: (date) => $(this.$refs.input).data('daterangepicker').setStartDate(date) }, watch: { - value: function (newVal) { + value(newVal) { if (!this.isInitialized) return; + this.updateInputValue(newVal); + const datePicker = $(this.$refs.input).data('daterangepicker'); if (this.dateRange) { - if (!newVal || newVal.from === null || newVal.to === null) { - $(this.$refs.input).val(''); - } else { - datePicker.setStartDate(this.moment.unix(newVal.from)); - datePicker.setEndDate(this.moment.unix(newVal.to)); - } + datePicker.setStartDate(newVal?.from ? this.moment.unix(newVal.from) : this.moment()); + datePicker.setEndDate(newVal?.to ? this.moment.unix(newVal.to) : this.moment()); } else { - if (!newVal) { - $(this.$refs.input).val(''); - } else { - datePicker.setStartDate(this.moment.unix(newVal)); - datePicker.setEndDate(this.moment.unix(newVal)); - } + const date = newVal ? this.moment.unix(newVal) : this.moment(); + datePicker.setStartDate(date); + datePicker.setEndDate(date); } } }, beforeDestroy() { - $(this.$refs.input).off('apply.daterangepicker'); - document.removeEventListener('click', this.handleOutsideClick); + const picker = $(this.$refs.input).data('daterangepicker'); + if (picker) picker.remove(); }, -}) +}); \ No newline at end of file diff --git a/public/plugins/vue/tt-components/tt-table.js b/public/plugins/vue/tt-components/tt-table.js index 40ee7d451..ecfede3fe 100644 --- a/public/plugins/vue/tt-components/tt-table.js +++ b/public/plugins/vue/tt-components/tt-table.js @@ -201,9 +201,9 @@ Vue.component('tt-table', { .isValid() ? moment.unix(row[key]).format('DD.MM.YYYY HH:mm') : moment(row[key]) .format('DD.MM.YYYY HH:mm')) : '' }} - - - + {{ autoCompleteData[key] && autoCompleteData[key][row[key]] ? autoCompleteData[key][row[key]]['title'] : row[key] }} @@ -236,9 +236,9 @@ Vue.component('tt-table', { }} {{ columns[key].filterOptions.find(option => option.value.toString() === row[key].toString())?.text }} {{ window.moment(row[key] * 1000).format('DD.MM.YYYY HH:mm:ss') }} - - - + {{ autoCompleteData[key] && autoCompleteData[key][row[key]] ? autoCompleteData[key][row[key]]['title'] : row[key] }}