From 3e694958420082b102b1a8ec9a702eba7dae9358 Mon Sep 17 00:00:00 2001 From: SimonGschnell Date: Tue, 12 Aug 2025 09:53:45 +0200 Subject: [PATCH 1/5] fix(Dashboard drag&drop): behavior of dragged widgets when they exceed the grid limits, and ensures all widget clones are always deleted --- public/js/components/Drop/Grid.js | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/public/js/components/Drop/Grid.js b/public/js/components/Drop/Grid.js index 74d67e49d..ae1a6504c 100644 --- a/public/js/components/Drop/Grid.js +++ b/public/js/components/Drop/Grid.js @@ -439,7 +439,7 @@ export default { }) this.dragEnd(); this.dragCancel(); - } + } if (!this.active) return this.dragCancel(); this.checkPinnedWidgetAnimation(); @@ -454,14 +454,14 @@ export default { let x = this.x + this.draggedOffset[0]; let y = this.y + this.draggedOffset[1]; if (x < 0) { - this.draggedOffset[0] -= x; + this.draggedOffset[0] += x; x = 0; } else if (x + this.draggedItem.w > this.cols) { this.draggedOffset[0] += this.cols - this.draggedItem.w - x; x = this.cols - this.draggedItem.w; } if (y < 0) { - this.draggedOffset[1] -= y; + this.draggedOffset[1] += y; y = 0; } this.positionUpdates = this.dragGrid.move(this.draggedItem, x, y); @@ -481,6 +481,7 @@ export default { } }, dragCancel() { + this.removeWidgetClones(); this.additionalRowComputed = false; this.toggleDraggedItemOverlay(false); this.mode = MODE_IDLE; @@ -492,6 +493,7 @@ export default { }, dragEnd() { + this.removeWidgetClones(); if (this.mode == MODE_IDLE) return; // clean up unused classes @@ -501,10 +503,7 @@ export default { ele.classList.remove("denied-dragging-animation"); }) - let widgetClones = document.getElementsByClassName("widgetClone"); - for (let i=0; i = this.cols) return this.dragCancel(); @@ -597,6 +596,12 @@ export default { draggedItemNode.classList.remove("border-danger"); } }, + removeWidgetClones(){ + let widgetClones = Array.from(document.getElementsByClassName("widgetClone")); + for (let i = 0; i < widgetClones.length; i++) { + this.$refs.container.removeChild(widgetClones[i]); + } + }, mouseDown(){ this.mode = MODE_MOUSE_DOWN; }, From 4eab58177a15c12b48fd04adc5d7a201e4ad5063 Mon Sep 17 00:00:00 2001 From: SimonGschnell Date: Tue, 12 Aug 2025 11:41:14 +0200 Subject: [PATCH 2/5] update(disabled widget background): updates the background of disabled widgets in the dashboard by giving them more opacity --- public/css/components/dashboard.css | 11 +++++++++++ public/css/theme/default.css | 4 +++- public/js/components/Dashboard/Item.js | 2 +- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/public/css/components/dashboard.css b/public/css/components/dashboard.css index 8dc19128d..88d136b55 100644 --- a/public/css/components/dashboard.css +++ b/public/css/components/dashboard.css @@ -203,3 +203,14 @@ } } + +.hiddenWidget{ + background: var(--fhc-disabled-background); + opacity: 40%; +} + +.hiddenWidget .card, +.hiddenWidget .card-body, +.hiddenWidget .card-body *{ + background: inherit !important; +} diff --git a/public/css/theme/default.css b/public/css/theme/default.css index ba6493542..a0f366174 100644 --- a/public/css/theme/default.css +++ b/public/css/theme/default.css @@ -89,7 +89,8 @@ --fhc-link: var(--fhc-blue-10); /* disabled */ - --fhc-disabled: var(--fhc-gray-10); + --fhc-disabled: var(--fhc-gray-90); + --fhc-disabled-background: var(--fhc-gray-30); /* status colors */ --fhc-danger: var(--fhc-red-10); @@ -135,6 +136,7 @@ /* disabled */ --fhc-disabled: var(--fhc-gray-10); + --fhc-disabled-background: var(--fhc-gray-120); /* status colors */ --fhc-danger: var(--fhc-red-10); diff --git a/public/js/components/Dashboard/Item.js b/public/js/components/Dashboard/Item.js index eccc8242e..d2ad4ae75 100644 --- a/public/js/components/Dashboard/Item.js +++ b/public/js/components/Dashboard/Item.js @@ -156,7 +156,7 @@ export default { -
+
From 645da5a5bf4ed8a195eeb8949c73e1f208c38954 Mon Sep 17 00:00:00 2001 From: SimonGschnell Date: Wed, 13 Aug 2025 12:09:34 +0200 Subject: [PATCH 3/5] fix(Dashboard drag&drop): ensures dragend events trigger correctly in chrome --- public/js/components/Drop/Grid.js | 27 +++++++++++++++------------ public/js/composables/GridLogic.js | 3 ++- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/public/js/components/Drop/Grid.js b/public/js/components/Drop/Grid.js index ae1a6504c..cfe5747d4 100644 --- a/public/js/components/Drop/Grid.js +++ b/public/js/components/Drop/Grid.js @@ -434,11 +434,8 @@ export default { }, dragOver(evt) { if ((this.y + 1) > this.rows && (this.mode == MODE_MOVE || this.mode == MODE_RESIZE)) { - this.positionUpdates = this.positionUpdates?.filter(item => { - return item.widgetid == this.draggedItem.data.widgetid; - }) - this.dragEnd(); this.dragCancel(); + } if (!this.active) return this.dragCancel(); @@ -464,7 +461,7 @@ export default { this.draggedOffset[1] += y; y = 0; } - this.positionUpdates = this.dragGrid.move(this.draggedItem, x, y); + this.positionUpdates= this.dragGrid.move(this.draggedItem, x, y); break; } case MODE_RESIZE: { @@ -494,8 +491,11 @@ export default { }, dragEnd() { this.removeWidgetClones(); - if (this.mode == MODE_IDLE) + this.toggleDraggedItemOverlay(false); + + if (this.mode == MODE_IDLE){ return; + } // clean up unused classes let draggedItemNode = document.getElementById(this.draggedItem.data.widgetid); draggedItemNode.classList.remove("border-danger"); @@ -503,16 +503,19 @@ export default { ele.classList.remove("denied-dragging-animation"); }) - - - if (!this.active || this.x < 0 || this.y < 0 || this.x >= this.cols) - return this.dragCancel(); + //if (!this.active || this.x < 0 || this.y < 0 || this.x >= this.cols) + //return this.dragCancel(); + this.mode = MODE_IDLE; let updated = []; this.convertGridResultToUpdate(this.positionUpdates, updated); updated = this._updateFixedPositions(updated); if (updated.length) this.$emit('rearrangeItems', updated.filter(v => v)); + + this.draggedItem = null; + this.draggedNode = null; + this.$emit('draggedItem', null); }, _updateFixedPositions(updated) { updated.forEach((item, index) => { @@ -617,7 +620,7 @@ export default { @touchmove="dragOver" @touchend="dragCancel" @dragover.prevent="dragOver" - @drop="dragEnd" + @drop="dragEnd($event)" @mousemove="updateCursorOnMouseMove" @mouseleave="mouseLeave"> @@ -631,7 +634,7 @@ export default { @mouse-up="mouseUp" @start-resize="startResize" @dragging="dragging" - @end-drag="dragCancel" + @end-drag="dragEnd" @touch-end="dragEnd();mouseUp();" @touch-start="updateCursorOnMouseMove($event); mouseDown();" class="position-absolute" diff --git a/public/js/composables/GridLogic.js b/public/js/composables/GridLogic.js index 93c662eb5..ff8ae0c39 100644 --- a/public/js/composables/GridLogic.js +++ b/public/js/composables/GridLogic.js @@ -116,7 +116,7 @@ class GridLogic { prefer = DIR_RIGHT; } - const originalFrame = [...item.frame]; + const originalFrame = Array.isArray(item.frame) ? [...item.frame] : [item.frame]; const currItem = {...item}; currItem.x = x; @@ -146,6 +146,7 @@ class GridLogic { } } replaceUpdate[item.index] = { index: item.index, x, y }; + return replaceUpdate; } From e46f46c95bc41204e44d62010daf23cc10fe957e Mon Sep 17 00:00:00 2001 From: SimonGschnell Date: Thu, 14 Aug 2025 15:07:38 +0200 Subject: [PATCH 4/5] update(Dashboard grid): doesnt allow the user to drag a widget outside of the grid boundaries --- public/js/components/DashboardWidget/Url.js | 2 +- public/js/components/Drop/Grid.js | 20 ++++++++++++++++++-- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/public/js/components/DashboardWidget/Url.js b/public/js/components/DashboardWidget/Url.js index 2763862a9..16eacab90 100644 --- a/public/js/components/DashboardWidget/Url.js +++ b/public/js/components/DashboardWidget/Url.js @@ -159,7 +159,7 @@ export default { // this.$emit('setConfig', true); -> use this to enable widget config mode if needed }, template: /*html*/ ` -
+
diff --git a/public/js/components/Drop/Grid.js b/public/js/components/Drop/Grid.js index cfe5747d4..d11e4c249 100644 --- a/public/js/components/Drop/Grid.js +++ b/public/js/components/Drop/Grid.js @@ -274,8 +274,23 @@ export default { dragging(event){ if(this.mode == MODE_MOVE){ this.toggleDraggedItemOverlay(true); - this.clonedWidget.style.top = `${this.clientY-20}px`; - this.clonedWidget.style.left = `${this.clientX-15}px`; + + const containerRect = this.$refs.container.getBoundingClientRect(); + const clonedWidgetRect = this.clonedWidget.getBoundingClientRect(); + + let desiredTop = this.clientY - 20; + let desiredLeft = this.clientX - 15; + + const minTop = 0; + const maxTop = containerRect.height - clonedWidgetRect.height; + const minLeft = 0; + const maxLeft = containerRect.width - clonedWidgetRect.width; + + const constrainedTop = Math.max(minTop, Math.min(maxTop, desiredTop)); + const constrainedLeft = Math.max(minLeft, Math.min(maxLeft, desiredLeft)); + + this.clonedWidget.style.top = `${constrainedTop}px`; + this.clonedWidget.style.left = `${constrainedLeft}px`; } }, createNewGrid(items) { @@ -413,6 +428,7 @@ export default { setTimeout(() => { this.draggedNode = evt.target.closest(".drop-grid-item"); //clones the widget for the drag Image + let clone = evt.target.closest(".drop-grid-item")?.cloneNode(true); clone.style.zIndex = 5; From f695d8b66a2437420e0e831d0a7d967dd61ba3ce Mon Sep 17 00:00:00 2001 From: SimonGschnell Date: Mon, 18 Aug 2025 10:21:18 +0200 Subject: [PATCH 5/5] update(Dashboard Widget Drag): shows hidden widget when dragging the widget on the dashboard --- public/js/components/Drop/Grid.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/public/js/components/Drop/Grid.js b/public/js/components/Drop/Grid.js index d11e4c249..a7bea64e3 100644 --- a/public/js/components/Drop/Grid.js +++ b/public/js/components/Drop/Grid.js @@ -434,6 +434,8 @@ export default { clone.style.zIndex = 5; clone.classList.add("widgetClone"); this.$refs.container.appendChild(clone); + const hiddenWidget = clone.querySelector("[style='display: none;']"); + hiddenWidget.style.removeProperty("display"); this.clonedWidget = clone; }, 0);