diff --git a/app/Core/Template.php b/app/Core/Template.php index 0f397fd28..fe820aa5f 100644 --- a/app/Core/Template.php +++ b/app/Core/Template.php @@ -680,7 +680,11 @@ public function displayNotification(): string if (session()->exists("confettiInYourFace") && session("confettiInYourFace") === true) { $notification .= app('blade.compiler')::render( - '', + '', [] ); @@ -754,7 +758,10 @@ public function displayInlineNotification(): string if (session()->exists("confettiInYourFace") && session("confettiInYourFace") === true) { $notification .= app('blade.compiler')::render( - '', + '', [] ); diff --git a/app/Domain/Comments/Templates/submodules/generalComment.sub.php b/app/Domain/Comments/Templates/submodules/generalComment.sub.php index 748c8c1c6..8db5882d5 100644 --- a/app/Domain/Comments/Templates/submodules/generalComment.sub.php +++ b/app/Domain/Comments/Templates/submodules/generalComment.sub.php @@ -183,7 +183,10 @@ function toggleCommentBoxes(id, formHash) { } jQuery(".confetti").click(function(){ - confetti.start(); + confetti({ + spread: 70, + origin: { y: 1.2 }, + }); }); function respondToVisibility(element, callback) { diff --git a/app/Domain/Dashboard/Js/dashboardController.js b/app/Domain/Dashboard/Js/dashboardController.js index 66bc8c40c..ae5dfa958 100644 --- a/app/Domain/Dashboard/Js/dashboardController.js +++ b/app/Domain/Dashboard/Js/dashboardController.js @@ -202,7 +202,7 @@ leantime.dashboardController = (function () { label: leantime.i18n.__("label.done_todos"), backgroundColor: leantime.dashboardController.chartColors.green, borderColor: leantime.dashboardController.chartColors.green, - data: actualData['done']['data'], + data: actualData.done.data, fill: true, lineTension: 0, pointRadius:0, @@ -211,7 +211,7 @@ leantime.dashboardController = (function () { label: leantime.i18n.__("label.progress_todos"), backgroundColor: leantime.dashboardController.chartColors.yellow, borderColor: leantime.dashboardController.chartColors.yellow, - data: actualData['progress']['data'], + data: actualData.progress.data, fill: true, lineTension: 0, pointRadius:0, @@ -221,7 +221,7 @@ leantime.dashboardController = (function () { label: leantime.i18n.__("label.new_todos"), backgroundColor: leantime.dashboardController.chartColors.red, borderColor: leantime.dashboardController.chartColors.red, - data: actualData['open']['data'], + data: actualData.open.data, fill: true, lineTension: 0, pointRadius:0, @@ -296,10 +296,10 @@ leantime.dashboardController = (function () { jQuery("#" + id).click( function (event) { - chart.data.datasets[0].data = actualData['done']['data']; + chart.data.datasets[0].data = actualData.done.data; - chart.data.datasets[1].data = actualData['progress']['data']; - chart.data.datasets[2].data = actualData['open']['data']; + chart.data.datasets[1].data = actualData.progress.data; + chart.data.datasets[2].data = actualData.open.data; chart.options.scales.y.title.text = label; diff --git a/app/Domain/Gamecenter/Js/game-snake.js b/app/Domain/Gamecenter/Js/game-snake.js index b85109aa4..8cedb629c 100644 --- a/app/Domain/Gamecenter/Js/game-snake.js +++ b/app/Domain/Gamecenter/Js/game-snake.js @@ -160,22 +160,22 @@ SNAKE.Snake = SNAKE.Snake || (function() { // ----- public variables ----- me.snakeBody = {}; - me.snakeBody["b0"] = new SnakeBlock(); // create snake head - me.snakeBody["b0"].row = config.startRow || 1; - me.snakeBody["b0"].col = config.startCol || 1; - me.snakeBody["b0"].xPos = me.snakeBody["b0"].row * playingBoard.getBlockWidth(); - me.snakeBody["b0"].yPos = me.snakeBody["b0"].col * playingBoard.getBlockHeight(); - me.snakeBody["b0"].elm = createSnakeElement(); - me.snakeBody["b0"].elmStyle = me.snakeBody["b0"].elm.style; - playingBoard.getBoardContainer().appendChild( me.snakeBody["b0"].elm ); - me.snakeBody["b0"].elm.style.left = me.snakeBody["b0"].xPos + "px"; - me.snakeBody["b0"].elm.style.top = me.snakeBody["b0"].yPos + "px"; - me.snakeBody["b0"].next = me.snakeBody["b0"]; - me.snakeBody["b0"].prev = me.snakeBody["b0"]; + me.snakeBody.b0 = new SnakeBlock(); // create snake head + me.snakeBody.b0.row = config.startRow || 1; + me.snakeBody.b0.col = config.startCol || 1; + me.snakeBody.b0.xPos = me.snakeBody.b0.row * playingBoard.getBlockWidth(); + me.snakeBody.b0.yPos = me.snakeBody.b0.col * playingBoard.getBlockHeight(); + me.snakeBody.b0.elm = createSnakeElement(); + me.snakeBody.b0.elmStyle = me.snakeBody.b0.elm.style; + playingBoard.getBoardContainer().appendChild( me.snakeBody.b0.elm ); + me.snakeBody.b0.elm.style.left = me.snakeBody.b0.xPos + "px"; + me.snakeBody.b0.elm.style.top = me.snakeBody.b0.yPos + "px"; + me.snakeBody.b0.next = me.snakeBody.b0; + me.snakeBody.b0.prev = me.snakeBody.b0; me.snakeLength = 1; - me.snakeHead = me.snakeBody["b0"]; - me.snakeTail = me.snakeBody["b0"]; + me.snakeHead = me.snakeBody.b0; + me.snakeTail = me.snakeBody.b0; me.snakeHead.elm.className = me.snakeHead.elm.className.replace(/\bsnake-snakebody-dead\b/,''); me.snakeHead.elm.id = "snake-snakehead-alive"; me.snakeHead.elm.className += " snake-snakebody-alive"; diff --git a/app/Domain/Help/Js/helperController.js b/app/Domain/Help/Js/helperController.js index c79db7b44..2597127d9 100644 --- a/app/Domain/Help/Js/helperController.js +++ b/app/Domain/Help/Js/helperController.js @@ -203,7 +203,10 @@ leantime.helperController = (function () { scrollTo:true, when: { show: function() { - confetti.start(); + confetti({ + spread: 70, + origin: { y: 1.2 }, + }); } }, advanceOn: '.headmenu click' diff --git a/app/Views/Templates/sections/header.blade.php b/app/Views/Templates/sections/header.blade.php index 3398e3ba8..16b4c9c09 100644 --- a/app/Views/Templates/sections/header.blade.php +++ b/app/Views/Templates/sections/header.blade.php @@ -43,6 +43,11 @@ @dispatchEvent('afterMainScriptTag') + + @foreach ($themeScripts as $script) diff --git a/package-lock.json b/package-lock.json index b3ccb9c59..994823bb1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "leantime", - "version": "3.1.4", + "version": "3.2.0-beta", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "leantime", - "version": "3.1.4", + "version": "3.2.0-beta", "license": "AGPL-3.0", "dependencies": { "@assuradeurengilde/fontawesome-iconpicker": "^3.2.3", @@ -19,6 +19,7 @@ "@sentry/browser": "^7.109.0", "@sentry/webpack-plugin": "^2.16.1", "ajv": "^8.13.0", + "canvas-confetti": "^1.9.3", "chart.js": "^3.6.0", "chartjs-adapter-luxon": "^1.3.1", "chosen-js": "^1.8.7", @@ -4935,6 +4936,15 @@ } ] }, + "node_modules/canvas-confetti": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/canvas-confetti/-/canvas-confetti-1.9.3.tgz", + "integrity": "sha512-rFfTURMvmVEX1gyXFgn5QMn81bYk70qa0HLzcIOSVEyl57n6o9ItHeBtUSWdvKAPY0xlvBHno4/v3QPrT83q9g==", + "funding": { + "type": "donate", + "url": "https://www.paypal.me/kirilvatev" + } + }, "node_modules/chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", diff --git a/package.json b/package.json index 90a155dc6..d98c5840d 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "@sentry/browser": "^7.109.0", "@sentry/webpack-plugin": "^2.16.1", "ajv": "^8.13.0", + "canvas-confetti": "^1.9.3", "chart.js": "^3.6.0", "chartjs-adapter-luxon": "^1.3.1", "chosen-js": "^1.8.7", @@ -23,8 +24,8 @@ "datatables.net-rowgroup": "^1.4.1", "datatables.net-rowreorder": "^1.4.1", "fullcalendar": "^6.1.11", - "htmx.org": "^1.9.12", "gridstack": "^10.1.2", + "htmx.org": "^1.9.12", "ical.js": "^1.5.0", "imagesloaded": "^5.0.0", "isotope-layout": "^3.0.6", diff --git a/public/assets/js/libs/confetti/js/confetti.js b/public/assets/js/libs/confetti/js/confetti.js index fb0e3c14e..da2efebf8 100644 --- a/public/assets/js/libs/confetti/js/confetti.js +++ b/public/assets/js/libs/confetti/js/confetti.js @@ -8,8 +8,8 @@ var confetti = (function () { let cy = ''; let confetti = []; - const confettiCount = 500; - const gravity = 0.7; + const confettiCount = 50; + const gravity = 1.2; const terminalVelocity = 5; const drag = 0.075; const colors = [ @@ -85,7 +85,8 @@ var confetti = (function () { velocity: { x: randomRange(-25, 25), - y: randomRange(0, -50) } }); + y: randomRange(0, -50) } + }); } @@ -93,6 +94,7 @@ var confetti = (function () { //---------Render----------- let render = () => { + ctx.clearRect(0, 0, canvas.width, canvas.height); confetti.forEach((confetto, index) => { diff --git a/public/dist/mix-manifest.json b/public/dist/mix-manifest.json index 24ff592cd..5e350dc6c 100644 --- a/public/dist/mix-manifest.json +++ b/public/dist/mix-manifest.json @@ -1,19 +1,62 @@ { - "/js/compiled-htmx.3.1.4.min.js": "/js/compiled-htmx.3.1.4.min.js", - "/js/compiled-htmx-headSupport.3.1.4.min.js": "/js/compiled-htmx-headSupport.3.1.4.min.js", - "/css/main.3.1.4.min.css": "/css/main.3.1.4.min.css", - "/css/editor.3.1.4.min.css": "/css/editor.3.1.4.min.css", - "/css/app.3.1.4.min.css": "/css/app.3.1.4.min.css", - "/js/compiled-footer.3.1.4.min.js": "/js/compiled-footer.3.1.4.min.js", - "/js/compiled-app.3.1.4.min.js": "/js/compiled-app.3.1.4.min.js", - "/js/compiled-frameworks.3.1.4.min.js": "/js/compiled-frameworks.3.1.4.min.js", - "/js/compiled-framework-plugins.3.1.4.min.js": "/js/compiled-framework-plugins.3.1.4.min.js", - "/js/compiled-global-component.3.1.4.min.js": "/js/compiled-global-component.3.1.4.min.js", - "/js/compiled-calendar-component.3.1.4.min.js": "/js/compiled-calendar-component.3.1.4.min.js", - "/js/compiled-table-component.3.1.4.min.js": "/js/compiled-table-component.3.1.4.min.js", - "/js/compiled-editor-component.3.1.4.min.js": "/js/compiled-editor-component.3.1.4.min.js", - "/js/compiled-gantt-component.3.1.4.min.js": "/js/compiled-gantt-component.3.1.4.min.js", - "/js/compiled-chart-component.3.1.4.min.js": "/js/compiled-chart-component.3.1.4.min.js", + "/js/Auth/Js/authController.js": "/js/Auth/Js/authController.js", + "/js/Calendar/Js/calendarController.js": "/js/Calendar/Js/calendarController.js", + "/js/Canvas/Js/canvasController.js": "/js/Canvas/Js/canvasController.js", + "/js/Clients/Js/clientsController.js": "/js/Clients/Js/clientsController.js", + "/js/Comments/Js/commentsController.js": "/js/Comments/Js/commentsController.js", + "/js/Cpcanvas/Js/cpCanvasController.js": "/js/Cpcanvas/Js/cpCanvasController.js", + "/js/Dashboard/Js/dashboardController.js": "/js/Dashboard/Js/dashboardController.js", + "/js/Dbmcanvas/Js/dbmCanvasController.js": "/js/Dbmcanvas/Js/dbmCanvasController.js", + "/js/Eacanvas/Js/eaCanvasController.js": "/js/Eacanvas/Js/eaCanvasController.js", + "/js/Emcanvas/Js/emCanvasController.js": "/js/Emcanvas/Js/emCanvasController.js", + "/js/Gamecenter/Js/game-snake.js": "/js/Gamecenter/Js/game-snake.js", + "/js/Goalcanvas/Js/goalCanvasController.js": "/js/Goalcanvas/Js/goalCanvasController.js", + "/js/Help/Js/helperController.js": "/js/Help/Js/helperController.js", + "/js/Help/Js/helperRepository.js": "/js/Help/Js/helperRepository.js", + "/js/Ideas/Js/ideasController.js": "/js/Ideas/Js/ideasController.js", + "/js/Insightscanvas/Js/insightsCanvasController.js": "/js/Insightscanvas/Js/insightsCanvasController.js", + "/js/Lbmcanvas/Js/lbmCanvasController.js": "/js/Lbmcanvas/Js/lbmCanvasController.js", + "/js/Leancanvas/Js/leanCanvasController.js": "/js/Leancanvas/Js/leanCanvasController.js", + "/js/Menu/Js/menuController.js": "/js/Menu/Js/menuController.js", + "/js/Menu/Js/menuRepository.js": "/js/Menu/Js/menuRepository.js", + "/js/Minempathycanvas/Js/risksCanvasController.js": "/js/Minempathycanvas/Js/risksCanvasController.js", + "/js/Obmcanvas/Js/obmCanvasController.js": "/js/Obmcanvas/Js/obmCanvasController.js", + "/js/Projects/Js/projectsController.js": "/js/Projects/Js/projectsController.js", + "/js/Reactions/Js/reactionsController.js": "/js/Reactions/Js/reactionsController.js", + "/js/Retroscanvas/Js/retroCanvasController.js": "/js/Retroscanvas/Js/retroCanvasController.js", + "/js/Riskscanvas/Js/risksCanvasController.js": "/js/Riskscanvas/Js/risksCanvasController.js", + "/js/Sbcanvas/Js/sbCanvasController.js": "/js/Sbcanvas/Js/sbCanvasController.js", + "/js/Setting/Js/settingController.js": "/js/Setting/Js/settingController.js", + "/js/Setting/Js/settingRepository.js": "/js/Setting/Js/settingRepository.js", + "/js/Setting/Js/settingService.js": "/js/Setting/Js/settingService.js", + "/js/Smcanvas/Js/smCanvasController.js": "/js/Smcanvas/Js/smCanvasController.js", + "/js/Sqcanvas/Js/sqCanvasController.js": "/js/Sqcanvas/Js/sqCanvasController.js", + "/js/Swotcanvas/Js/swotCanvasController.js": "/js/Swotcanvas/Js/swotCanvasController.js", + "/js/Tickets/Js/ticketsController.js": "/js/Tickets/Js/ticketsController.js", + "/js/Tickets/Js/ticketsRepository.js": "/js/Tickets/Js/ticketsRepository.js", + "/js/Timesheets/Js/timesheetsController.js": "/js/Timesheets/Js/timesheetsController.js", + "/js/Users/Js/usersController.js": "/js/Users/Js/usersController.js", + "/js/Users/Js/usersRepository.js": "/js/Users/Js/usersRepository.js", + "/js/Users/Js/usersService.js": "/js/Users/Js/usersService.js", + "/js/Valuecanvas/Js/valueCanvasController.js": "/js/Valuecanvas/Js/valueCanvasController.js", + "/js/Widgets/Js/Widgetcontroller.js": "/js/Widgets/Js/Widgetcontroller.js", + "/js/Wiki/Js/wikiController.js": "/js/Wiki/Js/wikiController.js", + "/js/compiled-htmx.3.2.0-beta.min.js": "/js/compiled-htmx.3.2.0-beta.min.js", + "/js/compiled-htmx-headSupport.3.2.0-beta.min.js": "/js/compiled-htmx-headSupport.3.2.0-beta.min.js", + "/js/authController.js": "/js/authController.js", + "/css/main.3.2.0-beta.min.css": "/css/main.3.2.0-beta.min.css", + "/css/editor.3.2.0-beta.min.css": "/css/editor.3.2.0-beta.min.css", + "/css/app.3.2.0-beta.min.css": "/css/app.3.2.0-beta.min.css", + "/js/compiled-footer.3.2.0-beta.min.js": "/js/compiled-footer.3.2.0-beta.min.js", + "/js/compiled-app.3.2.0-beta.min.js": "/js/compiled-app.3.2.0-beta.min.js", + "/js/compiled-frameworks.3.2.0-beta.min.js": "/js/compiled-frameworks.3.2.0-beta.min.js", + "/js/compiled-framework-plugins.3.2.0-beta.min.js": "/js/compiled-framework-plugins.3.2.0-beta.min.js", + "/js/compiled-global-component.3.2.0-beta.min.js": "/js/compiled-global-component.3.2.0-beta.min.js", + "/js/compiled-calendar-component.3.2.0-beta.min.js": "/js/compiled-calendar-component.3.2.0-beta.min.js", + "/js/compiled-table-component.3.2.0-beta.min.js": "/js/compiled-table-component.3.2.0-beta.min.js", + "/js/compiled-editor-component.3.2.0-beta.min.js": "/js/compiled-editor-component.3.2.0-beta.min.js", + "/js/compiled-gantt-component.3.2.0-beta.min.js": "/js/compiled-gantt-component.3.2.0-beta.min.js", + "/js/compiled-chart-component.3.2.0-beta.min.js": "/js/compiled-chart-component.3.2.0-beta.min.js", "/images/03-1.png": "/images/03-1.png", "/images/32px.png": "/images/32px.png", "/images/40px.png": "/images/40px.png", diff --git a/webpack.mix.js b/webpack.mix.js index d440d9c12..63e18355e 100644 --- a/webpack.mix.js +++ b/webpack.mix.js @@ -3,6 +3,30 @@ const glob = require('glob'); const path = require('path'); const version = pjson.version; +const fs = require("fs"); + +// Helper to get all files of a given extension in a given directory and its subfolders. +function getFilesRecursive(dir, type) { + // The list of files that we will return. + let files = [] + // Loop everything in given location. + fs.readdirSync(dir).forEach(file => { + let fileName = `${dir}/${file}` + // Add if its a file and it is of the correct file type. + if(fs.statSync(fileName).isFile() && fileName.endsWith(type)) { + files.push(fileName) + } + // Process subfolder. + if(!fs.statSync(fileName).isFile()) { + // Recusively loop this function for the subfolder. + files = files.concat(getFilesRecursive(fileName, type)) + } + }) + return files +} + + + let mix = require('laravel-mix'); require('laravel-mix-eslint'); require('mix-tailwindcss'); @@ -10,8 +34,22 @@ require('mix-tailwindcss'); require('dotenv').config({ path: 'config/.env' }); mix - .setPublicPath('public/dist') // this is the URL to place assets referenced in the CSS/JS - .setResourceRoot(`../`) // this is what to prefix the URL with + .setPublicPath('public/dist') + .setResourceRoot(`../`); + +/* + +//Draft for file based js controller loading +getFilesRecursive('app/Domain', '.js').forEach(file => { + subfolder = file.match(/(.*)[\/\\]/)[1]||''; // 'src/js/libraries' + subfolder = subfolder.replace('app/Domain', ''); // '/libraries' + mix.js(file, 'js' + subfolder); +}); +*/ + + + // this is the URL to place assets referenced in the CSS/JS + mix // this is what to prefix the URL with .combine('./public/assets/js/libs/prism/prism.js', `public/dist/js/compiled-footer.${version}.min.js`) .js('./public/assets/js/app/htmx.js', `public/dist/js/compiled-htmx.${version}.min.js`) .js('./public/assets/js/app/htmx-headSupport.js', `public/dist/js/compiled-htmx-headSupport.${version}.min.js`) @@ -45,7 +83,7 @@ mix "./node_modules/@popperjs/core/dist/umd/popper.js", "./node_modules/tippy.js/dist/tippy-bundle.umd.js", "./public/assets/js/libs/slimselect.min.js", - "./public/assets/js/libs/confetti/js/confetti.js", + "./node_modules/canvas-confetti/dist/confetti.browser.js", "./public/assets/js/libs/jquery.nyroModal/js/jquery.nyroModal.custom.js", "./public/assets/js/libs/uppy/uppy.js", "./node_modules/croppie/croppie.js",