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">
+
+
+
+
+