Implement autoarrange collection when adding a new collection
@Ivanruii y travaille déjà.
Depuis le 26/6/2024.
Évaluation
Cette issue n'a pas encore été évaluée.
Description
Right now when you click on Add collection the collection is place on the top left corner of the visible area of the canvas, if a blind person tries to add more than one collection they will be place stacked, that's not an accesible approach.
The idea is to implement an algorithm that:
- Will find for free spots (or at least the ones with less collision area).
- Will propose a where to place the collection starting in the center of the visible area.
- Will place next tables following an spiral path.
Once the table is added we should highlight it using some animation just to let the user know where has been placed.
There's an initial POC implemented:
https://github.com/Lemoncode/auto-arrange-playground
And how it works:
https://github.com/Lemoncode/mongo-modeler/assets/1457912/447236a3-4364-427c-8428-996088c2abd6
A previous discussion is needed before starting integrating the POC, the steps:
- Understand the current solution (team start).
- Adapt it to mongo modeler as is and give it a try.
- Enhance it and add unit testing once we check that it fits with Mongo Modeler.
Steps to implement this:
-
In common under common/helper create a subfolder called
autorrange-table. -
Under that subfolder create a
autoarrange-table.model.tswe will slightly update the model (removecolorfield).
./src/common/autoarrange-table/autoarrange-table.model.ts
export interface Box {
x: number;
y: number;
width: number;
height: number;
}
- Add the util to calculate overlapping etc...
./src/common/autoarrange-table/autoarrange-table.utils.ts
import { Box } from './autoarrange-table.model';
export const getRandomInt = (min: number, max: number): number => {
return Math.floor(Math.random() * (max - min + 1)) + min;
};
export const isOverlapping = (box1: Box, box2: Box): boolean => {
return (
box1.x < box2.x + box2.width &&
box1.x + box1.width > box2.x &&
box1.y < box2.y + box2.height &&
box1.y + box1.height > box2.y
);
};
export const calculateCollisionArea = (box1: Box, box2: Box): number => {
const xOverlap = Math.max(
0,
Math.min(box1.x + box1.width, box2.x + box2.width) -
Math.max(box1.x, box2.x)
);
const yOverlap = Math.max(
0,
Math.min(box1.y + box1.height, box2.y + box2.height) -
Math.max(box1.y, box2.y)
);
return xOverlap * yOverlap;
};
And create the main file:
./src/common/autoarrange-table/index.ts
import { Box, Size } from "../model";
import { calculateCollisionArea, isOverlapping } from "./canvas.utils";
function* spiralPositions(
centerX: number,
centerY: number,
canvasSize: Size
): Generator<[number, number]> {
let x = 0,
y = 0,
dx = 0,
dy = -1;
for (let i = 0; i < Math.max(canvasSize.width, canvasSize.height) ** 2; i++) {
if (
-canvasSize.width / 2 < x &&
x < canvasSize.width / 2 &&
-canvasSize.height / 2 < y &&
y < canvasSize.height / 2
) {
yield [centerX + x, centerY + y];
}
if (x === y || (x < 0 && x === -y) || (x > 0 && x === 1 - y)) {
[dx, dy] = [-dy, dx];
}
x += dx;
y += dy;
}
}
export function findFreePositionOrMinCollision(
boxes: Box[],
newBoxSize: Size,
canvasSize: Size
): Box | null {
const centerX = Math.floor(canvasSize.width / 2);
const centerY = Math.floor(canvasSize.height / 2);
let minCollisionBox: Box | null = null;
let minCollisionArea = Infinity;
for (const [x, y] of spiralPositions(centerX, centerY, canvasSize)) {
const newBox = {
x,
y,
width: newBoxSize.width,
height: newBoxSize.height,
// TODO: we will remove this once we get rid of the poc
// and integrate this into the main app
color: "orange",
};
if (
x >= 0 &&
y >= 0 &&
x + newBoxSize.width <= canvasSize.width &&
y + newBoxSize.height <= canvasSize.height
) {
let collisionArea = 0;
let isFree = true;
for (const existingBox of boxes) {
if (isOverlapping(newBox, existingBox)) {
isFree = false;
collisionArea += calculateCollisionArea(newBox, existingBox);
}
}
if (isFree) {
return newBox;
}
if (collisionArea < minCollisionArea) {
minCollisionArea = collisionArea;
minCollisionBox = newBox;
}
}
}
if (minCollisionBox !== null) {
return minCollisionBox;
}
// TODO: if no free position is found, return a random one
return null;
}
Now on the Add table handler let's use the findFreePositionOrMinCollision, to add a new collection, things to take into consideration:
- Let's map all the tables from
TableVmtoBox(just create a mapper), to take into account we will have to calculate the fullsize of each table (witdth and height) and add a margin e.g. 40px. - Then call
findFreePositionOrMinCollisionpassing the box collection and the current view size (canvasViewSettings.scrollPosition.x,canvasViewSettings.scrollPosition.y, and the current subview with the width and height of the part that is shown. - Add some transition or animation to highlight the table temporarily once is created
Check that the approach is working, then we will do a second iteration (refactor the code, add unit testing etc...)
- Langage dominant
- TypeScript
- Étoiles
- 139
- Forks
- 40
- Métriques de merge des PR
- Aucune PR mergée en 30 j
Préparer son environnement
Ce projet ne fournit ni conteneur de développement, ni Dockerfile, ni guide de contribution : l'installation est à votre charge. Commencez par son README, et consultez notre guide de la première contribution pour les étapes générales.
Par où commencer
- Lisez l'issue en entier, puis le guide de contribution du projet.
- Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
- Forkez le dépôt et travaillez sur une branche.
- Ouvrez une pull request qui référence le numéro de l'issue.
Autres issues de Lemoncode/mongo-modeler
-
Add color customization to relationship lines and tablesPeut-être pris @RamiroRodriguezC l’a pris il y a 150 jours. Ouverte
Difficulté 4/5 3-5 jours Accessibilité débutants 48/100
Lemoncode/mongo-modeler#610 · 2 commentaires ·
-
Array of objects functionalityOuverte
Difficulté 4/5 3-5 jours Accessibilité débutants 48/100
Lemoncode/mongo-modeler#609 ·
-
Difficulté 3/5 1-2 jours Accessibilité débutants 35/100
Lemoncode/mongo-modeler#597 ·
-
[VSCode Extension] Hide Open and Save toolbar buttonsPeut-être à nouveau libre Une pull request pour cette issue a été fermée sans être fusionnée. Ouverte
Difficulté 3/5 1-2 jours Accessibilité débutants 25/100
Lemoncode/mongo-modeler#591 ·
-
[VSCode Extension] Integrate new file functionalityPeut-être à nouveau libre Une pull request pour cette issue a été fermée sans être fusionnée. Ouverte
Difficulté 4/5 3-5 jours Accessibilité débutants 25/100
Lemoncode/mongo-modeler#590 ·
Toutes les issues de Lemoncode/mongo-modeler
Issues similaires
-
Difficulté 1/5 1-3 heures Accessibilité débutants 66/100
Les mainteneurs répondent en général sous 1 jour
-
area:plugins area:security area:skills bug has repro
Difficulté 2/5 1-3 heures Accessibilité débutants 76/100
anthropics/claude-code#105911 ·
Les mainteneurs répondent en général sous 1 jour
-
[ko] Translate /team into KoreanOuvertedocumentation good first issue help wanted
Difficulté 2/5 1-3 heures Accessibilité débutants 74/100
dev-five-git/devup-ui#879 ·
Les mainteneurs répondent en général sous 11 jours
-
openspec-apply-change skill: when blocked, may select a ready artifact unrelated to missingArtifactsOuverte
Difficulté 2/5 1-3 heures Accessibilité débutants 72/100
Fission-AI/OpenSpec#2165 ·
Les mainteneurs répondent en général sous 1 jour
-
🐞 bug 🧐 unconfirmed
Difficulté 2/5 1-3 heures Accessibilité débutants 66/100
Tencent/tdesign-vue-next#7032 · 1 commentaire ·
Les mainteneurs répondent en général sous 1 jour