From 0f3babbb3f507f5e48c06ade14de2435f8976f36 Mon Sep 17 00:00:00 2001 From: Ross Keenan Date: Thu, 12 Aug 2021 13:10:52 +0200 Subject: [PATCH] feat: :sparkles: Multiple field names for each direction in a hierarchy --- src/BreadcrumbsSettingTab.ts | 74 +++++++++++++++++--------------- src/Components/VisComp.svelte | 35 ++++++++++----- src/interfaces.ts | 10 ++--- src/main.ts | 69 +++++++++++++++++++++-------- src/sharedFunctions.ts | 81 ++++++++++++++++++++++++++--------- 5 files changed, 179 insertions(+), 90 deletions(-) diff --git a/src/BreadcrumbsSettingTab.ts b/src/BreadcrumbsSettingTab.ts index 5bc5e1b2..dbaa5caf 100644 --- a/src/BreadcrumbsSettingTab.ts +++ b/src/BreadcrumbsSettingTab.ts @@ -15,7 +15,8 @@ import { } from "src/constants"; import type { Relations, userHierarchy, visTypes } from "src/interfaces"; import type BreadcrumbsPlugin from "src/main"; -import { isInVault, splitAndTrim } from "src/sharedFunctions"; +import { hierToStr, isInVault, splitAndTrim } from "src/sharedFunctions"; +import { isEqual } from "lodash"; export class BreadcrumbsSettingTab extends PluginSettingTab { plugin: BreadcrumbsPlugin; @@ -33,36 +34,36 @@ export class BreadcrumbsSettingTab extends PluginSettingTab { function hierIndex( currHiers: userHierarchy[], - values: [string, string, string] + values: [string[], string[], string[]] ) { return currHiers.findIndex( (hier) => - hier.up === values[0] && - hier.same === values[1] && - hier.down === values[2] + isEqual(hier.up, values[0]) && + isEqual(hier.same, values[1]) && + isEqual(hier.down, values[2]) ); } const addHierarchyRow = ( - values: userHierarchy = { up: "↑", same: "→", down: "↓" }, + values: userHierarchy = { up: ["↑"], same: ["→"], down: ["↓"] }, existing = false ) => { const row = createDiv({ cls: "hierarchy-row" }); const hierarchyNames = row.createSpan({}); - const upInput = hierarchyNames.createEl("input", { value: values.up }); + const upInput = hierarchyNames.createEl("input", { + value: values.up.join(", "), + }); const sameInput = hierarchyNames.createEl("input", { - value: values.same, + value: values.same.join(", "), }); const downInput = hierarchyNames.createEl("input", { - value: values.down, + value: values.down.join(", "), }); - let cleanInputs: [string, string, string] = [ - upInput.value, - sameInput.value, - downInput.value, - ]; + let cleanInputs = [upInput.value, sameInput.value, downInput.value].map( + splitAndTrim + ) as [string[], string[], string[]]; [upInput, sameInput, downInput].forEach((input) => input.addEventListener("change", () => { @@ -74,11 +75,12 @@ export class BreadcrumbsSettingTab extends PluginSettingTab { const deleteButton = row.createEl("button", { text: "X" }, (el) => { el.addEventListener("click", async () => { row.remove(); - const removeIndex = hierIndex(plugin.settings.userHierarchies, [ - upInput.value, - sameInput.value, - downInput.value, - ]); + const removeIndex = hierIndex( + plugin.settings.userHierarchies, + [upInput.value, sameInput.value, downInput.value].map( + splitAndTrim + ) as [string[], string[], string[]] + ); if (removeIndex > -1) { plugin.settings.userHierarchies.splice(removeIndex, 1); @@ -108,24 +110,27 @@ export class BreadcrumbsSettingTab extends PluginSettingTab { await plugin.saveSettings(); } } - cleanInputs = [upInput.value, sameInput.value, downInput.value]; + cleanInputs = [upInput.value, sameInput.value, downInput.value].map( + splitAndTrim + ) as [string[], string[], string[]]; saveButton.toggleClass("hierarchy-unsaved", false); saveButton.textContent = "Saved"; if ( - hierIndex(plugin.settings.userHierarchies, [ - upInput.value, - sameInput.value, - downInput.value, - ]) > -1 + hierIndex( + plugin.settings.userHierarchies, + [upInput.value, sameInput.value, downInput.value].map( + splitAndTrim + ) as [string[], string[], string[]] + ) > -1 ) { new Notice( "A hierarchy with these Up, Same, and Down values already exists." ); } else { plugin.settings.userHierarchies.push({ - up: upInput.value, - same: sameInput.value, - down: downInput.value, + up: splitAndTrim(upInput.value), + same: splitAndTrim(sameInput.value), + down: splitAndTrim(downInput.value), }); await plugin.saveSettings(); new Notice("Hierarchy saved."); @@ -160,6 +165,7 @@ export class BreadcrumbsSettingTab extends PluginSettingTab { fieldDetails.append(addHierarchyRow()); }); }); + console.log(splitAndTrim("")); fieldDetails.createEl( "button", @@ -177,15 +183,13 @@ export class BreadcrumbsSettingTab extends PluginSettingTab { fieldDetails.createEl("button", { text: "Show Hierarchies" }, (el) => { el.addEventListener("click", () => { - if (plugin.settings.userHierarchies.length === 0) { + if (plugin.settings.userHierarchies.length) { + new Notice( + plugin.settings.userHierarchies.map(hierToStr).join("\n\n") + ); + } else { new Notice("No hierarchies currently exist."); - return; } - let hierText = ""; - plugin.settings.userHierarchies.forEach((hier) => { - hierText += `up: ${hier.up}, same: ${hier.same}, down: ${hier.down}\n`; - }); - new Notice(hierText); console.log({ hierarchies: plugin.settings.userHierarchies }); }); }); diff --git a/src/Components/VisComp.svelte b/src/Components/VisComp.svelte index 7ea326bb..19cc5214 100644 --- a/src/Components/VisComp.svelte +++ b/src/Components/VisComp.svelte @@ -5,7 +5,12 @@ VisGraphs, visTypes, } from "src/interfaces"; - import { closeImpliedLinks, removeUnlinkedNodes } from "src/sharedFunctions"; + import { + closeImpliedLinks, + getAllXGs, + mergeGs, + removeUnlinkedNodes, + } from "src/sharedFunctions"; import type { VisModal } from "src/VisModal"; import { arcDiagram } from "src/Visualisations/ArcDiagram"; import { circlePacking } from "src/Visualisations/CirclePacking"; @@ -53,19 +58,27 @@ Math.round(window.innerHeight / 1.3), ]; - const { gParents, gSiblings, gChildren } = plugin.currGraphs; + const allUps = getAllXGs(plugin, "up"); + const allSames = getAllXGs(plugin, "same"); + const allDowns = getAllXGs(plugin, "down"); + console.log({ allUps, allDowns }); + + const upG = mergeGs(...Object.values(allUps)); + const sameG = mergeGs(...Object.values(allSames)); + const downG = mergeGs(...Object.values(allDowns)); + console.log({ upG, downG }); const [closedParentNoSingle, closedSiblingNoSingle, closedChildNoSingle] = [ - closeImpliedLinks(gParents, gChildren), - closeImpliedLinks(gSiblings, gSiblings), - closeImpliedLinks(gChildren, gParents), + closeImpliedLinks(upG, downG), + closeImpliedLinks(sameG, sameG), + closeImpliedLinks(downG, upG), ]; const graphs: VisGraphs = { Parent: { Real: { - All: gParents, - "No Unlinked": removeUnlinkedNodes(gParents), + All: upG, + "No Unlinked": removeUnlinkedNodes(upG), }, Closed: { All: closedParentNoSingle, @@ -74,8 +87,8 @@ }, Sibling: { Real: { - All: gSiblings, - "No Unlinked": removeUnlinkedNodes(gSiblings), + All: sameG, + "No Unlinked": removeUnlinkedNodes(sameG), }, Closed: { All: closedSiblingNoSingle, @@ -84,8 +97,8 @@ }, Child: { Real: { - All: gChildren, - "No Unlinked": removeUnlinkedNodes(gChildren), + All: downG, + "No Unlinked": removeUnlinkedNodes(downG), }, Closed: { All: closedChildNoSingle, diff --git a/src/interfaces.ts b/src/interfaces.ts index adfb7cb3..4ebae924 100644 --- a/src/interfaces.ts +++ b/src/interfaces.ts @@ -3,9 +3,6 @@ import type { FrontMatterCache, Pos, TFile } from "obsidian"; export interface BreadcrumbsSettings { userHierarchies: userHierarchy[]; - // parentFieldName: string; - // siblingFieldName: string; - // childFieldName: string; indexNote: string[]; refreshIntervalTime: number; defaultView: boolean; @@ -44,10 +41,11 @@ export interface dvFrontmatterCache { | TFile; } +export type Directions = "up" | "same" | "down"; export interface userHierarchy { - up: string; - same: string; - down: string; + up: string[]; + same: string[]; + down: string[]; } export interface dvLink { diff --git a/src/main.ts b/src/main.ts index 944759b4..bb6fd134 100644 --- a/src/main.ts +++ b/src/main.ts @@ -10,6 +10,7 @@ import { } from "src/constants"; import type { BreadcrumbsSettings, + Directions, dvFrontmatterCache, relObj, } from "src/interfaces"; @@ -77,7 +78,11 @@ export default class BreadcrumbsPlugin extends Plugin { settings: BreadcrumbsSettings; visited: [string, HTMLDivElement][]; refreshIntervalID: number; - currGraphs: { [field: string]: Graph }[]; + currGraphs: { + up: { [field: string]: Graph }; + same: { [field: string]: Graph }; + down: { [field: string]: Graph }; + }[]; async onload(): Promise { console.log("loading breadcrumbs plugin"); @@ -194,16 +199,23 @@ export default class BreadcrumbsPlugin extends Plugin { g: Graph, currFileName: string, fields: string[], - relationship: string + dir: Directions, + fieldName: string ): void { - g.setNode(currFileName, relationship); - if (relationship === "") return; + g.setNode(currFileName, { dir, fieldName }); + if (fieldName === "") return; fields.forEach((field) => { - g.setEdge(currFileName, field, relationship); + g.setEdge(currFileName, field, { dir, fieldName }); }); } - async initGraphs(): Promise<{ [field: string]: Graph }[]> { + async initGraphs(): Promise< + { + up: { [field: string]: Graph }; + same: { [field: string]: Graph }; + down: { [field: string]: Graph }; + }[] + > { debug(this.settings, "initialising graphs"); const files = this.app.vault.getMarkdownFiles(); @@ -216,30 +228,51 @@ export default class BreadcrumbsPlugin extends Plugin { } const relObjArr = await getNeighbourObjArr(this, fileFrontmatterArr); + console.log({ relObjArr }); const { userHierarchies } = this.settings; - const allFields: string[] = userHierarchies - .map((hier) => Object.values(hier)) - .flat() - .filter((field: string) => field !== ""); - const graphs: { [field: string]: Graph }[] = []; + const graphs: { + up: { [field: string]: Graph }; + same: { [field: string]: Graph }; + down: { [field: string]: Graph }; + }[] = []; userHierarchies.forEach((hier, i) => { - const newGraphs: { [field: string]: Graph } = {}; - newGraphs[hier.up] = new Graph(); - newGraphs[hier.same] = new Graph(); - newGraphs[hier.down] = new Graph(); + const newGraphs: { + up: { [field: string]: Graph }; + same: { [field: string]: Graph }; + down: { [field: string]: Graph }; + } = { up: {}, same: {}, down: {} }; + + Object.keys(hier).forEach((dir: Directions) => { + hier[dir].forEach((dirField) => { + newGraphs[dir][dirField] = new Graph(); + }); + }); + graphs.push(newGraphs); }); + console.log({ graphs }); relObjArr.forEach((relObj) => { const currFileName = relObj.current.basename || relObj.current.name; relObj.hierarchies.forEach((hier, i) => { - Object.keys(hier).forEach((key) => { - const fields = hier[key]; - this.populateGraph(graphs[i][key], currFileName, fields, key); + Object.keys(hier).forEach((dir: Directions) => { + const fieldsObj: { + [field: string]: string[]; + } = hier[dir]; + + Object.keys(fieldsObj).forEach((fieldName) => { + this.populateGraph( + graphs[i][dir][fieldName], + currFileName, + fieldsObj[fieldName], + dir, + fieldName + ); + }); }); }); }); diff --git a/src/sharedFunctions.ts b/src/sharedFunctions.ts index 083dd830..93185cc2 100644 --- a/src/sharedFunctions.ts +++ b/src/sharedFunctions.ts @@ -17,6 +17,7 @@ import type { JugglLink, neighbourObj, relObj, + userHierarchy, } from "src/interfaces"; import type BreadcrumbsPlugin from "src/main"; import type MatrixView from "src/MatrixView"; @@ -212,14 +213,15 @@ export async function getNeighbourObjArr( ): Promise< { current: TFile; - hierarchies: { [field: string]: string[] }[]; + hierarchies: { + up: { [field: string]: string[] }; + same: { [field: string]: string[] }; + down: { [field: string]: string[] }; + }[]; }[] > { const { userHierarchies } = plugin.settings; - const allFields: string[] = userHierarchies - .map((hier) => Object.values(hier)) - .flat() - .filter((field: string) => field !== ""); + console.log({ userHierarchies }); let jugglLinks: JugglLink[] = []; if (plugin.app.plugins.plugins.juggl !== undefined) { @@ -228,27 +230,54 @@ export async function getNeighbourObjArr( const neighbourObjArr: { current: TFile; - hierarchies: { [field: string]: string[] }[]; + hierarchies: { + up: { [field: string]: string[] }; + same: { [field: string]: string[] }; + down: { [field: string]: string[] }; + }[]; }[] = fileFrontmatterArr.map((fileFrontmatter) => { const hierFields: { current: TFile; - hierarchies: { [field: string]: string[] }[]; + hierarchies: { + up: { [field: string]: string[] }; + same: { [field: string]: string[] }; + down: { [field: string]: string[] }; + }[]; } = { current: fileFrontmatter.file, hierarchies: [], }; userHierarchies.forEach((hier, i) => { - const fields: string[] = Object.values(hier); - const newHier: { [field: string]: string[] } = {}; - fields.forEach((field) => { - const fieldValues = getFieldValues( + const fieldsArr = Object.values(hier) as [string[], string[], string[]]; + const newHier: { + up: { [field: string]: string[] }; + same: { [field: string]: string[] }; + down: { [field: string]: string[] }; + } = { up: {}, same: {}, down: {} }; + + fieldsArr[0].forEach((upField) => { + newHier.up[upField] = getFieldValues( + fileFrontmatter, + upField, + plugin.settings + ); + }); + fieldsArr[1].forEach((sameField) => { + newHier.same[sameField] = getFieldValues( + fileFrontmatter, + sameField, + plugin.settings + ); + }); + fieldsArr[2].forEach((downField) => { + newHier.down[downField] = getFieldValues( fileFrontmatter, - field, + downField, plugin.settings ); - newHier[field] = fieldValues; }); + hierFields.hierarchies.push(newHier); }); @@ -447,21 +476,33 @@ export function removeUnlinkedNodes(g: Graph) { export function getAllXGs( plugin: BreadcrumbsPlugin, - rel: "up" | "same" | "down" + dir: "up" | "same" | "down" ) { const { userHierarchies } = plugin.settings; + const fieldNamesInXDir = userHierarchies - .map((hier) => hier[rel]) - .filter((field) => field !== ""); - const currHiers = plugin.currGraphs; + .map((hier) => hier[dir]) + .filter((field) => field.join() !== "") + .flat(); + + console.log({ fieldNamesInXDir }); + + const { currGraphs } = plugin; const allXGs: { [rel: string]: Graph } = {}; - currHiers.forEach((hier) => { + + currGraphs.forEach((hierarchyGs) => { fieldNamesInXDir.forEach((field) => { - const graph = hier[field]; - if (hier[field]) { + const graph = hierarchyGs[dir][field]; + if (graph) { allXGs[field] = graph; } }); }); return allXGs; } + +export function hierToStr(hier: userHierarchy) { + return `↑: ${hier.up.join(", ")}. +→: ${hier.same.join(", ")}. +↓: ${hier.down.join(", ")}.`; +}