@gmickel/gno 0.33.4 → 0.34.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -1
- package/package.json +1 -1
- package/src/serve/browse-tree.ts +201 -0
- package/src/serve/public/app.tsx +38 -14
- package/src/serve/public/components/BacklinksPanel.tsx +10 -10
- package/src/serve/public/components/BrowseDetailPane.tsx +194 -0
- package/src/serve/public/components/BrowseOverview.tsx +81 -0
- package/src/serve/public/components/BrowseTreeSidebar.tsx +281 -0
- package/src/serve/public/components/BrowseWorkspaceCard.tsx +96 -0
- package/src/serve/public/components/FrontmatterDisplay.tsx +164 -65
- package/src/serve/public/components/OutgoingLinksPanel.tsx +8 -12
- package/src/serve/public/components/RelatedNotesSidebar.tsx +42 -76
- package/src/serve/public/components/editor/MarkdownPreview.tsx +61 -2
- package/src/serve/public/components/ui/button.tsx +1 -1
- package/src/serve/public/components/ui/dialog.tsx +1 -1
- package/src/serve/public/hooks/useWorkspace.tsx +38 -0
- package/src/serve/public/lib/browse.ts +110 -0
- package/src/serve/public/lib/workspace-tabs.ts +59 -1
- package/src/serve/public/pages/Browse.tsx +334 -344
- package/src/serve/public/pages/DocView.tsx +484 -296
- package/src/serve/public/pages/DocumentEditor.tsx +1 -11
- package/src/serve/public/pages/GraphView.tsx +5 -4
- package/src/serve/routes/api.ts +47 -0
- package/src/serve/server.ts +5 -0
- package/src/store/sqlite/adapter.ts +240 -241
|
@@ -33,10 +33,7 @@ import {
|
|
|
33
33
|
type CodeMirrorEditorRef,
|
|
34
34
|
MarkdownPreview,
|
|
35
35
|
} from "../components/editor";
|
|
36
|
-
import {
|
|
37
|
-
FrontmatterDisplay,
|
|
38
|
-
parseFrontmatter,
|
|
39
|
-
} from "../components/FrontmatterDisplay";
|
|
36
|
+
import { parseFrontmatter } from "../components/FrontmatterDisplay";
|
|
40
37
|
import { Badge } from "../components/ui/badge";
|
|
41
38
|
import { Button } from "../components/ui/button";
|
|
42
39
|
import {
|
|
@@ -227,7 +224,6 @@ export default function DocumentEditor({ navigate }: PageProps) {
|
|
|
227
224
|
const hasUnsavedChanges = content !== originalContent;
|
|
228
225
|
const hasLocalSnapshot = historyEntries.length > 0;
|
|
229
226
|
const parsedContent = useMemo(() => parseFrontmatter(content), [content]);
|
|
230
|
-
const hasFrontmatter = Object.keys(parsedContent.data).length > 0;
|
|
231
227
|
|
|
232
228
|
const refreshHistoryEntries = useCallback((docId: string) => {
|
|
233
229
|
const next = loadLocalHistory(docId);
|
|
@@ -1090,12 +1086,6 @@ export default function DocumentEditor({ navigate }: PageProps) {
|
|
|
1090
1086
|
ref={previewRef}
|
|
1091
1087
|
>
|
|
1092
1088
|
<div className="mx-auto max-w-3xl">
|
|
1093
|
-
{hasFrontmatter && (
|
|
1094
|
-
<FrontmatterDisplay
|
|
1095
|
-
className="mb-4 rounded-lg border border-border/40 bg-muted/10 p-4"
|
|
1096
|
-
content={content}
|
|
1097
|
-
/>
|
|
1098
|
-
)}
|
|
1099
1089
|
<MarkdownPreview content={parsedContent.body} />
|
|
1100
1090
|
</div>
|
|
1101
1091
|
</div>
|
|
@@ -298,8 +298,8 @@ export default function GraphView({ navigate }: PageProps) {
|
|
|
298
298
|
if (includeSimilar) {
|
|
299
299
|
params.set("includeSimilar", "true");
|
|
300
300
|
}
|
|
301
|
-
params.set("limit", "
|
|
302
|
-
params.set("edgeLimit", "
|
|
301
|
+
params.set("limit", "600");
|
|
302
|
+
params.set("edgeLimit", "2200");
|
|
303
303
|
|
|
304
304
|
const url = `/api/graph?${params.toString()}`;
|
|
305
305
|
const { data, error: fetchError } = await apiFetch<GraphResponse>(url);
|
|
@@ -632,14 +632,14 @@ export default function GraphView({ navigate }: PageProps) {
|
|
|
632
632
|
<Suspense fallback={<GraphLoading />}>
|
|
633
633
|
<ForceGraph2D
|
|
634
634
|
backgroundColor={COLORS.canvas}
|
|
635
|
-
cooldownTicks={
|
|
635
|
+
cooldownTicks={45}
|
|
636
636
|
graphData={forceGraphData}
|
|
637
637
|
linkColor={(link: any) => link.color}
|
|
638
638
|
linkCurvature={0.1}
|
|
639
639
|
linkDirectionalParticleColor={() => COLORS.nodeDefault}
|
|
640
640
|
linkDirectionalParticles={
|
|
641
641
|
// Disable particles on large graphs for performance
|
|
642
|
-
forceGraphData.links.length >
|
|
642
|
+
forceGraphData.links.length > 250 ? 0 : 1
|
|
643
643
|
}
|
|
644
644
|
linkDirectionalParticleWidth={1.5}
|
|
645
645
|
linkWidth={(link: any) =>
|
|
@@ -670,6 +670,7 @@ export default function GraphView({ navigate }: PageProps) {
|
|
|
670
670
|
onZoom={(transform: { k: number }) => {
|
|
671
671
|
pointerScaleRef.current = transform.k;
|
|
672
672
|
}}
|
|
673
|
+
warmupTicks={20}
|
|
673
674
|
ref={graphRef}
|
|
674
675
|
/>
|
|
675
676
|
</Suspense>
|
package/src/serve/routes/api.ts
CHANGED
|
@@ -50,6 +50,7 @@ import {
|
|
|
50
50
|
import { searchHybrid } from "../../pipeline/hybrid";
|
|
51
51
|
import { validateQueryModes } from "../../pipeline/query-modes";
|
|
52
52
|
import { searchBm25 } from "../../pipeline/search";
|
|
53
|
+
import { buildBrowseTree, normalizeBrowsePath } from "../browse-tree";
|
|
53
54
|
import { applyConfigChange, applyConfigChangeTyped } from "../config-sync";
|
|
54
55
|
import { getConnectorStatuses, installConnector } from "../connectors";
|
|
55
56
|
import {
|
|
@@ -780,6 +781,12 @@ export async function handleDocs(
|
|
|
780
781
|
url: URL
|
|
781
782
|
): Promise<Response> {
|
|
782
783
|
const collection = url.searchParams.get("collection") || undefined;
|
|
784
|
+
const pathPrefix = normalizeBrowsePath(url.searchParams.get("pathPrefix"));
|
|
785
|
+
const directChildrenOnlyParam = (
|
|
786
|
+
url.searchParams.get("directChildrenOnly") ?? ""
|
|
787
|
+
)
|
|
788
|
+
.trim()
|
|
789
|
+
.toLowerCase();
|
|
783
790
|
const sortFieldRaw = (url.searchParams.get("sortField") ?? "modified")
|
|
784
791
|
.trim()
|
|
785
792
|
.toLowerCase();
|
|
@@ -818,6 +825,15 @@ export async function handleDocs(
|
|
|
818
825
|
return errorResponse("VALIDATION", "sortOrder must be 'asc' or 'desc'");
|
|
819
826
|
}
|
|
820
827
|
const sortOrder: "asc" | "desc" = sortOrderRaw === "asc" ? "asc" : "desc";
|
|
828
|
+
const directChildrenOnly =
|
|
829
|
+
directChildrenOnlyParam === "1" || directChildrenOnlyParam === "true";
|
|
830
|
+
|
|
831
|
+
if (pathPrefix && !collection) {
|
|
832
|
+
return errorResponse(
|
|
833
|
+
"VALIDATION",
|
|
834
|
+
"pathPrefix requires a collection filter"
|
|
835
|
+
);
|
|
836
|
+
}
|
|
821
837
|
|
|
822
838
|
// Parse tag filters
|
|
823
839
|
let tagsAll: string[] | undefined;
|
|
@@ -867,6 +883,8 @@ export async function handleDocs(
|
|
|
867
883
|
collection,
|
|
868
884
|
limit,
|
|
869
885
|
offset,
|
|
886
|
+
pathPrefix: pathPrefix || undefined,
|
|
887
|
+
directChildrenOnly,
|
|
870
888
|
tagsAll,
|
|
871
889
|
tagsAny,
|
|
872
890
|
sortField: sortFieldRaw,
|
|
@@ -893,12 +911,41 @@ export async function handleDocs(
|
|
|
893
911
|
total,
|
|
894
912
|
limit,
|
|
895
913
|
offset,
|
|
914
|
+
pathPrefix,
|
|
915
|
+
directChildrenOnly,
|
|
896
916
|
availableDateFields,
|
|
897
917
|
sortField: sortFieldRaw,
|
|
898
918
|
sortOrder,
|
|
899
919
|
});
|
|
900
920
|
}
|
|
901
921
|
|
|
922
|
+
export async function handleBrowseTree(
|
|
923
|
+
store: SqliteAdapter
|
|
924
|
+
): Promise<Response> {
|
|
925
|
+
const [collectionsResult, documentsResult] = await Promise.all([
|
|
926
|
+
store.getCollections(),
|
|
927
|
+
store.listActiveDocumentsForBrowse(),
|
|
928
|
+
]);
|
|
929
|
+
|
|
930
|
+
if (!collectionsResult.ok) {
|
|
931
|
+
return errorResponse("RUNTIME", collectionsResult.error.message, 500);
|
|
932
|
+
}
|
|
933
|
+
if (!documentsResult.ok) {
|
|
934
|
+
return errorResponse("RUNTIME", documentsResult.error.message, 500);
|
|
935
|
+
}
|
|
936
|
+
|
|
937
|
+
const collections = buildBrowseTree(
|
|
938
|
+
collectionsResult.value,
|
|
939
|
+
documentsResult.value
|
|
940
|
+
);
|
|
941
|
+
|
|
942
|
+
return jsonResponse({
|
|
943
|
+
collections,
|
|
944
|
+
totalCollections: collections.length,
|
|
945
|
+
totalDocuments: documentsResult.value.length,
|
|
946
|
+
});
|
|
947
|
+
}
|
|
948
|
+
|
|
902
949
|
/**
|
|
903
950
|
* GET /api/docs/autocomplete
|
|
904
951
|
* Query params: query, collection, limit
|
package/src/serve/server.ts
CHANGED
|
@@ -15,6 +15,7 @@ import homepage from "./public/index.html";
|
|
|
15
15
|
import {
|
|
16
16
|
handleActiveJob,
|
|
17
17
|
handleAsk,
|
|
18
|
+
handleBrowseTree,
|
|
18
19
|
handleCapabilities,
|
|
19
20
|
handleCollections,
|
|
20
21
|
handleConnectors,
|
|
@@ -256,6 +257,10 @@ export async function startServer(
|
|
|
256
257
|
);
|
|
257
258
|
},
|
|
258
259
|
},
|
|
260
|
+
"/api/browse/tree": {
|
|
261
|
+
GET: async () =>
|
|
262
|
+
withSecurityHeaders(await handleBrowseTree(store), isDev),
|
|
263
|
+
},
|
|
259
264
|
"/api/docs/:id/deactivate": {
|
|
260
265
|
POST: async (req: Request) => {
|
|
261
266
|
if (!isRequestAllowed(req, port)) {
|