mirror of
https://github.com/FH-Complete/FHC-Core.git
synced 2026-07-16 22:42:16 +00:00
feature(CIS Dashboard gridsystem): allows to pin widgets in the grid and changes how widgets are positioned in different viewports
This commit is contained in:
@@ -77,12 +77,10 @@
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.dragged-widget-icon{
|
||||
position: absolute;
|
||||
height: 250px;
|
||||
width: 200px;
|
||||
top: -999px;
|
||||
left: -999px;
|
||||
z-index: 3;
|
||||
.pin:hover{
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.pin[pinned]:hover{
|
||||
color:rgb(153, 116, 116);
|
||||
}
|
||||
|
||||
@@ -24,7 +24,9 @@ export default {
|
||||
"dragstart",
|
||||
"resizestart",
|
||||
"configOpened",
|
||||
"configClosed"
|
||||
"configClosed",
|
||||
"pinItem",
|
||||
"unPinItem"
|
||||
],
|
||||
props: [
|
||||
"id",
|
||||
@@ -36,8 +38,13 @@ export default {
|
||||
"hidden",
|
||||
"editMode",
|
||||
"loading",
|
||||
"item_data",
|
||||
"place",
|
||||
],
|
||||
computed: {
|
||||
isPinned(){
|
||||
return this.place?.pinned ? true : false;
|
||||
},
|
||||
isResizeable() {
|
||||
if (!this.widget) return false;
|
||||
return this.widget.setup.width.max || this.widget.setup.height.max;
|
||||
@@ -47,6 +54,17 @@ export default {
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
unpin(){
|
||||
// Unpinning is only possible in edit mode
|
||||
if(!this.editMode)
|
||||
return;
|
||||
let result = { item: this.item_data, x: this.item_data.x, y: this.item_data.y };
|
||||
this.$emit('unPinItem', [result]);
|
||||
},
|
||||
pinItem(){
|
||||
let result = { item: this.item_data, x: this.item_data.x, y: this.item_data.y};
|
||||
this.$emit('pinItem',[result]);
|
||||
},
|
||||
getWidgetC4Link(widget) {
|
||||
return (FHC_JS_DATA_STORAGE_OBJECT.app_root +
|
||||
FHC_JS_DATA_STORAGE_OBJECT.ci_router + widget.setup.cis4link)
|
||||
@@ -120,12 +138,25 @@ export default {
|
||||
<i class="fa-solid fa-spinner fa-pulse fa-3x"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else-if="!hidden || editMode" :id="widgetID" class="dashboard-item card overflow-hidden h-100 position-relative" :class="arguments && arguments.className ? arguments.className : ''">
|
||||
<div v-else-if="!hidden || editMode" class="dashboard-item card overflow-hidden h-100 position-relative" :class="arguments && arguments.className ? arguments.className : ''">
|
||||
<div v-if="widget" class="card-header d-flex ps-0 pe-2 align-items-center">
|
||||
<Transition>
|
||||
<span v-if="editMode" drag-action="move" class="col-auto mx-2 px-2 cursor-move"><i class="fa-solid fa-grip-vertical"></i></span>
|
||||
<span v-if="editMode && !isPinned" drag-action="move" class="col-auto mx-2 px-2 cursor-move"><i class="fa-solid fa-grip-vertical"></i></span>
|
||||
</Transition>
|
||||
<span class="col mx-2 px-2">{{ widget.setup.name }}</span>
|
||||
<template v-if="isPinned">
|
||||
<div v-if="editMode" pinned="true" @click="unpin" class="pin cursor-pointer col-auto me-2">
|
||||
<i class="fa-solid fa-thumbtack "></i>
|
||||
</div>
|
||||
<div v-else class="col-auto me-2">
|
||||
<i class="fa-solid fa-thumbtack "></i>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div v-if="editMode" class="col-auto me-2 pin" @click="pinItem">
|
||||
<i class="fa-solid fa-thumbtack" style="color:lightgray;"></i>
|
||||
</div>
|
||||
</template>
|
||||
<a v-if="widget.setup.cis4link" :href="getWidgetC4Link(widget)" class="col-auto ms-auto ">
|
||||
<i class="fa fa-arrow-up-right-from-square me-1"></i>
|
||||
</a>
|
||||
@@ -157,7 +188,7 @@ export default {
|
||||
</template>
|
||||
</bs-modal>
|
||||
<height-transition>
|
||||
<div v-if="editMode && isResizeable" class="card-footer d-flex justify-content-end p-0">
|
||||
<div v-if="editMode && isResizeable && !isPinned" class="card-footer d-flex justify-content-end p-0">
|
||||
<span drag-action="resize" class="col-auto px-1 cursor-nw-resize"><i class="fa-solid fa-up-right-and-down-left-from-center mirror-x"></i></span>
|
||||
</div>
|
||||
</height-transition>
|
||||
|
||||
@@ -57,71 +57,28 @@ export default {
|
||||
return 'margin-bottom: 8px;';
|
||||
},
|
||||
items() {
|
||||
|
||||
const computeNearestPlace = (item, gridWidth) =>{
|
||||
// reuses the nearest placement of the widget from another viewport
|
||||
/* 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();
|
||||
.shift();
|
||||
place = item.place[nearestIndex];
|
||||
}
|
||||
else{
|
||||
place = { x: 0, y: 0, w: 1, h: 1 };
|
||||
}
|
||||
return place;
|
||||
}
|
||||
} */
|
||||
|
||||
return this.widgets.map(item => {
|
||||
return { ...item, ...(item.place[this.gridWidth] || computeNearestPlace(item, this.gridWidth))};
|
||||
let placedItems = this.widgets.map(item => {
|
||||
return { ...item, reorder: false, ...(item.place[this.gridWidth] || { reorder: true, ...{ x: 0, y: 0, w: 1, h: 1 } })};
|
||||
});
|
||||
return placedItems;
|
||||
|
||||
},
|
||||
items_hashmap() {
|
||||
let items = {};
|
||||
this.items.forEach(item => {
|
||||
items[`x${item.x}y${item.y}`] = item;
|
||||
});
|
||||
return items
|
||||
},
|
||||
items_placeholders(){
|
||||
let placeholders = [];
|
||||
let col_max = this.gridWidth;
|
||||
let rows_max = this.gridHeight;
|
||||
|
||||
// occupied hashmap to keep track of the occupied cells
|
||||
let occupied = {};
|
||||
|
||||
for (let y = 0; y < rows_max; y++) {
|
||||
for (let x = 0; x < col_max; x++) {
|
||||
// skip current position if it was registered as occupied
|
||||
if (Object.keys(occupied).length && occupied[`x${x}y${y}`]) {
|
||||
continue;
|
||||
}
|
||||
let current_item = this.items_hashmap[`x${x}y${y}`];
|
||||
if (current_item) {
|
||||
//calculate the occupied cells from the width and the height from the items
|
||||
let width = current_item.w;
|
||||
let height = current_item.h;
|
||||
let max_x = x + width - 1;
|
||||
let max_y = y + height - 1;
|
||||
if(x != max_x || y != max_y){
|
||||
for (let occupied_y = y; occupied_y <= max_y; occupied_y++) {
|
||||
for (let occupied_x = x; occupied_x <= max_x; occupied_x++) {
|
||||
if (occupied_x != x || occupied_y != y) {
|
||||
occupied[`x${occupied_x}y${occupied_y}`]=true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
placeholders.push({ x: x, y: y, w: 1, h: 1, placeholder: true,
|
||||
data: { id: 'placeholder_' + String(placeholders.length).padStart(4, "0") } });
|
||||
}
|
||||
}
|
||||
}
|
||||
return placeholders;
|
||||
},
|
||||
|
||||
},
|
||||
methods: {
|
||||
handleConfigOpened() {
|
||||
@@ -140,7 +97,7 @@ export default {
|
||||
else
|
||||
minmaxW = {min:minmaxW,max:minmaxW};
|
||||
if (w < minmaxW.min)
|
||||
w = minmaxW.min;
|
||||
w = minmaxW.min;
|
||||
if (w > minmaxW.max)
|
||||
w = minmaxW.max;
|
||||
|
||||
@@ -170,7 +127,7 @@ export default {
|
||||
payload[item.id] = { config };
|
||||
this.updatePreset(payload);
|
||||
},
|
||||
updatePositions(updated) {
|
||||
updatePositions(updated, pinned=false) {
|
||||
let result = {};
|
||||
updated.forEach(update => {
|
||||
|
||||
@@ -182,6 +139,7 @@ export default {
|
||||
delete item.y;
|
||||
delete item.w;
|
||||
delete item.h;
|
||||
delete item.place[this.gridWidth].pinned;
|
||||
if (update.x !== undefined)
|
||||
item.place[this.gridWidth].x = update.x;
|
||||
if (update.y !== undefined)
|
||||
@@ -190,11 +148,13 @@ export default {
|
||||
item.place[this.gridWidth].w = update.w;
|
||||
if (update.h !== undefined)
|
||||
item.place[this.gridWidth].h = update.h;
|
||||
if (pinned){
|
||||
item.place[this.gridWidth].pinned = true;
|
||||
}
|
||||
|
||||
result[item.id] = item;
|
||||
}
|
||||
});
|
||||
|
||||
this.updatePreset(result);
|
||||
},
|
||||
updatePreset(update) {
|
||||
@@ -213,13 +173,8 @@ export default {
|
||||
});
|
||||
},
|
||||
template: `
|
||||
<div class="dashboard-section position-relative" ref="container" :style="getSectionStyle">
|
||||
<template v-for="setup in widgetsSetup">
|
||||
<div class="dragged-widget-icon" :id="'widget-'+name+'-'+setup.widget_id" >
|
||||
<widget-icon v-if="widgetsSetup" :widget="setup"></widget-icon>
|
||||
</div>
|
||||
</template>
|
||||
<drop-grid v-model:cols="gridWidth" :items="items" :placeholders="items_placeholders" :active="editModeIsActive" :resize-limit="checkResizeLimit" :margin-for-extra-row=".01" @rearrange-items="updatePositions" @gridHeight="gridHeight=$event" >
|
||||
<div class="dashboard-section position-relative pb-3 border-bottom" ref="container" :style="getSectionStyle">
|
||||
<drop-grid v-model:cols="gridWidth" :items="items" :active="editModeIsActive" :resize-limit="checkResizeLimit" :margin-for-extra-row=".01" @rearrange-items="updatePositions" @gridHeight="gridHeight=$event" >
|
||||
<template #default="item">
|
||||
|
||||
<dashboard-item
|
||||
@@ -228,15 +183,19 @@ export default {
|
||||
:widgetID="item.id"
|
||||
:width="item.w"
|
||||
:height="item.h"
|
||||
:item_data="{config:item.config, custom:item.custom, h:item.h, w:item.w,id:item.id,reorder:item.reorder,place:item.place,widget:item.widget,widgetid:item.widgetid,x:item.x,y:item.y}"
|
||||
:loading="item.loading"
|
||||
:config="item.config"
|
||||
:custom="item.custom"
|
||||
:hidden="item.hidden"
|
||||
:editMode="editMode"
|
||||
:place="item.place[gridWidth]"
|
||||
@change="saveConfig($event, item)"
|
||||
@remove="removeWidget(item, $event)"
|
||||
@config-opened="handleConfigOpened"
|
||||
@config-closed="handleConfigClosed">
|
||||
@config-closed="handleConfigClosed"
|
||||
@pinItem="updatePositions($event,true)"
|
||||
@unPinItem="updatePositions">
|
||||
</dashboard-item>
|
||||
<div v-else class="empty-tile-hover" @click="$emit('widgetAdd', name, { widget: 1, config: {}, place: {[gridWidth]: {x:item.x,y:item.y,w:1,h:1}}, custom: 1 })"></div>
|
||||
|
||||
|
||||
@@ -24,10 +24,6 @@ export default {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
placeholders: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
}
|
||||
},
|
||||
emits: [
|
||||
"rearrangeItems",
|
||||
@@ -48,8 +44,11 @@ export default {
|
||||
fixedPositionUpdates: null,
|
||||
draggedOffset: [0,0],
|
||||
draggedItem: null,
|
||||
draggedNode: null,
|
||||
draggedItemIcon: null,
|
||||
additionalRow: null,
|
||||
reorderedItems:[],
|
||||
clonedWidget:null,
|
||||
}
|
||||
},
|
||||
inject:{
|
||||
@@ -59,6 +58,64 @@ export default {
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
items_hashmap() {
|
||||
let items = {};
|
||||
this.items.forEach(item => {
|
||||
if (this.reorderedItems.length > 0){
|
||||
if(item.reorder){
|
||||
let rearrangedPosition = this.reorderedItems.filter(widget => widget.data.widgetid == item.widgetid)?.pop();
|
||||
if (rearrangedPosition) {
|
||||
item.x = rearrangedPosition.x;
|
||||
item.y = rearrangedPosition.y;
|
||||
}
|
||||
}
|
||||
}
|
||||
items[`x${item.x}y${item.y}`] = item;
|
||||
});
|
||||
return items
|
||||
},
|
||||
items_placeholders(){
|
||||
let placeholders = [];
|
||||
let col_max = this.cols;
|
||||
let rows_max = this.rows;
|
||||
|
||||
// occupied hashmap to keep track of the occupied cells
|
||||
let occupied = {};
|
||||
|
||||
for (let y = 0; y < rows_max; y++) {
|
||||
for (let x = 0; x < col_max; x++) {
|
||||
// skip current position if it was registered as occupied
|
||||
if (Object.keys(occupied).length && occupied[`x${x}y${y}`]) {
|
||||
continue;
|
||||
}
|
||||
let current_item = this.items_hashmap[`x${x}y${y}`];
|
||||
if (current_item) {
|
||||
//calculate the occupied cells from the width and the height from the items
|
||||
let width = current_item.w;
|
||||
let height = current_item.h;
|
||||
let max_x = x + width - 1;
|
||||
let max_y = y + height - 1;
|
||||
if(x != max_x || y != max_y){
|
||||
for (let occupied_y = y; occupied_y <= max_y; occupied_y++) {
|
||||
for (let occupied_x = x; occupied_x <= max_x; occupied_x++) {
|
||||
if (occupied_x != x || occupied_y != y) {
|
||||
occupied[`x${occupied_x}y${occupied_y}`]=true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
placeholders.push({ x: x, y: y, w: 1, h: 1, placeholder: true,
|
||||
data: { id: 'placeholder_' + String(placeholders.length).padStart(4, "0") } });
|
||||
}
|
||||
}
|
||||
}
|
||||
return placeholders;
|
||||
},
|
||||
placedItems_withPlaceholders() {
|
||||
return [...this.placedItems, ...this.items_placeholders];
|
||||
},
|
||||
rows() {
|
||||
if ((this.mode == MODE_MOVE || this.mode == MODE_RESIZE) && this.dragGrid)
|
||||
return this.dragGrid.h;
|
||||
@@ -83,6 +140,7 @@ export default {
|
||||
y: item.y,
|
||||
w: item.w,
|
||||
h: item.h,
|
||||
reorder: item.reorder,
|
||||
weight: item.weight || 0,
|
||||
data: item
|
||||
}
|
||||
@@ -110,7 +168,7 @@ export default {
|
||||
if (!this.positionUpdates)
|
||||
return this.prePlacedItems;
|
||||
return this.prePlacedItems.map(item => {
|
||||
if (!this.positionUpdates[item.index])
|
||||
if (!this.positionUpdates[item.index] )
|
||||
return item;
|
||||
return {
|
||||
index: item.index,
|
||||
@@ -123,9 +181,6 @@ export default {
|
||||
};
|
||||
});
|
||||
},
|
||||
placedItems_withPlaceholders(){
|
||||
return [...this.placedItems,...this.placeholders];
|
||||
},
|
||||
showEmptyTileHover() {
|
||||
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;
|
||||
@@ -169,27 +224,52 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
||||
toggleDraggedItemOverlay(condition){
|
||||
if(!this.draggedItem)
|
||||
if(!this.draggedNode)
|
||||
return;
|
||||
let draggedItemNode = document.getElementById(this.draggedItem.data.id);
|
||||
if(condition){
|
||||
draggedItemNode.classList.add("dashboard-item-overlay");
|
||||
this.draggedNode.firstElementChild.classList.add("dashboard-item-overlay");
|
||||
}else{
|
||||
draggedItemNode.classList.remove("dashboard-item-overlay");
|
||||
this.draggedNode.firstElementChild.classList.remove("dashboard-item-overlay");
|
||||
}
|
||||
},
|
||||
dragging(event){
|
||||
if(this.mode == MODE_MOVE){
|
||||
this.toggleDraggedItemOverlay(true);
|
||||
this.draggedItemIcon.style.top = `${this.clientY}px`;
|
||||
this.draggedItemIcon.style.left = `${this.clientX}px`;
|
||||
this.clonedWidget.style.top = `${this.clientY-20}px`;
|
||||
this.clonedWidget.style.left = `${this.clientX-15}px`;
|
||||
}
|
||||
},
|
||||
createNewGrid(items) {
|
||||
this.grid = new GridLogic(this.cols);
|
||||
const result = [];
|
||||
[...items].sort((a, b) => a.weight > b.weight).forEach(item => {
|
||||
let sortedItems = [...items].sort((a, b) => {
|
||||
if (a.reorder){
|
||||
return 999;
|
||||
}
|
||||
if (b.reorder){
|
||||
return -999;
|
||||
}
|
||||
return a.weight > b.weight;
|
||||
});
|
||||
let reorderedItems = [];
|
||||
sortedItems.forEach(item => {
|
||||
let freeSlots = this.grid.getFreeSlots();
|
||||
|
||||
if(item.reorder){
|
||||
item.reorder=true;
|
||||
let firstFreeSlot = freeSlots.shift();
|
||||
if (!firstFreeSlot) {
|
||||
item.x = 0;
|
||||
item.y = this.grid.h;
|
||||
}else{
|
||||
item.x = firstFreeSlot.x;
|
||||
item.y = firstFreeSlot.y;
|
||||
}
|
||||
reorderedItems.push(item);
|
||||
|
||||
}
|
||||
if (item.x + item.w > this.cols) {
|
||||
let targetW = this.cols-item.x,
|
||||
targetX = undefined;
|
||||
@@ -214,10 +294,12 @@ export default {
|
||||
item.frame = this.grid.getItemFrame(item);
|
||||
this.convertGridResultToUpdate(this.grid.add(item), result, items);
|
||||
});
|
||||
this.reorderedItems = reorderedItems;
|
||||
this.grid.clearWeights();
|
||||
return result;
|
||||
},
|
||||
convertGridResultToUpdate(input, output, baseArray) {
|
||||
|
||||
if (!input)
|
||||
return;
|
||||
if (!baseArray)
|
||||
@@ -296,7 +378,14 @@ export default {
|
||||
|
||||
this.mode = MODE_MOVE;
|
||||
this.draggedItem = item;
|
||||
this.draggedItemIcon = document.getElementById(`widget-${this.sectionName}-${this.draggedItem?.data.widget}`);
|
||||
this.draggedNode = evt.target;
|
||||
//clones the widget for the drag Image
|
||||
let clone = evt.target.cloneNode(true);
|
||||
clone.style.zIndex = 20;
|
||||
clone.classList.add("widgetClone");
|
||||
this.$refs.container.appendChild(clone);
|
||||
this.clonedWidget = clone;
|
||||
|
||||
this.draggedOffset = [item.x - this.x, item.y - this.y];
|
||||
this._dragStart(evt, item);
|
||||
},
|
||||
@@ -353,6 +442,7 @@ export default {
|
||||
this.positionUpdates = null;
|
||||
this.draggedOffset = [0,0],
|
||||
this.draggedItem = null;
|
||||
this.draggedNode = null;
|
||||
|
||||
if(this.draggedItemIcon){
|
||||
this.draggedItemIcon.style.top = '-999px';
|
||||
@@ -362,6 +452,10 @@ export default {
|
||||
|
||||
},
|
||||
dragEnd() {
|
||||
let widgetClones = document.getElementsByClassName("widgetClone");
|
||||
for(let widget of widgetClones){
|
||||
this.$refs.container.removeChild(widget);
|
||||
}
|
||||
if (this.mode == MODE_IDLE)
|
||||
return;
|
||||
if (!this.active || this.x < 0 || this.y < 0 || this.x >= this.cols)
|
||||
|
||||
@@ -23,9 +23,34 @@ class GridLogic {
|
||||
const i = y*this.w + x;
|
||||
return !this.grid[i] && this.grid[i] !== 0;
|
||||
}
|
||||
getMaxY(){
|
||||
return this.data.reduce((acc, item) => {
|
||||
if (item?.y > acc) {
|
||||
acc = item.y;
|
||||
}
|
||||
return acc;
|
||||
}, 0);
|
||||
}
|
||||
getFreeSlots() {
|
||||
const freeSlots = [];
|
||||
let biggestY = this.getMaxY();
|
||||
let totalSpaces = this.w * (biggestY+1);
|
||||
for(let i=0; i < totalSpaces; i++){
|
||||
if (!this.grid[i] && this.grid[i] !== 0){
|
||||
this.grid[i] = undefined;
|
||||
}
|
||||
}
|
||||
for(let i =0; i < this.grid.length; i++){
|
||||
if (!this.grid[i] && this.grid[i] !== 0){
|
||||
let x = i % this.w;
|
||||
let y = Math.floor(i / this.w);
|
||||
freeSlots.push({x, y});
|
||||
}
|
||||
}
|
||||
return freeSlots;
|
||||
}
|
||||
add(item, prefer) {
|
||||
let occupiers = this.getItemsInFrame(item.frame);
|
||||
|
||||
if (!occupiers.length) {
|
||||
item.frame.forEach(f => this.grid[f] = item.index);
|
||||
this.data[item.index] = item;
|
||||
@@ -63,6 +88,7 @@ class GridLogic {
|
||||
});
|
||||
item.frame.forEach(f => this.grid[f] = item.index);
|
||||
this.data[item.index] = item;
|
||||
|
||||
return result;
|
||||
} else {
|
||||
console.error('FATAL', "can't arrange item on grid");
|
||||
@@ -70,8 +96,11 @@ class GridLogic {
|
||||
}
|
||||
}
|
||||
move(item, x, y) {
|
||||
if (item.data.place[this.w].pinned)
|
||||
return [];
|
||||
if (item.x == x && item.y == y)
|
||||
return [];
|
||||
|
||||
this.remove(item);
|
||||
|
||||
let prefer = undefined;
|
||||
@@ -91,6 +120,32 @@ class GridLogic {
|
||||
currItem.x = x;
|
||||
currItem.y = y;
|
||||
currItem.frame = this.getItemFrame(currItem);
|
||||
let occupiers = this.getItemsInFrame(currItem.frame);
|
||||
|
||||
// does not update if the target conatins pinned widgets
|
||||
if (occupiers.some(frame => this.data[frame]?.data.place[this.w].pinned)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// checks if target contains widget with the same high and width
|
||||
let replace = occupiers
|
||||
.map(occupier => this.data[occupier])
|
||||
.filter( occupier => {
|
||||
return occupier.data.w == item.w && occupier.data.h == item.h
|
||||
});
|
||||
|
||||
// replaces positions of widget and target widget if they have same height and width
|
||||
if(replace.length > 0){
|
||||
let replaceUpdate =[];
|
||||
replaceUpdate[replace[0].index] = { index: replace[0].index, x:item.x, y:item.y };
|
||||
replaceUpdate[item.index] = { index: item.index, x: replace[0].x, y: replace[0].y};
|
||||
//update Grid and dataGrid
|
||||
replace[0].frame.forEach(f => this.grid[f] = item.index)
|
||||
item.frame.forEach(f => this.grid[f] = replace[0].index);
|
||||
this.data[replace[0].index] = item;
|
||||
this.data[item.index] = replace[0];
|
||||
return replaceUpdate;
|
||||
}
|
||||
|
||||
const updates = this.add(currItem, prefer);
|
||||
updates[item.index] = {index: item.index, x, y};
|
||||
@@ -145,25 +200,27 @@ class GridLogic {
|
||||
let targetframe;
|
||||
switch(dir) {
|
||||
case DIR_UP:
|
||||
if (this.data[index].y - amount < 0)
|
||||
if (this.data[index].data?.place[this.w]?.pinned || this.data[index].y - amount < 0)
|
||||
return false;
|
||||
targetframe = this.data[index].frame.map(i => i-this.w*amount);
|
||||
move.y = -amount;
|
||||
break;
|
||||
case DIR_DOWN:
|
||||
if (this.data[index].data?.place[this.w]?.pinned)
|
||||
return false;
|
||||
if (this.data[index].y + this.data[index].h + amount > this.h)
|
||||
cost += .4;
|
||||
targetframe = this.data[index].frame.map(i => i+this.w*amount);
|
||||
move.y = amount;
|
||||
break;
|
||||
case DIR_LEFT:
|
||||
if (this.data[index].x - amount < 0)
|
||||
if (this.data[index].data?.place[this.w]?.pinned || this.data[index].x - amount < 0)
|
||||
return false;
|
||||
targetframe = this.data[index].frame.map(i => i-amount);
|
||||
move.x = -amount;
|
||||
break;
|
||||
case DIR_RIGHT:
|
||||
if (this.data[index].x + this.data[index].w + amount > this.w)
|
||||
if (this.data[index].data?.place[this.w]?.pinned || this.data[index].x + this.data[index].w + amount > this.w)
|
||||
return false;
|
||||
targetframe = this.data[index].frame.map(i => i+amount);
|
||||
move.x = amount;
|
||||
|
||||
Reference in New Issue
Block a user