Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
8578918
eng-1344 f10b upload obsidian relations and their schemas
maparent Jan 15, 2026
5322113
current progress
trangdoan982 Jan 23, 2026
455b4a8
feature finished
trangdoan982 Jan 23, 2026
b9deb25
address PR comments
trangdoan982 Jan 25, 2026
58e2099
address PR comments
trangdoan982 Jan 26, 2026
5ad8ac8
remove local test file
trangdoan982 Jan 26, 2026
2933462
curr progress
trangdoan982 Jan 27, 2026
5469397
revert what is handled in #721
maparent Feb 5, 2026
5bf1e0b
Use SpaceURI rather than spaceId in frontmatter
maparent Feb 5, 2026
4c6d890
address PR comments
trangdoan982 Feb 7, 2026
5967490
address PR comments
trangdoan982 Feb 8, 2026
9a25b5b
cleanup
trangdoan982 Feb 8, 2026
9a56c72
Update apps/obsidian/src/utils/importNodes.ts
trangdoan982 Feb 8, 2026
649bb02
normalize on using numbers for dates
maparent Feb 8, 2026
af8dc78
correction
maparent Feb 8, 2026
0b34866
apply ctime, mtime to assets
maparent Feb 8, 2026
8f8fb5e
spurious log
maparent Feb 8, 2026
0ecb29d
Preserve ctime, mtime in processFrontMatter. Also timezone correction
maparent Feb 8, 2026
d6ccb28
add lastModified in frontMatter
maparent Feb 8, 2026
cad2844
make sure import image works
trangdoan982 Feb 8, 2026
b094851
add recursive folder creation
trangdoan982 Feb 8, 2026
16fb68f
modify the fetchNodeContent flow; simplify the pathMapping
trangdoan982 Feb 8, 2026
8fb6c26
WIP: shuffle the filePath around
maparent Feb 8, 2026
0b42251
send originalPathDepth
maparent Feb 8, 2026
f7de3e8
actually send path itself
maparent Feb 9, 2026
c8c349c
clarify var name
maparent Feb 9, 2026
045c751
make sure fileImport works for all possible settings
trangdoan982 Feb 10, 2026
e9f96fd
store relative path when rewrite the wikilink instead of default to f…
trangdoan982 Feb 10, 2026
63e5700
cleanup logs
trangdoan982 Feb 10, 2026
1714873
nit
maparent Feb 11, 2026
d9296ab
AI corrections
maparent Feb 11, 2026
3475762
Update apps/obsidian/src/utils/importNodes.ts
trangdoan982 Feb 11, 2026
8487eb0
address PR comments
trangdoan982 Feb 11, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion apps/obsidian/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@
"@octokit/core": "^6.1.2",
"@repo/eslint-config": "workspace:*",
"@repo/typescript-config": "workspace:*",
"@types/mime-types": "3.0.1",
"@types/node": "^20",
"@types/react": "catalog:obsidian",
"@types/react-dom": "catalog:obsidian",
"@types/mime-types": "3.0.1",
"autoprefixer": "^10.4.21",
"builtin-modules": "3.3.0",
"dotenv": "^16.4.5",
Expand All @@ -43,6 +43,7 @@
"@repo/utils": "workspace:*",
"@supabase/supabase-js": "catalog:",
"date-fns": "^4.1.0",
"gray-matter": "^4.0.3",
"mime-types": "^3.0.1",
"nanoid": "^4.0.2",
"react": "catalog:obsidian",
Expand Down
62 changes: 61 additions & 1 deletion apps/obsidian/src/components/DiscourseContextView.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
import { ItemView, TFile, WorkspaceLeaf } from "obsidian";
import { ItemView, TFile, WorkspaceLeaf, Notice } from "obsidian";
import { createRoot, Root } from "react-dom/client";
import DiscourseGraphPlugin from "~/index";
import { getDiscourseNodeFormatExpression } from "~/utils/getDiscourseNodeFormatExpression";
import { RelationshipSection } from "~/components/RelationshipSection";
import { VIEW_TYPE_DISCOURSE_CONTEXT } from "~/types";
import { PluginProvider, usePlugin } from "~/components/PluginContext";
import { getNodeTypeById } from "~/utils/typeUtils";
import { refreshImportedFile } from "~/utils/importNodes";
import { useState } from "react";

type DiscourseContextProps = {
activeFile: TFile | null;
};

const DiscourseContext = ({ activeFile }: DiscourseContextProps) => {
const plugin = usePlugin();
const [isRefreshing, setIsRefreshing] = useState(false);

const extractContentFromTitle = (format: string, title: string): string => {
if (!format) return "";
Expand All @@ -21,6 +24,30 @@ const DiscourseContext = ({ activeFile }: DiscourseContextProps) => {
return match?.[1] ?? title;
};

const handleRefresh = async () => {
if (!activeFile || isRefreshing) return;

setIsRefreshing(true);
try {
const result = await refreshImportedFile({ plugin, file: activeFile });
if (result.success) {
new Notice("File refreshed successfully", 3000);
} else {
new Notice(
`Failed to refresh file: ${result.error || "Unknown error"}`,
5000,
);
}
} catch (error) {
const errorMessage =
error instanceof Error ? error.message : String(error);
new Notice(`Refresh failed: ${errorMessage}`, 5000);
console.error("Refresh failed:", error);
} finally {
setIsRefreshing(false);
}
};

const renderContent = () => {
if (!activeFile) {
return <div>No file is open</div>;
Expand All @@ -45,6 +72,20 @@ const DiscourseContext = ({ activeFile }: DiscourseContextProps) => {
if (!nodeType) {
return <div>Unknown node type: {frontmatter.nodeTypeId}</div>;
}

const isImported = !!frontmatter.importedFromSpaceUri;
const modifiedAt =
typeof frontmatter.lastModified === "number"
? frontmatter.lastModified
: activeFile.stat.mtime;
const sourceDates =
isImported && activeFile?.stat
? {
createdAt: new Date(activeFile.stat.ctime).toLocaleString(),
modifiedAt: new Date(modifiedAt).toLocaleString(),
}
: null;

return (
<>
<div className="mb-6">
Expand All @@ -56,6 +97,18 @@ const DiscourseContext = ({ activeFile }: DiscourseContextProps) => {
/>
)}
{nodeType.name || "Unnamed Node Type"}
{isImported && (
<button
onClick={() => {
void handleRefresh();
}}
disabled={isRefreshing}
className="ml-auto rounded border px-2 py-1 text-xs"
title="Refresh from source"
>
{isRefreshing ? "Refreshing..." : "🔄 Refresh"}
</button>
)}
</div>

{nodeType.format && (
Expand All @@ -64,6 +117,13 @@ const DiscourseContext = ({ activeFile }: DiscourseContextProps) => {
{extractContentFromTitle(nodeType.format, activeFile.basename)}
</div>
)}

{isImported && sourceDates && (
<div className="text-modifier-text mt-2 text-xs">
<div>Created in source: {sourceDates.createdAt}</div>
<div>Last modified in source: {sourceDates.modifiedAt}</div>
</div>
)}
</div>

<div>
Expand Down
Loading
Loading