diff --git a/.vscode/settings.json b/.vscode/settings.json
index ac5149f7..0ff628a8 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -25,6 +25,7 @@
"NamingNotes",
"Codeblock",
"TreeView",
- "impliedRelations"
+ "impliedRelations",
+ "DataviewNotes"
]
}
\ No newline at end of file
diff --git a/src/AlternativeHierarchies/DataviewNotes.ts b/src/AlternativeHierarchies/DataviewNotes.ts
new file mode 100644
index 00000000..e1921d44
--- /dev/null
+++ b/src/AlternativeHierarchies/DataviewNotes.ts
@@ -0,0 +1,61 @@
+import type { MultiGraph } from "graphology";
+import { Notice } from "obsidian";
+import { BC_DV_NOTE, BC_DV_NOTE_FIELD, DATAVIEW_MISSING } from "../constants";
+import type { dvFrontmatterCache } from "../interfaces";
+import type BCPlugin from "../main";
+import {
+ getSourceOrder,
+ getTargetOrder,
+ populateMain,
+} from "../Utils/graphUtils";
+import { getFields } from "../Utils/HierUtils";
+import { getDVApi, getDVBasename } from "../Utils/ObsidianUtils";
+
+export function addDataviewNotesToGraph(
+ plugin: BCPlugin,
+ eligableAlts: dvFrontmatterCache[],
+ frontms: dvFrontmatterCache[],
+ mainG: MultiGraph
+) {
+ const { settings } = plugin;
+ const { userHiers, dataviewNoteField } = settings;
+ const dv = getDVApi(plugin);
+ if (!dv) {
+ new Notice(DATAVIEW_MISSING);
+ }
+
+ const fields = getFields(userHiers);
+
+ eligableAlts.forEach((altFile) => {
+ const basename = getDVBasename(altFile.file);
+ const query = altFile[BC_DV_NOTE] as string;
+
+ let field =
+ (altFile[BC_DV_NOTE_FIELD] as string) ?? (dataviewNoteField || fields[0]);
+
+ let targets: dvFrontmatterCache[] = [];
+ try {
+ targets = dv.pages(query).values;
+ } catch (er) {
+ new Notice(`${query} is not a valid Dataview from-query`);
+ console.log(er);
+ }
+
+ for (const target of targets) {
+ const targetBN = getDVBasename(target.file);
+ const sourceOrder = getSourceOrder(altFile);
+ const targetOrder = getTargetOrder(frontms, targetBN);
+
+ populateMain(
+ settings,
+ mainG,
+ basename,
+ field,
+ targetBN,
+ sourceOrder,
+ targetOrder,
+ true
+ );
+ }
+ });
+}
diff --git a/src/Settings/BreadcrumbsSettingTab.ts b/src/Settings/BreadcrumbsSettingTab.ts
index 9095a6a4..f4f529f1 100644
--- a/src/Settings/BreadcrumbsSettingTab.ts
+++ b/src/Settings/BreadcrumbsSettingTab.ts
@@ -1,4 +1,5 @@
import { App, PluginSettingTab, Setting } from "obsidian";
+import { addDataviewSettings } from "./DataviewNoteSettings";
import KoFi from "../Components/KoFi.svelte";
import type BCPlugin from "../main";
import { addCreateIndexSettings } from "./CreateIndexSettings";
@@ -113,6 +114,7 @@ export class BCSettingTab extends PluginSettingTab {
addHierarchyNoteSettings(plugin, alternativeHierarchyDetails);
addCSVSettings(plugin, alternativeHierarchyDetails);
addDendronSettings(plugin, alternativeHierarchyDetails);
+ addDataviewSettings(plugin, alternativeHierarchyDetails);
const cmdsDetails = details("Commands", containerEl);
addWriteBCsSettings(plugin, cmdsDetails);
diff --git a/src/Settings/DataviewNoteSettings.ts b/src/Settings/DataviewNoteSettings.ts
new file mode 100644
index 00000000..24b38c4b
--- /dev/null
+++ b/src/Settings/DataviewNoteSettings.ts
@@ -0,0 +1,33 @@
+import { DropdownComponent, Setting } from "obsidian";
+import type BCPlugin from "../main";
+import { refreshIndex } from "../refreshIndex";
+import { getFields } from "../Utils/HierUtils";
+import { fragWithHTML, subDetails } from "./BreadcrumbsSettingTab";
+
+export function addDataviewSettings(
+ plugin: BCPlugin,
+ alternativeHierarchyDetails: HTMLDetailsElement
+) {
+ const { settings } = plugin;
+ const { userHiers } = settings;
+ const fields = getFields(userHiers);
+ const dvDetails = subDetails("Dataview Notes", alternativeHierarchyDetails);
+
+ new Setting(dvDetails)
+ .setName("Default Tag Note Field")
+ .setDesc(
+ fragWithHTML(
+ "By default, Dataview notes use the first field in your hierarchies (usually an ↑
field). Choose a different one to use by default, without having to specify BC-dataview-note-field: {field}
.If you don't want to choose a default, select the blank option at the bottom of the list."
+ )
+ )
+ .addDropdown((dd: DropdownComponent) => {
+ const options = {};
+ fields.forEach((field) => (options[field] = field));
+ dd.addOptions(Object.assign(options, { "": "" }));
+ dd.onChange(async (field) => {
+ settings.dataviewNoteField = field;
+ await plugin.saveSettings();
+ await refreshIndex(plugin);
+ });
+ });
+}
diff --git a/src/constants.ts b/src/constants.ts
index 87aef9e7..0d28c013 100644
--- a/src/constants.ts
+++ b/src/constants.ts
@@ -143,6 +143,8 @@ export const [
BC_TRAVERSE_NOTE,
BC_REGEX_NOTE,
BC_REGEX_NOTE_FIELD,
+ BC_DV_NOTE,
+ BC_DV_NOTE_FIELD,
BC_IGNORE_DENDRON,
BC_HIDE_TRAIL,
BC_ORDER,
@@ -156,6 +158,8 @@ export const [
"BC-traverse-note",
"BC-regex-note",
"BC-regex-note-field",
+ "BC-dataview-note",
+ "BC-dataview-note-field",
"BC-ignore-dendron",
"BC-hide-trail",
"BC-order",
@@ -225,6 +229,20 @@ export const BC_FIELDS_INFO = [
afterInline: ":: ",
alt: false,
},
+ {
+ field: BC_DV_NOTE,
+ desc: "Set this note as a Breadcrumbs Dataview-note. The value of this field is a Dataview `from` query. All notes that match the query will be added to the BC graph using the default fieldName specified in `Settings > Alternative Hierarchies > Dataview Notes > Default Field`, or using the fieldName you specify in 'BC-dataview-note-field'.",
+ afterYaml: ": '",
+ afterInline: ":: ",
+ alt: true,
+ },
+ {
+ field: BC_DV_NOTE_FIELD,
+ desc: "Manually choose the field for this Dataview-note to use",
+ afterYaml: ": ",
+ afterInline: ":: ",
+ alt: false,
+ },
{
field: BC_IGNORE_DENDRON,
desc: "Tells Breadcrumbs to not treat this note as a dendron note (only useful if the note name has you dendron splitter in it, usually a period `.`).",
@@ -262,6 +280,9 @@ export const ILLEGAL_FILENAME_CHARS = [
"|",
];
+export const DATAVIEW_MISSING =
+ "The Dataview plugin must be installed for this to work";
+
export const DEFAULT_SETTINGS: BCSettings = {
addDendronNotes: false,
aliasesInIndex: false,
@@ -269,6 +290,7 @@ export const DEFAULT_SETTINGS: BCSettings = {
altLinkFields: [],
CSVPaths: "",
dateFormat: "YYYY-MM-DD",
+ dataviewNoteField: "up",
debugMode: "WARN",
defaultView: true,
dendronNoteDelimiter: ".",
diff --git a/src/interfaces.ts b/src/interfaces.ts
index 40ee657b..43ea67db 100644
--- a/src/interfaces.ts
+++ b/src/interfaces.ts
@@ -20,6 +20,7 @@ export interface BCSettings {
altLinkFields: string[];
CSVPaths: string;
dvWaitTime: number;
+ dataviewNoteField: string;
debugMode: DebugLevel;
defaultView: boolean;
dendronNoteDelimiter: string;
@@ -275,6 +276,7 @@ declare module "obsidian" {
dataview: {
api: {
page: (page: string) => dvFrontmatterCache;
+ pages: (query: string) => { values: dvFrontmatterCache[] };
pagePaths: (query?: string) => { values: string[] };
};
};
diff --git a/src/refreshIndex.ts b/src/refreshIndex.ts
index 0324ccc3..c265e604 100644
--- a/src/refreshIndex.ts
+++ b/src/refreshIndex.ts
@@ -3,6 +3,7 @@ import { debug, error } from "loglevel";
import { normalizePath, Notice, Pos, TFile, TFolder } from "obsidian";
import { wait } from "obsidian-community-lib";
import { addCSVCrumbs, getCSVRows } from "./AlternativeHierarchies/CSVCrumbs";
+import { addDataviewNotesToGraph } from "./AlternativeHierarchies/DataviewNotes";
import { addDendronNotesToGraph } from "./AlternativeHierarchies/DendronNotes";
import { addFolderNotesToGraph } from "./AlternativeHierarchies/FolderNotes";
import {
@@ -19,6 +20,7 @@ import { addTagNotesToGraph } from "./AlternativeHierarchies/TagNotes";
import { addTraverseNotesToGraph } from "./AlternativeHierarchies/TraverseNotes";
import {
BC_ALTS,
+ BC_DV_NOTE,
BC_FOLDER_NOTE,
BC_I_AUNT,
BC_I_COUSIN,
@@ -283,6 +285,7 @@ export async function buildMainG(plugin: BCPlugin): Promise {
buildObsGraph(app)
);
addDendronNotesToGraph(plugin, frontms, mainG);
+ addDataviewNotesToGraph(plugin, eligableAlts[BC_DV_NOTE], frontms, mainG);
db.end1G();