From 9457a2f264848ca4fdc55e30c3fa2cbf134b22d3 Mon Sep 17 00:00:00 2001 From: Mark Gregory Date: Tue, 16 Jun 2026 13:43:24 +0100 Subject: [PATCH] working ticket now with global vite builer --- Modules/Helpdesk/Resources/assets/js/app.js | 2 + Modules/Helpdesk/package.json | 8 +- package.json | 4 +- resources/js/app.js | 162 +++++++++++++++----- scripts/build-modules.mjs | 37 +++++ 5 files changed, 174 insertions(+), 39 deletions(-) create mode 100644 scripts/build-modules.mjs diff --git a/Modules/Helpdesk/Resources/assets/js/app.js b/Modules/Helpdesk/Resources/assets/js/app.js index 7ba07a91..82be47cc 100644 --- a/Modules/Helpdesk/Resources/assets/js/app.js +++ b/Modules/Helpdesk/Resources/assets/js/app.js @@ -1,5 +1,7 @@ import './bootstrap'; + import Sortable from 'sortablejs'; window.Sortable = Sortable; + console.info('Helpdesk module assets loaded'); diff --git a/Modules/Helpdesk/package.json b/Modules/Helpdesk/package.json index 2e43a68c..4999a653 100644 --- a/Modules/Helpdesk/package.json +++ b/Modules/Helpdesk/package.json @@ -6,8 +6,12 @@ "build": "vite build" }, "devDependencies": { - "laravel-vite-plugin": "^2.0.1", + "laravel-vite-plugin": "^3.1.0", "sass-embedded": "^1.89.2", - "vite": "^7.2.7" + "vite": "^8.0.16" + }, + "dependencies": { + "jquery": "^4.0.0", + "select2": "^4.1.0" } } diff --git a/package.json b/package.json index 431f1ca1..c911bdcf 100644 --- a/package.json +++ b/package.json @@ -5,9 +5,9 @@ "scripts": { "dev": "vite --host 0.0.0.0", "build": "vite build", - "modules:install": "find Modules -maxdepth 2 -name package.json -not -path '*/node_modules/*' -execdir npm install \\;", - "modules:build": "find Modules -maxdepth 2 -name package.json -not -path '*/node_modules/*' -exec sh -c 'cd \"$(dirname \"$1\")\" && node -e \"const p=require(\\\"./package.json\\\"); process.exit(p.scripts && p.scripts.build ? 0 : 1)\" && npm run build || true' sh {} \\;", + "modules:build": "node scripts/build-modules.mjs", "build:all": "npm run build && npm run modules:build", + "modules:install": "find Modules -maxdepth 2 -name package.json -not -path '*/node_modules/*' -execdir npm install \\;", "install:all": "npm install && npm run modules:install" }, "dependencies": { diff --git a/resources/js/app.js b/resources/js/app.js index 1840d1dc..2a77cd04 100644 --- a/resources/js/app.js +++ b/resources/js/app.js @@ -1,15 +1,13 @@ -require("flatpickr"); +require('flatpickr'); import '@fortawesome/fontawesome-free/css/all.min.css'; import Chart from 'chart.js/auto'; import $ from 'jquery'; window.$ = $; - window.jQuery = $; import 'select2'; - import 'select2/dist/css/select2.min.css'; const chartColours = [ @@ -19,14 +17,29 @@ const chartColours = [ '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)); + 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') { @@ -42,18 +55,22 @@ function renderWmsCharts() { ? series.map((item, index) => ({ label: item.label, data: item.data, - backgroundColor: chartColours[index % chartColours.length], - borderColor: chartColours[index % chartColours.length], + 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, - }]; + : [ + { + label: 'Total', + data: values, + backgroundColor: chartColours, + borderColor: 'rgb(255,255,255)', + borderWidth: 2, + }, + ]; new Chart(canvas, { type, @@ -67,34 +84,51 @@ function renderWmsCharts() { plugins: { legend: { labels: { - color: document.documentElement.classList.contains('dark') ? '#e4e4e7' : '#3f3f46', + 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', + scales: + type === 'doughnut' + ? {} + : { + x: { + ticks: { + color: + document.documentElement.classList.contains( + 'dark' + ) + ? '#d4d4d8' + : '#52525b', + }, + grid: { + color: + 'rgba(113,113,122,0.18)', + }, }, - 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)', + }, }, }, - y: { - beginAtZero: true, - ticks: { - precision: 0, - color: document.documentElement.classList.contains('dark') ? '#d4d4d8' : '#52525b', - }, - grid: { - color: 'rgba(113, 113, 122, 0.18)', - }, - }, - }, }, }); @@ -102,5 +136,63 @@ function renderWmsCharts() { }); } -document.addEventListener('DOMContentLoaded', renderWmsCharts); -document.addEventListener('livewire:navigated', renderWmsCharts); +/** + * Initialise Select2 controls. + * + * @returns {void} + */ +function initialiseSelect2() { + if (!window.jQuery?.fn?.select2) { + return; + } + + $('[data-helpdesk-select2]').each(function () { + const $select = $(this); + + if ($select.hasClass('select2-hidden-accessible')) { + $select.select2('destroy'); + } + + const isMultiple = $select.prop('multiple'); + + $select.select2({ + width: '100%', + allowClear: !isMultiple, + closeOnSelect: !isMultiple, + dropdownAutoWidth: true, + placeholder: + $select.find('option[value=""]').first().text() || + (isMultiple ? 'Select options' : 'Select option'), + }); + + $select.off('change.select2-livewire'); + + $select.on('change.select2-livewire', function () { + this.dispatchEvent( + new Event('change', { + bubbles: true, + }) + ); + }); + }); +} + +/** + * Boot page UI. + * + * @returns {void} + */ +function bootUi() { + renderWmsCharts(); + initialiseSelect2(); +} + +document.addEventListener('DOMContentLoaded', bootUi); + +document.addEventListener('livewire:navigated', bootUi); + +document.addEventListener('livewire:init', () => { + Livewire.hook('morphed', () => { + initialiseSelect2(); + }); +}); diff --git a/scripts/build-modules.mjs b/scripts/build-modules.mjs new file mode 100644 index 00000000..7314acaf --- /dev/null +++ b/scripts/build-modules.mjs @@ -0,0 +1,37 @@ +import fs from 'node:fs'; +import path from 'node:path'; +import { execSync } from 'node:child_process'; + +const modulesDir = path.resolve('Modules'); + +for (const moduleName of fs.readdirSync(modulesDir)) { + + const modulePath = path.join(modulesDir, moduleName); + + if (!fs.statSync(modulePath).isDirectory()) { + continue; + } + + const packageJson = path.join(modulePath, 'package.json'); + const viteConfig = path.join(modulePath, 'vite.config.js'); + + if (!fs.existsSync(packageJson) || !fs.existsSync(viteConfig)) { + console.log(`Skipping ${moduleName}`); + continue; + } + + console.log(`Building ${moduleName}`); + + try { + execSync( + 'npm run build', + { + cwd: modulePath, + stdio: 'inherit', + } + ); + } catch (error) { + console.error(`Failed building ${moduleName}`); + process.exit(1); + } +}