change firstSeen to mappedRelationsIndex

This commit is contained in:
Marc-Roig 2023-01-05 16:44:18 +01:00
parent 8bf254faac
commit a05bdd83ae

View File

@ -25,39 +25,41 @@ const sortConnectArray = (connectArr, initialArr = [], strictSort = true) => {
// Boolean to know if we have to recalculate the order of the relations // Boolean to know if we have to recalculate the order of the relations
let needsSorting = false; let needsSorting = false;
// Map to validate if relation is already in sortedConnect or DB. // Map to validate if relation is already in sortedConnect or DB.
const relInArray = initialArr.reduce((acc, rel) => ({ ...acc, [rel.id]: true }), {}); const relationInArray = initialArr.reduce((acc, rel) => ({ ...acc, [rel.id]: true }), {});
// Map to store the first index where a relation id is connected // Map to store the first index where a relation id is connected
const firstSeen = {}; const mappedRelationsIndex = connectArr.reduce((mapper, relation, index) => {
const adjacentRelId = relation.position?.before || relation.position?.after;
if (!relationInArray[adjacentRelId] && !mapper[adjacentRelId]) {
needsSorting = true;
}
return {
[relation.id]: mapper[relation.id] || index, // If the relation is already in the array, we keep the first index
...mapper,
};
}, {});
// Map to validate if connect relation has already been computed // Map to validate if connect relation has already been computed
const computedIdx = {}; const computedIdx = {};
connectArr.forEach((rel, idx) => {
// If adjacent relation is not in the database or seen yet in the connect array
// then we need to sort the connect array
const adjacentRelId = rel.position?.before || rel.position?.after;
if (!relInArray[adjacentRelId] && !firstSeen[adjacentRelId]) needsSorting = true;
// Populate firstSeen
if (!(rel.id in firstSeen)) firstSeen[rel.id] = idx;
});
// If we don't need to sort the connect array, we can return it as is // If we don't need to sort the connect array, we can return it as is
if (!needsSorting) return connectArr; if (!needsSorting) return connectArr;
// Add relation to sortedConnect and mark it as seen // Add relation to sortedConnect and mark it as seen
const pushRelation = (rel) => { const pushRelation = (relation) => {
sortedConnect.push(rel); sortedConnect.push(relation);
relInArray[rel.id] = true; relationInArray[relation.id] = true;
}; };
// Recursively compute in which order the relation should be connected // Recursively compute in which order the relation should be connected
const computeRelation = (rel, idx, relationsSeenInBranch) => { const computeRelation = (relation, idx, relationsSeenInBranch) => {
const adjacentRelId = rel.position?.before || rel.position?.after; const adjacentRelId = relation.position?.before || relation.position?.after;
// This connect has already been computed // This connect has already been computed
if (idx in computedIdx) return; if (idx in computedIdx) return;
if (!adjacentRelId || relInArray[adjacentRelId]) { if (!adjacentRelId || relationInArray[adjacentRelId]) {
return pushRelation(rel); return pushRelation(relation);
} }
// If the relation has already been seen in the current branch, // If the relation has already been seen in the current branch,
@ -70,7 +72,7 @@ const sortConnectArray = (connectArr, initialArr = [], strictSort = true) => {
} }
// Look if id is referenced elsewhere in the array // Look if id is referenced elsewhere in the array
const adjacentRelIdx = firstSeen[adjacentRelId]; const adjacentRelIdx = mappedRelationsIndex[adjacentRelId];
if (adjacentRelIdx) { if (adjacentRelIdx) {
const adjacentRel = connectArr[adjacentRelIdx]; const adjacentRel = connectArr[adjacentRelIdx];
@ -78,25 +80,27 @@ const sortConnectArray = (connectArr, initialArr = [], strictSort = true) => {
// Mark adjacent relation idx as computed, // Mark adjacent relation idx as computed,
// so it is not computed again later in the loop // so it is not computed again later in the loop
computedIdx[adjacentRelIdx] = true; computedIdx[adjacentRelIdx] = true;
computeRelation(adjacentRel, idx, { ...relationsSeenInBranch, [rel.id]: true }); computeRelation(adjacentRel, idx, { ...relationsSeenInBranch, [relation.id]: true });
pushRelation(rel); pushRelation(relation);
} else if (strictSort) { } else if (strictSort) {
// If we reach this point, it means that the adjacent relation is not in the connect array // If we reach this point, it means that the adjacent relation is not in the connect array
// and it is not in the database. This should not happen. // and it is not in the database. This should not happen.
throw new InvalidRelationError( throw new InvalidRelationError(
`There was a problem connecting relation with id ${rel.id} at position ${JSON.stringify( `There was a problem connecting relation with id ${
rel.position relation.id
} at position ${JSON.stringify(
relation.position
)}. The relation with id ${adjacentRelId} needs to be connected first.` )}. The relation with id ${adjacentRelId} needs to be connected first.`
); );
} else { } else {
// We are in non-strict mode so we can push the relation. // We are in non-strict mode so we can push the relation.
pushRelation({ id: rel.id, position: { end: true } }); pushRelation({ id: relation.id, position: { end: true } });
} }
}; };
// Iterate over connectArr and populate sortedConnect // Iterate over connectArr and populate sortedConnect
connectArr.forEach((rel, idx) => { connectArr.forEach((relation, idx) => {
computeRelation(rel, idx, {}); computeRelation(relation, idx, {});
}); });
return sortedConnect; return sortedConnect;
@ -184,8 +188,7 @@ const relationsOrderer = (initArr, idColumn, orderColumn, strict) => {
return this; return this;
}, },
connect(relations) { connect(relations) {
const sortedRelations = sortConnectArray(relations, arr, strict); sortConnectArray(_.castArray(relations), arr, strict).forEach((relation) => {
sortedRelations.forEach((relation) => {
this.disconnect(relation); this.disconnect(relation);
try { try {