From 33f800fa2844a604aca18c38a91797bd29caa600 Mon Sep 17 00:00:00 2001 From: SimonGschnell Date: Tue, 1 Apr 2025 13:06:23 +0200 Subject: [PATCH] fix(Dashboard Mobile Touch Events): fixes the behaviour of the touch event for the dashboard grid --- public/css/components/dashboard.css | 8 +++ public/js/components/Dashboard/Dashboard.js | 14 +++++ public/js/components/Dashboard/Section.js | 29 +++++----- .../js/components/Dashboard/Widget/Picker.js | 18 ++---- .../components/Dashboard/Widget/WidgetIcon.js | 29 ++++++++++ public/js/components/Drop/Grid.js | 55 +++++++++++++------ public/js/components/Drop/Grid/Item.js | 15 ++--- 7 files changed, 118 insertions(+), 50 deletions(-) create mode 100644 public/js/components/Dashboard/Widget/WidgetIcon.js diff --git a/public/css/components/dashboard.css b/public/css/components/dashboard.css index fb9a628de..e31b74233 100644 --- a/public/css/components/dashboard.css +++ b/public/css/components/dashboard.css @@ -77,3 +77,11 @@ z-index: 2; } +.dragged-widget-icon{ + position: absolute; + height: 250px; + width: 200px; + top: -999px; + left: -999px; + z-index: 3; +} \ No newline at end of file diff --git a/public/js/components/Dashboard/Dashboard.js b/public/js/components/Dashboard/Dashboard.js index a0d3ddcf3..e6f26d169 100644 --- a/public/js/components/Dashboard/Dashboard.js +++ b/public/js/components/Dashboard/Dashboard.js @@ -34,6 +34,7 @@ export default { provide() { return { editMode: Vue.computed(()=>this.editMode), + widgetsSetup: Vue.computed(() => this.widgets), } }, computed: { @@ -142,6 +143,19 @@ export default { } }, created() { + + axios.get(this.apiurl + '/Widget/getWidgetsForDashboard', { + params: { + db: this.dashboard + } + }).then(res => { + res.data.retval.forEach(widget => { + widget.arguments = JSON.parse(widget.arguments); + widget.setup = JSON.parse(widget.setup); + }); + this.widgets = res.data.retval; + }).catch(err => console.error('ERROR:', err)); + axios.get(this.apiurl + '/Config', {params:{ db: this.dashboard }}).then(res => { diff --git a/public/js/components/Dashboard/Section.js b/public/js/components/Dashboard/Section.js index 3a71eb5fc..9a8a59a4f 100644 --- a/public/js/components/Dashboard/Section.js +++ b/public/js/components/Dashboard/Section.js @@ -49,18 +49,23 @@ export default { return 'margin-bottom: 8px;'; }, items() { + + const computeNearestPlace = (item, gridWidth) =>{ + let place; + if (Object.keys(item.place).length > 0) { + const nearestIndex = Object.keys(item.place) + .sort((a, b) => Math.abs(a - gridWidth) - Math.abs(b - gridWidth)) + .pop(); + place = item.place[nearestIndex]; + } + else{ + place = { x: 0, y: 0, w: 1, h: 1 }; + } + return place; + } return this.widgets.map(item => { - let place; - if(!item.place[this.gridWidth]){ - const nearestIndex = Object.keys(item.place).sort((a,b)=>Math.abs(a-this.gridWidth)-Math.abs(b-this.gridWidth)).pop(); - if (nearestIndex === null){ - place = {x:0,y:0,w:1,h:1}; - }else{ - place = item.place[nearestIndex]; - } - } - return { ...item, ...(item.place[this.gridWidth] || place)}; + return { ...item, ...(item.place[this.gridWidth] || computeNearestPlace(item, this.gridWidth))}; }); }, items_hashmap() { @@ -73,10 +78,6 @@ export default { items_placeholders(){ let placeholders = []; let col_max = this.gridWidth; - // OLD way of calculating the max rows - //let max_row = Math.max(...this.items.map(item => item.y)) + 1; - //let max_row_max_height = Math.max(...this.items.filter(item => item.y == (max_row - 1)).map(item => item.h)); - //max_row + max_row_max_height - 1; let rows_max = this.gridHeight; // occupied hashmap to keep track of the occupied cells diff --git a/public/js/components/Dashboard/Widget/Picker.js b/public/js/components/Dashboard/Widget/Picker.js index c96e3bc7b..7ffd0671c 100644 --- a/public/js/components/Dashboard/Widget/Picker.js +++ b/public/js/components/Dashboard/Widget/Picker.js @@ -1,8 +1,10 @@ import BsModal from "../../Bootstrap/Modal.js"; +import WidgetIcon from "./WidgetIcon.js"; export default { components: { - BsModal + BsModal, + WidgetIcon, }, props: [ "widgets" @@ -28,11 +30,7 @@ export default { this.callbacks = {}; this.$refs.modal.hide(); }, - path(src) { - if (src[0] == '/') - return FHC_JS_DATA_STORAGE_OBJECT.app_root + src; - return src; - } + }, template: `
@@ -43,13 +41,7 @@ export default { No Widgets available
-
- -
-
{{ widget.setup.name || widget.widget_kurzbz }}
-

{{ widget.beschreibung }}

-
-
+
diff --git a/public/js/components/Dashboard/Widget/WidgetIcon.js b/public/js/components/Dashboard/Widget/WidgetIcon.js new file mode 100644 index 000000000..312cad659 --- /dev/null +++ b/public/js/components/Dashboard/Widget/WidgetIcon.js @@ -0,0 +1,29 @@ +export default { + data(){ + return { + + } + }, + props:{ + widget:{ + type:Object, + required:true, + } + }, + methods:{ + path(src) { + if (src[0] == '/') + return FHC_JS_DATA_STORAGE_OBJECT.app_root + src; + return src; + } + }, + emits:["select"], + template: /*html */` +
+ +
+
{{ widget.setup.name || widget.widget_kurzbz }}
+

{{ widget.beschreibung }}

+
+
`, +} \ No newline at end of file diff --git a/public/js/components/Drop/Grid.js b/public/js/components/Drop/Grid.js index 3a975d209..4da51e815 100644 --- a/public/js/components/Drop/Grid.js +++ b/public/js/components/Drop/Grid.js @@ -2,6 +2,7 @@ import GridItem from './Grid/Item.js'; import GridLogic from '../../composables/GridLogic.js'; +import WidgetIcon from '../Dashboard/Widget/WidgetIcon.js'; const MODE_IDLE = 0; const MODE_MOVE = 1; @@ -10,10 +11,10 @@ const MODE_RESIZE = 2; export default { name: 'Grid', components: { - GridItem - }, - inject: { + GridItem, + WidgetIcon, }, + inject: ["widgetsSetup"], props: { cols: Number, items: Array, @@ -50,6 +51,7 @@ export default { fixedPositionUpdates: null, draggedOffset: [0,0], draggedItem: null, + draggedItemIcon: null, additionalRow: null, } }, @@ -125,7 +127,15 @@ export default { if (!this.active || !this.grid || this.mode != MODE_IDLE || this.x < 0 || this.y < 0 || this.x >= this.cols || this.y >= this.rows) return false; return this.grid.isFreeSlot(this.x, this.y); - } + }, + widgetSetup(){ + if (!this.widgetsSetup) + return; + return this.widgetsSetup.reduce((acc, ele) => { + acc[ele.widget_id] =ele; + return acc; + } ,{}); + }, }, watch: { active(active) { @@ -157,6 +167,8 @@ export default { }, methods: { toggleDraggedItemOverlay(condition){ + if(!this.draggedItem) + return; let draggedItemNode = document.getElementById(this.draggedItem.data.id); if(condition){ draggedItemNode.classList.add("dashboard-item-overlay"); @@ -165,13 +177,11 @@ export default { } }, dragging(event){ - if(this.mode == MODE_MOVE) + if(this.mode == MODE_MOVE){ this.toggleDraggedItemOverlay(true); - /* use case: instead of showing the ghost widget when dragging, - change the x and y position of the widget when dragging to drag the whole widget - event.target.style.top = `${this.clientY}px`; - event.target.style.left = `${this.clientX}px`; - */ + this.draggedItemIcon.style.top = `${this.clientY}px`; + this.draggedItemIcon.style.left = `${this.clientX}px`; + } }, createNewGrid(items) { this.grid = new GridLogic(this.cols); @@ -270,10 +280,9 @@ export default { return true; }, - _dragStart(evt) { + _dragStart(evt, item) { if (evt.dataTransfer) { - if(this.mode == MODE_RESIZE) - evt.dataTransfer.setDragImage(evt.target, -99999, -99999); + evt.dataTransfer.setDragImage(evt.target, -99999, -99999); evt.dataTransfer.dropEffect = 'move'; evt.dataTransfer.effectAllowed = 'move'; } @@ -282,10 +291,11 @@ export default { if (!this.active) return; - this._dragStart(evt); this.mode = MODE_MOVE; this.draggedItem = item; + this.draggedItemIcon = document.getElementById(`widget${this.draggedItem?.data.widget}`); this.draggedOffset = [item.x - this.x, item.y - this.y]; + this._dragStart(evt, item); }, startResize(evt, item) { if (!this.active) @@ -334,14 +344,21 @@ export default { } }, dragCancel() { + + this.toggleDraggedItemOverlay(false); this.mode = MODE_IDLE; this.positionUpdates = null; this.draggedOffset = [0,0], this.draggedItem = null; + + if(this.draggedItemIcon){ + this.draggedItemIcon.style.top = '-999px'; + this.draggedItemIcon.style.left = '-999px'; + this.draggedItemIcon = null; + } + }, dragEnd() { - if(this.mode == MODE_MOVE) - this.toggleDraggedItemOverlay(false); if (this.mode == MODE_IDLE) return; if (!this.active || this.x < 0 || this.y < 0 || this.x >= this.cols) @@ -388,6 +405,11 @@ export default { @mousemove="updateCursorOnMouseMove" @mouseleave="mouseLeave"> +