114 lines
2.9 KiB
Svelte
114 lines
2.9 KiB
Svelte
|
|
<script>
|
||
|
|
import Mustache from "mustache";
|
||
|
|
import { imgurl } from "../files/imageserver";
|
||
|
|
import { uniqBy } from "lodash";
|
||
|
|
import { onMount, getContext } from "svelte";
|
||
|
|
import { Network } from "vis-network/esnext";
|
||
|
|
import "vis-network/styles/vis-network.css";
|
||
|
|
|
||
|
|
const channelurl = getContext("channelurl");
|
||
|
|
export let schemas;
|
||
|
|
export let recordGraph;
|
||
|
|
let network;
|
||
|
|
let allEdges = recordGraph._graph.edges.map((e) => {
|
||
|
|
e.fieldLabel = schemas
|
||
|
|
.find((s) => s.uid === e.fromSchema)
|
||
|
|
.fields.find((f) => f.name === e.field).label;
|
||
|
|
return e;
|
||
|
|
});
|
||
|
|
|
||
|
|
let nodes = recordGraph._graph.nodes.map((r) => {
|
||
|
|
let nodeOptions = {
|
||
|
|
id: r.data.id,
|
||
|
|
label: renderTitle(
|
||
|
|
schemas.find((s) => s.uid === r._sys.schema),
|
||
|
|
r
|
||
|
|
),
|
||
|
|
borderWidth: 0,
|
||
|
|
color: {
|
||
|
|
background:
|
||
|
|
r.data.id === recordGraph.data.id ? "#0b5d1e" : "#eeeeee",
|
||
|
|
},
|
||
|
|
font: {
|
||
|
|
multi: true,
|
||
|
|
color: r.data.id === recordGraph.data.id ? "#fff" : "#333",
|
||
|
|
},
|
||
|
|
};
|
||
|
|
|
||
|
|
nodeOptions.shape = "box";
|
||
|
|
if (r._file?.path) {
|
||
|
|
nodeOptions.shape = "image";
|
||
|
|
nodeOptions.image = imgurl(r, 64, 64, "crop");
|
||
|
|
}
|
||
|
|
|
||
|
|
return nodeOptions;
|
||
|
|
});
|
||
|
|
|
||
|
|
nodes = uniqBy(nodes, (n) => n.id);
|
||
|
|
|
||
|
|
// create an array with edges
|
||
|
|
let networkEdges = allEdges.map((e) => {
|
||
|
|
return {
|
||
|
|
from: e.from,
|
||
|
|
to: e.to,
|
||
|
|
label: e.fieldLabel,
|
||
|
|
arrows: {
|
||
|
|
to: {
|
||
|
|
enabled: true,
|
||
|
|
type: "arrow",
|
||
|
|
scaleFactor: 0.5,
|
||
|
|
},
|
||
|
|
},
|
||
|
|
font: { align: "middle" },
|
||
|
|
};
|
||
|
|
});
|
||
|
|
|
||
|
|
let data = {
|
||
|
|
nodes: nodes,
|
||
|
|
edges: networkEdges,
|
||
|
|
};
|
||
|
|
let options = {
|
||
|
|
physics: false,
|
||
|
|
layout: {
|
||
|
|
hierarchical: {
|
||
|
|
enabled: true,
|
||
|
|
nodeSpacing: 150,
|
||
|
|
treeSpacing: 200,
|
||
|
|
direction: "UD",
|
||
|
|
sortMethod: "directed",
|
||
|
|
},
|
||
|
|
},
|
||
|
|
};
|
||
|
|
|
||
|
|
onMount(() => {
|
||
|
|
let networkInstance = new Network(network, data, options);
|
||
|
|
|
||
|
|
networkInstance.on("doubleClick", function (params) {
|
||
|
|
if (params.nodes[0]) {
|
||
|
|
window.location = channelurl + "/records/" + params.nodes[0];
|
||
|
|
}
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
function renderTitle(schema, record) {
|
||
|
|
const template = `${schema.titleTemplate}\n <i>${schema.label}</i>`;
|
||
|
|
Mustache.parse(template);
|
||
|
|
|
||
|
|
let recordData = { ...record, ...record.data };
|
||
|
|
|
||
|
|
return Mustache.render(template, recordData);
|
||
|
|
}
|
||
|
|
</script>
|
||
|
|
|
||
|
|
<div class="lx-card">
|
||
|
|
<div class="network-container" bind:this={network} />
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<style>
|
||
|
|
.network-container {
|
||
|
|
width: 100%;
|
||
|
|
height: 80vh;
|
||
|
|
max-height: 800px;
|
||
|
|
}
|
||
|
|
</style>
|