Skip to content

Commit

Permalink
Merge pull request #6 from JonasSchatz/force-graph-v2
Browse files Browse the repository at this point in the history
Force graph v2
  • Loading branch information
JonasSchatz authored Dec 18, 2020
2 parents 3c6ac53 + 227ad13 commit 03b3b2b
Show file tree
Hide file tree
Showing 11 changed files with 226 additions and 490 deletions.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,8 @@
"title": "Codekasten: Search Note"
},
{
"command": "codekasten.update-graph",
"title": "Codekasten: Update Graph"
"command": "codekasten.refresh-graph",
"title": "Codekasten: Refresh Graph"
}
]
},
Expand Down
1 change: 0 additions & 1 deletion src/core/Note.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,4 @@ export class WebviewNote {
label: string;
path: string;
isStub: boolean;
isCurrentlyActive: boolean;
}
145 changes: 72 additions & 73 deletions src/features/graphviz.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import * as fs from 'fs';
import * as md5 from "md5";
import * as path from 'path';
import { TextDecoder } from "util";
import * as vscode from "vscode";

import { NoteGraph } from "../core";
import { Note, WebviewNote } from "../core/Note";
import { Logger } from '../services';
import { openNoteInWorkspace } from "../vscode/NoteActions";

import { Feature } from "./feature";
Expand All @@ -17,40 +17,87 @@ const feature: Feature = {

context.subscriptions.push(
vscode.commands.registerCommand("codekasten.show-graph", async () => {
panel = await initializeWebviewPanel(context, graph);
panel = initializeWebviewPanel(context, graph);

const noteAddedListener = graph.onDidAddNote(() => sendGraph(graph, panel, 'Webview update, onDidAddNote'));
const noteUpdatedListener = graph.onDidUpdateNote(() => sendGraph(graph, panel, 'Webview update, onDidUpdateNote'));
const noteDeleteListener = graph.onDidDeleteNote(() => sendGraph(graph, panel, 'Webview update, onDidDeleteNote'));
vscode.window.onDidChangeActiveTextEditor((editor) => sendGraph(graph, panel, `Webview update, onDidChangeActiveTextEditor ${editor.document?.uri.fsPath}`));
const noteAddedListener = graph.onDidAddNote(() => sendGraph(graph, panel, "update"));
const noteUpdatedListener = graph.onDidUpdateNote(() => sendGraph(graph, panel, "update"));
const noteDeleteListener = graph.onDidDeleteNote(() => sendGraph(graph, panel, "update"));

panel.onDidDispose(() => {
noteAddedListener.dispose();
noteUpdatedListener.dispose();
noteDeleteListener.dispose();
});
})

vscode.window.onDidChangeActiveTextEditor((editor) => {
if (editor.document.uri.scheme === "file") {
Logger.info(`About to update GraphViz: Selected Note ${editor.document.uri.fsPath}`);
panel.webview.postMessage({
type: "didSelectNote",
payload: md5(editor.document.uri.fsPath)
});
}
});


})
);

context.subscriptions.push(
vscode.commands.registerCommand("codekasten.update-graph", () => {
sendGraph(graph, panel, 'Webview update, manual trigger');
vscode.commands.registerCommand("codekasten.refresh-graph", () => {
sendGraph(graph, panel, "refresh");
})
);
}
};


function sendGraph(graph: NoteGraph, panel: vscode.WebviewPanel, debugMessage: string) {
console.log(debugMessage);
function sendGraph(graph: NoteGraph, panel: vscode.WebviewPanel, messageType: string) {
const webviewData = generateWebviewData(graph);
panel.webview.postMessage({
type: "refresh",
type: messageType,
payload: webviewData
});
};

async function initializeWebviewPanel(context: vscode.ExtensionContext, graph: NoteGraph) {
/**
* Turn the NoteGraph into a list of nodes and links for force-graph to consume
*/
function generateWebviewData(graph: NoteGraph) {
const webviewNodes: WebviewNote[] = [];
const webviewLinks: { source: string; target: string; targetIsStub: boolean }[] = [];

graph.graph.nodes().forEach(id => {
const sourceNote: Note = graph.getNote(id);

webviewNodes.push({
'id': md5(sourceNote.path),
'label': sourceNote.title ? sourceNote.title : path.basename(sourceNote.path, path.extname(sourceNote.path)),
'path': sourceNote.path,
'isStub': sourceNote.isStub
});

for (const link of sourceNote.links) {
const targetNote: Note = graph.getNote(md5(link));
webviewLinks.push( {
'source': id,
'target': md5(link),
'targetIsStub': targetNote.isStub
});
}
});

const webviewData = {
'nodes': webviewNodes,
'links': webviewLinks
};

// Debug: Write the data to a file
//fs.writeFileSync(path.resolve(__dirname, '../..', 'static', 'test_data_autogenerated'), JSON.stringify(webviewData));
return webviewData;
}


function initializeWebviewPanel(context: vscode.ExtensionContext, graph: NoteGraph) {
const panel = vscode.window.createWebviewPanel(
"note-graph",
"Notes",
Expand All @@ -61,7 +108,7 @@ async function initializeWebviewPanel(context: vscode.ExtensionContext, graph: N
}
);

panel.webview.html = await generateWebviewHtml(context, panel);
panel.webview.html = getWebviewContent(context, panel);

panel.webview.onDidReceiveMessage(
message => {
Expand All @@ -72,8 +119,8 @@ async function initializeWebviewPanel(context: vscode.ExtensionContext, graph: N
openNoteInWorkspace(message.payload.path, vscode.ViewColumn.One);
}

if (message.type === 'ready') {
sendGraph(graph, panel, 'Webview update, initial');
if (message.type === 'webviewDidLoad') {
sendGraph(graph, panel, "initial");
}
},
undefined,
Expand All @@ -83,74 +130,26 @@ async function initializeWebviewPanel(context: vscode.ExtensionContext, graph: N
return panel;
}


/**
* Replaces the placeholders in the HTML template file with the respective files at the extensionPath
* Replace the placeholders in the HTML with the vscode-webview-resource URIs
*/
async function generateWebviewHtml(context: vscode.ExtensionContext, panel: vscode.WebviewPanel) {
const webviewContentPath = vscode.Uri.file(path.join(context.extensionPath, 'static', 'dataviz.html'));
const file = await vscode.workspace.fs.readFile(webviewContentPath);
const text = new TextDecoder('utf-8').decode(file);
function getWebviewContent(context: vscode.ExtensionContext, panel: vscode.WebviewPanel) {

const webviewUri = (fileName: string) =>
panel.webview.asWebviewUri(
vscode.Uri.file(path.join(context.extensionPath, "static", fileName))
).toString();

const textWithVariables = text.replace(
"${graphPath}",
"{{./graph.js}}"
).replace(
"${graphStylesPath}",
"{{./graph.css}}"
);

const webviewContentUri: vscode.Uri = vscode.Uri.file(path.join(context.extensionPath, 'static', 'dataviz.html'));
const text: string = fs.readFileSync(webviewContentUri.fsPath, 'utf-8');

const textWithVariables = text.replace(new RegExp(/(?<=data-replace src=")([^"]*)"/, 'g'), '{{$1}}"');

const filled = textWithVariables.replace(/\{\{.*\}\}/g, (match) => {
const fileName = match.slice(2, -2).trim();
return webviewUri(fileName);
});
return filled;
}

/**
* Turn the NoteGraph into a list of nodes and edges for D3 to consume
*/
function generateWebviewData(graph: NoteGraph) {
const webviewNodes: WebviewNote[] = [];
const webviewEdges: { source: string; target: string; targetIsStub: boolean }[] = [];
const currentlyOpenNotePath: string = vscode.window.activeTextEditor?.document?.uri.fsPath;
console.log(`This should be identical: ${currentlyOpenNotePath}`)

graph.graph.nodes().forEach(id => {
const sourceNote: Note = graph.getNote(id);

webviewNodes.push({
'id': md5(sourceNote.path),
'label': sourceNote.title ? sourceNote.title : path.basename(sourceNote.path, path.extname(sourceNote.path)),
'path': sourceNote.path,
'isStub': sourceNote.isStub,
'isCurrentlyActive': (sourceNote.path === currentlyOpenNotePath) ? true : false
});

for (const link of sourceNote.links) {
const targetNote: Note = graph.getNote(md5(link));
webviewEdges.push( {
'source': id,
'target': md5(link),
'targetIsStub': targetNote.isStub
});
}
});

const webviewData = {
'nodes': webviewNodes,
'edges': webviewEdges
};

// Debug: Write the data to a file
//fs.writeFileSync(path.resolve(__dirname, '../..', 'static', 'test_data_autogenerated'), JSON.stringify(webviewData));

return webviewData;
}
};

export default feature;
2 changes: 0 additions & 2 deletions static/d3.v4.min.js

This file was deleted.

16 changes: 5 additions & 11 deletions static/dataviz.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,12 @@
<html>
<head>
<meta charset="utf-8" />
<link rel="stylesheet" data-replace href="${graphStylesPath}">
<script src="{{./d3.v4.min.js}}"></script>
<script data-replace src="./d3.v6.min.js"></script>
<script data-replace src="./force-graph.1.34.1.min.js"></script>
</head>
<body>
<div class="buttons">
<span><span id="files">0</span> files</span>
<span><span id="connections">0</span> links</span>
<span><span id="zoom">1.00</span>x</span>
</div>
<div class="controls">
<span id="moveToCurrentlyActive">Move to currently active</span>
</div>
<script data-replace src="${graphPath}"></script>
<div id="graph"></div>
<!-- <script data-replace src="./test-data.js"></script> -->
<script data-replace src="./graph.js"></script>
</body>
</html>
20 changes: 0 additions & 20 deletions static/dataviz_local.html

This file was deleted.

5 changes: 5 additions & 0 deletions static/force-graph.1.34.1.min.js

Large diffs are not rendered by default.

77 changes: 0 additions & 77 deletions static/graph.css

This file was deleted.

Loading

0 comments on commit 03b3b2b

Please sign in to comment.