require('flatpickr'); import '@fortawesome/fontawesome-free/css/all.min.css'; import Chart from 'chart.js/auto'; import $ from 'jquery'; window.$ = $; window.jQuery = $; import select2Factory from 'select2'; import 'select2/dist/css/select2.min.css'; import '../css/wms-select2.css'; if (typeof select2Factory === 'function') { select2Factory(window, $); } const chartColours = [ 'rgb(8, 145, 178)', 'rgb(37, 99, 235)', 'rgb(79, 70, 229)', 'rgb(14, 116, 144)', ]; /** * Parse JSON attribute safely. * * @param {HTMLElement} element * @param {string} attribute * @param {Array} fallback * @returns {*} */ function parseJsonAttribute(element, attribute, fallback = []) { try { return JSON.parse( element.getAttribute(attribute) || JSON.stringify(fallback) ); } catch (error) { return fallback; } } /** * Render dashboard charts. * * @returns {void} */ function renderWmsCharts() { document.querySelectorAll('[data-wms-chart]').forEach((canvas) => { if (canvas.dataset.rendered === 'true') { return; } const type = canvas.dataset.wmsChart; const labels = parseJsonAttribute(canvas, 'data-labels'); const series = parseJsonAttribute(canvas, 'data-series'); const values = parseJsonAttribute(canvas, 'data-values'); const datasets = series.length ? series.map((item, index) => ({ label: item.label, data: item.data, backgroundColor: chartColours[index % chartColours.length], borderColor: chartColours[index % chartColours.length], borderWidth: 2, borderRadius: 8, })) : [ { label: 'Total', data: values, backgroundColor: chartColours, borderColor: 'rgb(255,255,255)', borderWidth: 2, }, ]; canvas.wmsChart = new Chart(canvas, { type, data: { labels, datasets, }, options: { responsive: true, maintainAspectRatio: false, plugins: { legend: { labels: { color: document.documentElement.classList.contains( 'dark' ) ? '#e4e4e7' : '#3f3f46', boxWidth: 12, boxHeight: 12, }, }, }, scales: type === 'doughnut' ? {} : { x: { ticks: { color: document.documentElement.classList.contains( 'dark' ) ? '#d4d4d8' : '#52525b', }, grid: { color: 'rgba(113,113,122,0.18)', }, }, y: { beginAtZero: true, ticks: { precision: 0, color: document.documentElement.classList.contains( 'dark' ) ? '#d4d4d8' : '#52525b', }, grid: { color: 'rgba(113,113,122,0.18)', }, }, }, }, }); canvas.dataset.rendered = 'true'; }); } function livewireComponentFor(element) { let current = element; while (current && current !== document.documentElement) { if (current.hasAttribute?.('wire:id')) { if (!window.Livewire) { return null; } return window.Livewire.find(current.dataset.wireId); } current = current.parentElement; } return null; } function setLivewireProperty(element, model, value) { const component = livewireComponentFor(element); if (!component || !model) { return; } component.set(model, value === '' ? null : value); } function normaliseSelect2Options($select) { const isMultiple = $select.prop('multiple'); const $field = $select.closest('.wms-select2-field'); if (!isMultiple && $select.find('option[value=""]').length === 0) { $select.prepend(new Option('', '', false, false)); } return { theme: 'wms', width: '100%', allowClear: !isMultiple, closeOnSelect: !isMultiple, dropdownAutoWidth: false, minimumResultsForSearch: 0, dropdownParent: $field.length ? $field : window.jQuery(document.body), placeholder: $select.data('placeholder') || $select.attr('placeholder') || (isMultiple ? 'Select options' : 'Search and select'), sorter(data) { return data.sort((first, second) => (first.text || '').localeCompare(second.text || '', undefined, { sensitivity: 'base', ignorePunctuation: true, }) ); }, }; } function select2Selector() { return 'select[data-wms-select2], select[data-helpdesk-select2], select[data-company-country-select2], select.wms-select2-control'; } function initialiseSelect2Element(select) { if (!window.jQuery?.fn?.select2 || !select) { return false; } const $select = window.jQuery(select); if ($select.hasClass('select2-hidden-accessible')) { return true; } $select.select2(normaliseSelect2Options($select)); $select.off('change.wms-select2-livewire'); $select.on('change.wms-select2-livewire', function () { setLivewireProperty(this, this.dataset.wireModel, $select.val()); }); $select.off('select2:open.wms-select2-focus'); $select.on('select2:open.wms-select2-focus', function () { window.setTimeout(() => { const search = document.querySelector('.select2-container--open .select2-search__field'); if (search) { search.focus(); } }, 0); }); return true; } /** * Initialise all WMS Select2 controls currently on the page. * * @returns {void} */ function initialiseSelect2() { if (!window.jQuery?.fn?.select2) { window.setTimeout(initialiseSelect2, 100); return; } document.querySelectorAll(select2Selector()).forEach(initialiseSelect2Element); } /** * Selects inside Livewire/Navigate content can appear after DOMContentLoaded. * Initialise on first interaction as a safety net, then open Select2 immediately. */ document.addEventListener('mousedown', (event) => { const select = event.target.closest?.(select2Selector()); if (!select || select.classList.contains('select2-hidden-accessible')) { return; } if (initialiseSelect2Element(select)) { event.preventDefault(); window.setTimeout(() => window.jQuery(select).select2('open'), 0); } }, true); document.addEventListener('focusin', (event) => { const select = event.target.closest?.(select2Selector()); if (select) { initialiseSelect2Element(select); } }, true); /** * Boot page UI. * * @returns {void} */ function bootUi() { renderWmsCharts(); initialiseSelect2(); window.setTimeout(initialiseSelect2, 50); window.setTimeout(initialiseSelect2, 250); window.setTimeout(initialiseSelect2, 750); } document.addEventListener('DOMContentLoaded', bootUi); document.addEventListener('livewire:navigated', bootUi); document.addEventListener('livewire:init', () => { if (!window.Livewire?.hook) { return; } window.Livewire.hook('morphed', () => { window.setTimeout(initialiseSelect2, 0); }); });