Skip to content

Commit 1a4d551

Browse files
committed
Release v1.1.0
1 parent a7e17cb commit 1a4d551

23 files changed

Lines changed: 2663 additions & 1199 deletions

README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ To use the plugin prior to its public release on Obsidian's community plugin bro
2222
4. Install BRAT and enable it
2323

2424
## Install DataCore via BRAT
25-
Discourse Graphs relies on [DataCore](https://github.com/blacksmithgu/datacore) to do Obsidian-specific queries. To install Datacore
2625

2726
1. Add the DataCore plugin from the BRAT settings menu or run command "Add a beta plugin for testing"
2827
2. Enter the repository URL: `https://github.com/blacksmithgu/datacore` and choose "Latest version"

main.js

Lines changed: 1337 additions & 736 deletions
Large diffs are not rendered by default.

manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"id": "discourse-graphs",
33
"name": "Discourse Graph",
4-
"version": "1.0.0",
4+
"version": "1.1.0",
55
"minAppVersion": "1.7.0",
66
"description": "Add semantic structure to your notes with the Discourse Graph protocol.",
77
"author": "Discourse Graphs",

src/components/AdminPanelSettings.tsx

Lines changed: 19 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -8,31 +8,27 @@ export const AdminPanelSettings = () => {
88
const [syncModeEnabled, setSyncModeEnabled] = useState<boolean>(
99
plugin.settings.syncModeEnabled ?? false,
1010
);
11-
const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false);
1211

13-
const handleSyncModeToggle = useCallback((newValue: boolean) => {
14-
setSyncModeEnabled(newValue);
15-
setHasUnsavedChanges(true);
16-
}, []);
12+
const handleSyncModeToggle = useCallback(
13+
async (newValue: boolean) => {
14+
setSyncModeEnabled(newValue);
15+
plugin.settings.syncModeEnabled = newValue;
16+
await plugin.saveSettings();
1717

18-
const handleSave = async () => {
19-
plugin.settings.syncModeEnabled = syncModeEnabled;
20-
await plugin.saveSettings();
21-
new Notice("Admin panel settings saved");
22-
setHasUnsavedChanges(false);
23-
24-
if (syncModeEnabled) {
25-
try {
26-
await initializeSupabaseSync(plugin);
27-
new Notice("Sync mode initialized successfully");
28-
} catch (error) {
29-
console.error("Failed to initialize sync mode:", error);
30-
new Notice(
31-
`Failed to initialize sync mode: ${error instanceof Error ? error.message : String(error)}`,
32-
);
18+
if (newValue) {
19+
try {
20+
await initializeSupabaseSync(plugin);
21+
new Notice("Sync mode initialized successfully");
22+
} catch (error) {
23+
console.error("Failed to initialize sync mode:", error);
24+
new Notice(
25+
`Failed to initialize sync mode: ${error instanceof Error ? error.message : String(error)}`,
26+
);
27+
}
3328
}
34-
}
35-
};
29+
},
30+
[plugin],
31+
);
3632

3733
return (
3834
<div className="general-settings">
@@ -46,26 +42,12 @@ export const AdminPanelSettings = () => {
4642
<div className="setting-item-control">
4743
<div
4844
className={`checkbox-container ${syncModeEnabled ? "is-enabled" : ""}`}
49-
onClick={() => handleSyncModeToggle(!syncModeEnabled)}
45+
onClick={() => void handleSyncModeToggle(!syncModeEnabled)}
5046
>
5147
<input type="checkbox" checked={syncModeEnabled} />
5248
</div>
5349
</div>
5450
</div>
55-
56-
<div className="setting-item">
57-
<button
58-
onClick={() => void handleSave()}
59-
className={hasUnsavedChanges ? "mod-cta" : ""}
60-
disabled={!hasUnsavedChanges}
61-
>
62-
Save Changes
63-
</button>
64-
</div>
65-
66-
{hasUnsavedChanges && (
67-
<div className="text-muted mt-2">You have unsaved changes</div>
68-
)}
6951
</div>
7052
);
7153
};

src/components/DiscourseContextView.tsx

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
WorkspaceLeaf,
55
Notice,
66
FrontMatterCache,
7+
setIcon,
78
} from "obsidian";
89
import { createRoot, Root } from "react-dom/client";
910
import DiscourseGraphPlugin from "~/index";
@@ -14,6 +15,7 @@ import { PluginProvider, usePlugin } from "~/components/PluginContext";
1415
import { getNodeTypeById } from "~/utils/typeUtils";
1516
import { refreshImportedFile } from "~/utils/importNodes";
1617
import { publishNode } from "~/utils/publishNode";
18+
import { createBaseForNodeType } from "~/utils/baseForNodeType";
1719
import { useState, useEffect } from "react";
1820

1921
type DiscourseContextProps = {
@@ -154,6 +156,18 @@ const DiscourseContext = ({ activeFile }: DiscourseContextProps) => {
154156
/>
155157
)}
156158
{nodeType.name || "Unnamed Node Type"}
159+
<button
160+
onClick={() => {
161+
void createBaseForNodeType(plugin, nodeType);
162+
}}
163+
className="clickable-icon ml-1"
164+
title={`Create Base view for ${nodeType.name}`}
165+
aria-label={`Create Base view for ${nodeType.name}`}
166+
>
167+
<div
168+
ref={(el) => (el && setIcon(el, "layout-list")) || undefined}
169+
/>
170+
</button>
157171
{isImported && (
158172
<button
159173
onClick={() => {

src/components/GeneralSettings.tsx

Lines changed: 33 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { useState, useCallback, useRef, useEffect } from "react";
22
import { usePlugin } from "./PluginContext";
3-
import { Notice, setIcon } from "obsidian";
3+
import { setIcon } from "obsidian";
44
import SuggestInput from "./SuggestInput";
55
import { SLACK_LOGO, WHITE_LOGO_SVG } from "~/icons";
66

@@ -157,57 +157,51 @@ const GeneralSettings = () => {
157157
const [nodeTagHotkey, setNodeTagHotkey] = useState<string>(
158158
plugin.settings.nodeTagHotkey,
159159
);
160-
const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false);
161160

162161
const handleToggleChange = (newValue: boolean) => {
163162
setShowIdsInFrontmatter(newValue);
164-
setHasUnsavedChanges(true);
163+
plugin.settings.showIdsInFrontmatter = newValue;
164+
void plugin.saveSettings();
165165
};
166166

167-
const handleFolderPathChange = useCallback((newValue: string) => {
168-
setNodesFolderPath(newValue);
169-
setHasUnsavedChanges(true);
170-
}, []);
167+
const handleFolderPathChange = useCallback(
168+
(newValue: string) => {
169+
setNodesFolderPath(newValue);
170+
plugin.settings.nodesFolderPath = newValue.trim();
171+
void plugin.saveSettings();
172+
},
173+
[plugin],
174+
);
171175

172-
const handleCanvasFolderPathChange = useCallback((newValue: string) => {
173-
setCanvasFolderPath(newValue);
174-
setHasUnsavedChanges(true);
175-
}, []);
176+
const handleCanvasFolderPathChange = useCallback(
177+
(newValue: string) => {
178+
setCanvasFolderPath(newValue);
179+
plugin.settings.canvasFolderPath = newValue.trim();
180+
void plugin.saveSettings();
181+
},
182+
[plugin],
183+
);
176184

177185
const handleCanvasAttachmentsFolderPathChange = useCallback(
178186
(newValue: string) => {
179187
setCanvasAttachmentsFolderPath(newValue);
180-
setHasUnsavedChanges(true);
188+
plugin.settings.canvasAttachmentsFolderPath = newValue.trim();
189+
void plugin.saveSettings();
181190
},
182-
[],
191+
[plugin],
183192
);
184193

185-
const handleNodeTagHotkeyChange = useCallback((newValue: string) => {
186-
// Only allow single character
187-
if (newValue.length <= 1) {
188-
setNodeTagHotkey(newValue);
189-
setHasUnsavedChanges(true);
190-
}
191-
}, []);
192-
193-
const handleSave = async () => {
194-
const trimmedNodesFolderPath = nodesFolderPath.trim();
195-
const trimmedCanvasFolderPath = canvasFolderPath.trim();
196-
const trimmedCanvasAttachmentsFolderPath =
197-
canvasAttachmentsFolderPath.trim();
198-
plugin.settings.showIdsInFrontmatter = showIdsInFrontmatter;
199-
plugin.settings.nodesFolderPath = trimmedNodesFolderPath;
200-
plugin.settings.canvasFolderPath = trimmedCanvasFolderPath;
201-
plugin.settings.canvasAttachmentsFolderPath =
202-
trimmedCanvasAttachmentsFolderPath;
203-
plugin.settings.nodeTagHotkey = nodeTagHotkey || "";
204-
setNodesFolderPath(trimmedNodesFolderPath);
205-
setCanvasFolderPath(trimmedCanvasFolderPath);
206-
setCanvasAttachmentsFolderPath(trimmedCanvasAttachmentsFolderPath);
207-
await plugin.saveSettings();
208-
new Notice("General settings saved");
209-
setHasUnsavedChanges(false);
210-
};
194+
const handleNodeTagHotkeyChange = useCallback(
195+
(newValue: string) => {
196+
// Only allow single character
197+
if (newValue.length <= 1) {
198+
setNodeTagHotkey(newValue);
199+
plugin.settings.nodeTagHotkey = newValue;
200+
void plugin.saveSettings();
201+
}
202+
},
203+
[plugin],
204+
);
211205

212206
return (
213207
<div className="general-settings">
@@ -313,19 +307,6 @@ const GeneralSettings = () => {
313307
</div>
314308
</div>
315309

316-
<div className="setting-item">
317-
<button
318-
onClick={() => void handleSave()}
319-
className={hasUnsavedChanges ? "mod-cta" : ""}
320-
disabled={!hasUnsavedChanges}
321-
>
322-
Save Changes
323-
</button>
324-
</div>
325-
326-
{hasUnsavedChanges && (
327-
<div className="text-muted mt-2">You have unsaved changes</div>
328-
)}
329310
<InfoSection />
330311
</div>
331312
);

0 commit comments

Comments
 (0)