From bc2681a139cc476c1974770c6221a215e1ddc467 Mon Sep 17 00:00:00 2001 From: Ross Keenan Date: Sat, 29 Jan 2022 15:14:50 +0200 Subject: [PATCH] feat(DataviewNotes): :sparkles: Dataview Notes! Use `BC-dataview-note: query` to run any valid Dataview from-query and add Breadcrumbs to all matching notes --- .vscode/settings.json | 3 +- src/AlternativeHierarchies/DataviewNotes.ts | 61 +++++++++++++++++++++ src/Settings/BreadcrumbsSettingTab.ts | 2 + src/Settings/DataviewNoteSettings.ts | 33 +++++++++++ src/constants.ts | 22 ++++++++ src/interfaces.ts | 2 + src/refreshIndex.ts | 3 + 7 files changed, 125 insertions(+), 1 deletion(-) create mode 100644 src/AlternativeHierarchies/DataviewNotes.ts create mode 100644 src/Settings/DataviewNoteSettings.ts 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();