HGustavs / LenaSYS

Code Viewer and Course Organization System used in some courses at University of Skövde
57 stars 31 forks source link

Recursive relation is not possible on ER diagram #15678

Closed a22vioja closed 5 months ago

a22vioja commented 5 months ago

Description

Recursive relation (self-join) is not possible on ER diagram.

https://github.com/HGustavs/LenaSYS/assets/129263559/2967c0e8-67f0-4d16-ae13-fbee8804efd6

Job

Make ir possible to do a recursive relation on ER entity.

a22hanfa commented 5 months ago

This issue relates to the code responsible for positioning lines in recursive relations within diagrams, found in the old drawLine-function in diagram.js. It was stopped working in week 3 of 2024, this is due to a lot of functions being changed for the better, so some of the functionality was lost.

The code snippet was found in the old drawLine-function:

// Overwrite line positioning on recursive relations (2 lines pointing to same EREntity)
var connections = felem.neighbours[telem.id].length;
if (connections === 2) {
    var isFirst = felem.neighbours[telem.id][0].id === line.id;
    var fromRelation = felem.kind === "ERRelation";
    lengthConstant = 0;

    if (fromRelation) {
        if (line.ctype == "BT") {
            fy = felem.cy;
            fx = (isFirst) ? felem.x1 : felem.x2;
        } else if (line.ctype == "TB") {
            fy = felem.cy;
            fx = (isFirst) ? felem.x1 : felem.x2;
        } else if (line.ctype == "RL") {
            fx = felem.cx;
            fy = (isFirst) ? felem.y1 : felem.y2;
        } else if (line.ctype == "LR") {
            fx = felem.cx;
            fy = (isFirst) ? felem.y1 : felem.y2;
        }

        if (isFirst) {
            telem.recursivePos = getPoint(tx, ty);
        } else {
            tx = telem.recursivePos.x;
            ty = telem.recursivePos.y;
            delete telem.recursivePos;
        }

    } else {
        if (line.ctype == "BT") {
            ty = telem.cy;
            tx = (isFirst) ? telem.x1 : telem.x2;
        } else if (line.ctype == "TB") {
            ty = telem.cy;
            tx = (isFirst) ? telem.x1 : telem.x2;
        } else if (line.ctype == "RL") {
            tx = telem.cx;
            ty = (isFirst) ? telem.y1 : telem.y2;
        } else if (line.ctype == "LR") {
            tx = telem.cx;
            ty = (isFirst) ? telem.y1 : telem.y2;
        }

        if (isFirst) {
            felem.recursivePos = getPoint(fx, fy);
        } else {
            fx = felem.recursivePos.x;
            fy = felem.recursivePos.y;
            delete felem.recursivePos;
        }
    }
}

I do expect that this was where the lines where drawn. Therefore, I do believe that by reimplementing this function you could get the functionality once again.

The provided additional code snippet defines a special case for relations and entities that can have two lines. This logic ensures that a new line is created only if there are no existing lines or if it's a special case where one line already exists. I do believe that this might be relevant, this can be found in the function addLine.

// Define a boolean for special case that relation and entity can have 2 lines
    let specialCase = (
        fromElement.kind === elementTypesNames.ERRelation &&
        toElement.kind === elementTypesNames.EREntity ||
        fromElement.kind === elementTypesNames.EREntity &&
        toElement.kind === elementTypesNames.ERRelation
    );
    // If there is no existing lines or is a special case
    if (numOfExistingLines === 0 || (specialCase && numOfExistingLines === 1)) {
        let newLine = {
            id: makeRandomID(),
            fromID: fromElement.id,
            toID: toElement.id,
            kind: kind
        };

        // If the new line has an entity FROM or TO, add a cardinality ONLY if it's passed as a parameter.
        if (isLineConnectedTo(newLine, elementTypesNames.EREntity)) {
            if (cardinal) newLine.cardinality = cardinal;
        }
        preProcessLine(newLine);
        addObjectToLines(newLine, stateMachineShouldSave);
        if (successMessage) displayMessage(messageTypes.SUCCESS, `Created new line between: ${fromElement.name} and ${toElement.name}`);
        result = newLine;
    }