Skip to content

Commit

Permalink
feat: Juggl view into source node after layout is finished
Browse files Browse the repository at this point in the history
  • Loading branch information
HEmile committed Jan 16, 2022
1 parent cd73430 commit 5059693
Show file tree
Hide file tree
Showing 4 changed files with 181 additions and 144 deletions.
142 changes: 0 additions & 142 deletions src/Codeblocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,6 @@ function codeblockError(plugin: BCPlugin, parsedSource: ParsedCodeblock) {
</code></pre>`;
}

const STORE_ID = "core";

function indentToDepth(indent: string) {
return indent.length / 2 + 1;
Expand All @@ -256,148 +255,7 @@ function meetsConditions(
);
}

class BCStoreEvents extends Events implements DataStoreEvents {}

class BCStore extends Component implements ICoreDataStore {
graph: MultiGraph;
cache: MetadataCache;
plugin: IJugglPlugin;
constructor(
graph: MultiGraph,
metadata: MetadataCache,
plugin: IJugglPlugin
) {
super();
this.graph = graph;
this.cache = metadata;
this.plugin = plugin;
}

asString(node: NodeSingular): string {
const id = VizId.fromNode(node);
return id.id.slice(0, -3);
}

getFile(nodeId: VizId): TFile {
return this.cache.getFirstLinkpathDest(nodeId.id, "");
}

async connectNodes(
allNodes: cytoscape.NodeCollection,
newNodes: cytoscape.NodeCollection,
graph: IJuggl
): Promise<cytoscape.EdgeDefinition[]> {
const edges: EdgeDefinition[] = [];
const nodesListS = new Set(
allNodes.map((node) => this.asString(node)).filter((s) => s)
);
newNodes.forEach((node) => {
this.graph.forEachOutEdge(
this.asString(node),
(key, attr, source, target) => {
if (nodesListS.has(target)) {
edges.push({
data: {
id: `BC:${source}->${target}`,
source: VizId.toId(source, STORE_ID) + ".md",
target: VizId.toId(target, STORE_ID) + ".md",
type: attr.field,
dir: attr.dir,
},
classes: `type-${attr.field} dir-${attr.dir} breadcrumbs$`,
});
}
}
);
});
return Promise.resolve(edges);
}

getEvents(view: IJuggl): DataStoreEvents {
return new BCStoreEvents();
}

getNeighbourhood(nodeId: VizId[]): Promise<cytoscape.NodeDefinition[]> {
// TODO
return Promise.resolve([]);
}

refreshNode(id: VizId, view: IJuggl): void | Promise<void> {
return;
}

storeId(): string {
return STORE_ID;
}

get(nodeId: VizId, view: IJuggl): Promise<cytoscape.NodeDefinition> {
const file = this.getFile(nodeId);
if (file === null) {
const dangling = nodeDangling(nodeId.id);
console.log({ dangling });
return Promise.resolve(nodeDangling(nodeId.id));
}
const cache = this.cache.getFileCache(file);
if (cache === null) {
console.log("returning empty cache", nodeId);
return Promise.resolve(nodeDangling(nodeId.id));
}
return Promise.resolve(nodeFromFile(file, this.plugin, view.settings, nodeId.toId()));
}
}

function createJuggl(
plugin: BCPlugin,
target: HTMLElement,
initialNodes: string[],
args: IJugglSettings
) {
try {
const jugglPlugin = getPlugin(plugin.app);
if (!jugglPlugin) {
// TODO: Error handling
return;
}
for (let key in JUGGL_CB_DEFAULTS) {
if (key in args && args[key] === undefined) {
args[key] = JUGGL_CB_DEFAULTS[key];
}
}

const bcStore = new BCStore(
plugin.mainG,
plugin.app.metadataCache,
jugglPlugin
);
const stores: IJugglStores = {
coreStore: bcStore,
dataStores: [bcStore],
};

console.log({ args }, { initialNodes });
const juggl = jugglPlugin.createJuggl(target, args, stores, initialNodes);
plugin.addChild(juggl);
// juggl.load();
console.log({ juggl });
} catch (error) {
console.log({ error });
}
}

export function createJugglTrail(
plugin: BCPlugin,
target: HTMLElement,
paths: string[][],
source: string,
args: IJugglSettings
) {
let nodes = Array.from(
new Set(paths.reduce((prev, curr) => prev.concat(curr), []))
);
nodes.push(source);
nodes = nodes.map((s) => s + ".md");
createJuggl(plugin, target, nodes, args);
}

export function createdJugglCB(
plugin: BCPlugin,
Expand Down
2 changes: 1 addition & 1 deletion src/Views/TrailView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import type { MultiGraph } from "graphology";
import { error, info } from "loglevel";
import { MarkdownView, Notice, TFile } from "obsidian";
import type { BCSettings } from "../interfaces";
import { createJugglTrail } from "../Codeblocks";
import NextPrev from "../Components/NextPrev.svelte";
import TrailGrid from "../Components/TrailGrid.svelte";
import TrailPath from "../Components/TrailPath.svelte";
Expand All @@ -16,6 +15,7 @@ import {
} from "../graphUtils";
import type BCPlugin from "../main";
import { getFields, getRealnImplied } from "../sharedFunctions";
import {createJugglTrail} from "../Visualisations/Juggl";

function getLimitedTrailSub(plugin: BCPlugin) {
const { settings, mainG } = plugin;
Expand Down
179 changes: 179 additions & 0 deletions src/Visualisations/Juggl.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
import {Component, Events, MetadataCache, TFile} from "obsidian";
import {
DataStoreEvents, getPlugin,
ICoreDataStore,
IJuggl,
IJugglPlugin,
IJugglSettings, IJugglStores,
nodeDangling,
nodeFromFile,
VizId
} from "juggl-api";
import type {MultiGraph} from "graphology";
import type {EdgeDefinition, NodeSingular} from "cytoscape";
import type BCPlugin from "../main";
import {JUGGL_CB_DEFAULTS} from "../constants";
const STORE_ID = "core";


class BCStoreEvents extends Events implements DataStoreEvents {}

class BCStore extends Component implements ICoreDataStore {
graph: MultiGraph;
cache: MetadataCache;
plugin: IJugglPlugin;
constructor(
graph: MultiGraph,
metadata: MetadataCache,
plugin: IJugglPlugin
) {
super();
this.graph = graph;
this.cache = metadata;
this.plugin = plugin;
}

asString(node: NodeSingular): string {
const id = VizId.fromNode(node);
return id.id.slice(0, -3);
}

getFile(nodeId: VizId): TFile {
return this.cache.getFirstLinkpathDest(nodeId.id, "");
}

async connectNodes(
allNodes: cytoscape.NodeCollection,
newNodes: cytoscape.NodeCollection,
graph: IJuggl
): Promise<cytoscape.EdgeDefinition[]> {
const edges: EdgeDefinition[] = [];
const nodesListS = new Set(
allNodes.map((node) => this.asString(node)).filter((s) => s)
);
newNodes.forEach((node) => {
this.graph.forEachOutEdge(
this.asString(node),
(key, attr, source, target) => {
if (nodesListS.has(target)) {
edges.push({
data: {
id: `BC:${source}->${target}`,
source: VizId.toId(source, STORE_ID) + ".md",
target: VizId.toId(target, STORE_ID) + ".md",
type: attr.field,
dir: attr.dir,
},
classes: `type-${attr.field} dir-${attr.dir} breadcrumbs$`,
});
}
}
);
});
return Promise.resolve(edges);
}

getEvents(view: IJuggl): DataStoreEvents {
return new BCStoreEvents();
}

getNeighbourhood(nodeId: VizId[]): Promise<cytoscape.NodeDefinition[]> {
// TODO
return Promise.resolve([]);
}

refreshNode(id: VizId, view: IJuggl): void | Promise<void> {
return;
}

storeId(): string {
return STORE_ID;
}

get(nodeId: VizId, view: IJuggl): Promise<cytoscape.NodeDefinition> {
const file = this.getFile(nodeId);
if (file === null) {
const dangling = nodeDangling(nodeId.id);
console.log({ dangling });
return Promise.resolve(nodeDangling(nodeId.id));
}
const cache = this.cache.getFileCache(file);
if (cache === null) {
console.log("returning empty cache", nodeId);
return Promise.resolve(nodeDangling(nodeId.id));
}
return Promise.resolve(nodeFromFile(file, this.plugin, view.settings, nodeId.toId()));
}
}

function createJuggl(
plugin: BCPlugin,
target: HTMLElement,
initialNodes: string[],
args: IJugglSettings
): IJuggl {
try {
const jugglPlugin = getPlugin(plugin.app);
if (!jugglPlugin) {
// TODO: Error handling
return;
}
for (let key in JUGGL_CB_DEFAULTS) {
if (key in args && args[key] === undefined) {
args[key] = JUGGL_CB_DEFAULTS[key];
}
}

const bcStore = new BCStore(
plugin.mainG,
plugin.app.metadataCache,
jugglPlugin
);
const stores: IJugglStores = {
coreStore: bcStore,
dataStores: [bcStore],
};

console.log({ args }, { initialNodes });
const juggl = jugglPlugin.createJuggl(target, args, stores, initialNodes);
plugin.addChild(juggl);
// juggl.load();
console.log({ juggl });
return juggl;
} catch (error) {
console.log({ error });
return null;
}
}

export function createJugglTrail(
plugin: BCPlugin,
target: HTMLElement,
paths: string[][],
source: string,
args: IJugglSettings
) {
let nodes = Array.from(
new Set(paths.reduce((prev, curr) => prev.concat(curr), []))
);
nodes.push(source);
nodes = nodes.map((s) => s + ".md");
const juggl = createJuggl(plugin, target, nodes, args);
if (juggl) {
juggl.on("vizReady", (viz) => {
// After layout is done, center on source node
viz.one('layoutstop', e => {
const viz = e.cy;
const node = viz.$id(VizId.toId(source + ".md", STORE_ID));
viz.animate({
center: {
eles: node,
},
duration: 250,
queue: false,
zoom: 2
});
})
}
}
}
2 changes: 1 addition & 1 deletion src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ export const JUGGL_TRAIL_DEFAULTS: IJugglSettings = Object.assign(
JUGGL_CB_DEFAULTS,
{
animateLayout: true,
autoZoom: true,
autoZoom: false,
fdgdLayout: "d3-force",
height: "400px",
readContent: false,
Expand Down

0 comments on commit 5059693

Please sign in to comment.