Added bidirectional linking (BIG DIFF)

This commit is contained in:
Janet Vorobyeva
2023-09-05 09:22:55 -07:00
parent 1b1970c075
commit d3126bec62
7 changed files with 215 additions and 26 deletions

View File

@@ -644,7 +644,14 @@ export class RightPanel extends Disposable {
const lstate = use(tgtSec.linkingState);
const lfilter = lstate?.filterState ? use(lstate.filterState) : undefined;
const cursorPosStr = lstate?.cursorPos ? `${tgtSec.tableId()}[${use(lstate.cursorPos)}]` : "N/A";
//TODO JV TEMP DEBUG: srcLastUpdated is temporary
const cursorPosStr = (lstate?.cursorPos ? `${tgtSec.tableId()}[${use(lstate.cursorPos)}]` : "N/A") +
`\n srclastEdited: ${use(srcSec.lastCursorEdit)} \n tgtLastEdited: ${use(tgtSec.lastCursorEdit)}` +
`\n incomingCursorPos: ${lstate?.incomingCursorPos ? `${lstate.incomingCursorPos()}` : "N/A"}` +
(() => {
//const;
return '';
})();
//Main link info as a big string, will be in a <pre></pre> block
let preString = "No Incoming Link";

View File

@@ -49,8 +49,12 @@ interface LinkNode {
groupbyColumns?: Set<number>;
// list of ids of the sections that are ancestors to this section according to the linked section
// relationship
ancestors: Set<number>;
// relationship. ancestors[0] is this.section, ancestors[last] is oldest ancestor
ancestors: number[];
//corresponds to ancestors array, but is 1 shorter.
// if isAncCursLink[0] == true, that means the link from ancestors[0] to ancestors[1] is a same-table cursor-link
isAncestorCursorLink: boolean[];
// the section record. Must be the empty record sections that are to be created.
section: ViewSectionRec;
@@ -141,9 +145,39 @@ function isValidLink(source: LinkNode, target: LinkNode) {
}
}
// The link must not create a cycle
if (source.ancestors.has(target.section.getRowId())) {
return false;
//The link must not create a cycle, unless it's only same-table cursor-links all the way to target
if (source.ancestors.includes(target.section.getRowId())) {
//cycles only allowed for cursor links
if(source.column || target.column || source.isSummary) {
return false;
}
// Walk backwards along the chain of ancestors
// - if we hit a non-cursor link before reaching target, then that would be an illegal cycle
// - when we hit target, we've verified that this is a legal cycle, so break
// (ancestors further up the hierarchy past target don't matter, since once we set target.linkSrcSec = src.sec,
// they would stop being ancestors of src)
// NOTE: we're guaranteed to hit target before the end of the array (because of the `if` above)
// but I'm paranoid so let's check and throw if it happens
// ALSO NOTE: isAncestorCursorLink may be 1 shorter than ancestors, but it's accounted for by the above
for(let i = 0; ; i++) {
//We made it! All is well
if(source.ancestors[i] == target.section.getRowId()) {
break;
}
//If we've hit the last ancestor and haven't found target, error out (shouldn't happen)
if(i == source.ancestors.length-1) { throw Error("Error: Array doesn't include targetSection"); }
//Need to keep following links back, make sure this one is cursorLink
if(!source.isAncestorCursorLink[i]) {
return false;
}
}
console.log("===== selectBy found valid cycle", JSON.stringify(source)); //TODO JV TEMP DEBUG
//Yay, this is a valid cycle of same-table cursor-links
}
return true;
@@ -224,15 +258,29 @@ function fromViewSectionRec(section: ViewSectionRec): LinkNode[] {
return [];
}
const table = section.table.peek();
const ancestors = new Set<number>();
const ancestors: number[] = [];
const isAncestorCursorLink: boolean[] = [];
for (let sec = section; sec.getRowId(); sec = sec.linkSrcSection.peek()) {
if (ancestors.has(sec.getRowId())) {
if (ancestors.includes(sec.getRowId())) {
// tslint:disable-next-line:no-console
console.warn(`Links should not create a cycle - section ids: ${Array.from(ancestors)}`);
console.warn(`Links should not create a cycle - section ids: ${ancestors}`);
//TODO JV: change this to only warn if cycles aren't all Cursor:Same-Table
break;
}
ancestors.add(sec.getRowId());
ancestors.push(sec.getRowId());
//isAncestorCursorLink may be 1 shorter than ancestors, since last ancestor has no incoming link
// however if we have a cycle (of cursor-links), then they'll be the same length
if(sec.linkSrcSection.peek().getRowId()) {
//TODO JV TEMP: Dear god determining if something is a cursor link or not is a nightmare
const srcCol = sec.linkSrcCol.peek().getRowId();
const tgtCol = sec.linkTargetCol.peek().getRowId();
const srcTable = sec.linkSrcSection.peek().table.peek();
const srcIsSummary = srcTable.primaryTableId.peek() !== srcTable.tableId.peek();
isAncestorCursorLink.push(srcCol == 0 && tgtCol == 0 && !srcIsSummary);
}
}
const isSummary = table.primaryTableId.peek() !== table.tableId.peek();
@@ -243,6 +291,7 @@ function fromViewSectionRec(section: ViewSectionRec): LinkNode[] {
groupbyColumns: isSummary ? table.summarySourceColRefs.peek() : undefined,
widgetType: section.parentKey.peek(),
ancestors,
isAncestorCursorLink,
section,
};
@@ -280,7 +329,8 @@ function fromPageWidget(docModel: DocModel, pageWidget: IPageWidget): LinkNode[]
// (e.g.: link from summary table with Attachments in group-by) but it seems to work fine as is
groupbyColumns,
widgetType: pageWidget.type,
ancestors: new Set(),
ancestors: [],
isAncestorCursorLink: [],
section: docModel.viewSections.getRowModel(pageWidget.section),
};