Commit 30e80d73 authored by Maximilian Lapie's avatar Maximilian Lapie

Merge branch 'maximilian/newGraph' into 'master'

Added lots of stuff

See merge request !12
parents 7eb8df77 a9a0b9ca
......@@ -6,19 +6,21 @@
"password": "1234"
},
"keywordSearch": {
"placeholder": "Enter keyword",
"selection": [
{
"placeholder": "Search in regests",
"layer": "regest",
"option": "Regest",
"query": "MATCH (n:Regesta) WHERE (n.ident=~ '.*(?i)%KEYWORD%.*') AND NOT id(n) in %CULLS% WITH distinct n as n ORDER BY n.app DESC RETURN id(n) as id, 'regest' as type, n.ident as title, n.app as app, n.rec as rec, n.text as tooltip"
},
{
"placeholder": "Search in entries",
"layer": "entry",
"option": "Entry (Person, Place, Thing, Event, other Entry)",
"query": "MATCH (n:IndexEntry) WHERE ((n.label=~ '.*(?i)%KEYWORD%.*') OR (n.path=~ '.*(?i)%KEYWORD%.*')) AND NOT id(n) in %CULLS% WITH distinct n as n ORDER BY n.app DESC RETURN id(n) as id, CASE WHEN \"IndexPerson\" in labels(n) THEN \"person\" WHEN \"IndexPlace\" in labels(n) THEN \"place\" WHEN \"IndexThing\" in labels(n) THEN \"thing\" WHEN \"IndexEvent\" in labels(n) THEN \"event\" ELSE \"entry\" END as type, n.label as title, n.app as app, n.rec as rec, n.path as tooltip"
},
{
"placeholder": "Search in lemmata",
"layer": "lemma",
"option": "Lemma",
"query": "MATCH (n) WHERE (n.lemma=~ '.*(?i)%KEYWORD%.*') AND NOT id(n) in %CULLS% WITH distinct n as n ORDER BY n.app DESC RETURN id(n) as id, \"lemma\" as type, n.lemma as title, n.app as app"
......@@ -47,7 +49,7 @@
"regest",
"event",
"person",
"place",
"indPlace",
"literature",
"place",
"reference",
......@@ -312,6 +314,10 @@
"geoLocalisation": "latLong"
},
"additionalFields": [
["url", "regId"]
],
"nodeTypes2": {
"date": {
"labelField": "startDate",
......@@ -426,8 +432,8 @@
"label": "date",
"type": "date",
"filter": {
"start": "1400",
"end": "1500"
"start": "1440",
"end": "1520"
},
"show": true,
"link": false,
......
......@@ -6,14 +6,15 @@
"password": "1234"
},
"keywordSearch": {
"placeholder": "Enter transliterated name",
"selection": [
{
"placeholder": "Search in sources",
"layer": "source",
"option": "Source",
"query": "MATCH (s:Source) WHERE (s.title=~ '.*(?i)%KEYWORD%.*') AND NOT id(s) in %CULLS% WITH distinct s as s ORDER BY s.title DESC RETURN id(s) as id, 'Source' as type, s.title as title, s.app as app"
},
{
"placeholder": "Enter transliterated name",
"layer": "entity",
"option": "Entity",
"query": "MATCH (n:Entity) WHERE (n.name=~ '.*(?i)%KEYWORD%.*') AND NOT id(n) in %CULLS% WITH distinct n as n ORDER BY n.app DESC RETURN id(n) as id, CASE WHEN 'Dacia' in labels(n) THEN 'Dacia' WHEN 'MoesiaInf' in labels(n) THEN 'Moesia Inferior' WHEN 'MoesiaSup' in labels(n) THEN 'Moesia Superior' WHEN 'PannoniaSup' in labels(n) THEN 'Pannonia Superior' WHEN 'Dalmatia' in labels(n) THEN 'Dalmatia' END as type, n.name as title, n.app as app, n.praenomen+' '+n.nomen+' '+n.cognomen +(CASE WHEN n.gender='Male' THEN ', Male' ELSE ', Female' END) +(CASE WHEN n.citizen THEN ' / Citizen' ELSE '' END) +(CASE WHEN n.libertus THEN ' / Libertus' ELSE '' END) +(CASE WHEN n.veteranus THEN ' / Veteranus' ELSE '' END) +(CASE WHEN n.peregrine THEN ' / Peregrine' ELSE '' END) +(CASE WHEN n.slave THEN ' / Slave' ELSE '' END) +(CASE WHEN EXISTS (n.occupation) THEN ' / Occupation: '+n.occupation ELSE '' END) as tooltip"
......@@ -62,9 +63,8 @@
"text": "Related Entities",
"icon": "fa-users",
"header": "Entities related with %PARENTS%",
"queryUnion": "UNWIND %PARENTSIDS% as egoid MATCH (e)-[r:related_with]->(ego) WHERE id(ego) = egoid WITH egoid, collect(distinct id(e)) as relids UNWIND relids as x WITH x, count(x) as c WITH collect(distinct x) as relations MATCH (n)-[r:related_with]->(ego) WHERE id(ego) IN %PARENTSIDS% AND id(n) in relations AND NOT id(n) in %CULLS% RETURN id(n) as id, CASE WHEN 'Dacia' in labels(n) THEN 'Dacia' WHEN 'MoesiaInf' in labels(n) THEN 'Moesia Inferior' WHEN 'MoesiaSup' in labels(n) THEN 'Moesia Superior' WHEN 'PannoniaSup' in labels(n) THEN 'Pannonia Superior' WHEN 'Dalmatia' in labels(n) THEN 'Dalmatia' END as type, n.name as title, collect(r.type) as relation, n.app as app, n.praenomen+' '+n.nomen+' '+n.cognomen as tooltip",
"queryIntersection": "UNWIND %PARENTSIDS% as egoid MATCH (e)-[r:related_with]->(ego) WHERE id(ego) = egoid WITH egoid, collect(distinct id(e)) as relids UNWIND relids as x WITH x, count(x) as c WHERE c=size(%PARENTSIDS%) WITH collect(distinct x) as relations MATCH (n)-[r:related_with]->(ego) WHERE id(ego) IN %PARENTSIDS% AND id(n) in relations AND NOT id(n) in %CULLS% RETURN id(n) as id, CASE WHEN 'Dacia' in labels(n) THEN 'Dacia' WHEN 'MoesiaInf' in labels(n) THEN 'Moesia Inferior' WHEN 'MoesiaSup' in labels(n) THEN 'Moesia Superior' WHEN 'PannoniaSup' in labels(n) THEN 'Pannonia Superior' WHEN 'Dalmatia' in labels(n) THEN 'Dalmatia' END as type, n.name as title, collect(r.type) as relation, n.app as app, n.praenomen+' '+n.nomen+' '+n.cognomen as tooltip"
},
"queryUnion": "UNWIND %PARENTSIDS% as egoid MATCH (e)-[r]->(ego) WHERE id(ego) = egoid WITH egoid, collect(distinct id(e)) as relids UNWIND relids as x WITH x, count(x) as c WITH collect(distinct x) as relations MATCH (n)-[r:related_with]->(ego) WHERE id(ego) IN %PARENTSIDS% AND id(n) in relations AND NOT id(n) in %CULLS% RETURN id(n) as id, CASE WHEN 'Dacia' in labels(n) THEN 'Dacia' WHEN 'MoesiaInf' in labels(n) THEN 'Moesia Inferior' WHEN 'MoesiaSup' in labels(n) THEN 'Moesia Superior' WHEN 'PannoniaSup' in labels(n) THEN 'Pannonia Superior' WHEN 'Dalmatia' in labels(n) THEN 'Dalmatia' END as type, n.name as title, collect(type(r)) as relation, n.app as app, n.praenomen+' '+n.nomen+' '+n.cognomen as tooltip",
"queryIntersection": "UNWIND %PARENTSIDS% as egoid MATCH (e)-[r]->(ego) WHERE id(ego) = egoid WITH egoid, collect(distinct id(e)) as relids UNWIND relids as x WITH x, count(x) as c WHERE c=size(%PARENTSIDS%) WITH collect(distinct x) as relations MATCH (n)-[r:related_with]->(ego) WHERE id(ego) IN %PARENTSIDS% AND id(n) in relations AND NOT id(n) in %CULLS% RETURN id(n) as id, CASE WHEN 'Dacia' in labels(n) THEN 'Dacia' WHEN 'MoesiaInf' in labels(n) THEN 'Moesia Inferior' WHEN 'MoesiaSup' in labels(n) THEN 'Moesia Superior' WHEN 'PannoniaSup' in labels(n) THEN 'Pannonia Superior' WHEN 'Dalmatia' in labels(n) THEN 'Dalmatia' END as type, n.name as title, collect(type(r)) as relation, n.app as app, n.praenomen+' '+n.nomen+' '+n.cognomen as tooltip" },
{
"name": "sources",
"text": "Sources",
......
......@@ -67,6 +67,13 @@ class QueryEngine {
nodeData["latitude"] = latitude
nodeData["longitude"] = longitude
}
this._dbConnector.settings.additionalFields.forEach(
([fieldNameNode, fieldNameDB]) => {
console.log(fieldNameNode, fieldNameDB, rawNode)
if (rawNode.properties[fieldNameDB])
nodeData[fieldNameNode] = rawNode.properties[fieldNameDB]
}
)
return nodeData
}
......@@ -126,7 +133,6 @@ class NodeFilters {
* @param endDate sould be a @Date object
*/
filterByDate = (startDate, endDate) => node => {
console.log("node", node, startDate, endDate)
const filterable = this._settings.filterable["date"]
if (node.collapsed)
return false
......@@ -148,15 +154,17 @@ class NodeFilters {
return true
}
filterAll = (keywords, startDate, endDate) => nodes => {
filterAllByNode = (keywords, startDate, endDate) => node => {
const keywordsFilter = this.filterByKeywords(keywords)
const dateFilter = this.filterByDate(startDate, endDate)
nodes.filterApply(
(node) => dateFilter(node) && keywordsFilter(node),
this.ifTrue,
this.ifFalse
)
return dateFilter(node) && keywordsFilter(node)
}
filterAll = (keywords, startDate, endDate) => nodes => nodes.filterApply(
this.filterAllByNode(keywords, startDate, endDate),
this.ifTrue,
this.ifFalse
)
}
/**
......@@ -297,7 +305,6 @@ export class Graph2d {
this.collapseChildren(ids, nodeType, relationType, recursive)
}
addComponents = f => (nodes, edges) => {
nodes.forEach(node => {
if (node){
......
import { Graph2d } from "./2d-graphosaurus/graph";
import IdSet from "../misc/customTypes/IdSet";
export class Graph2D {
......@@ -35,7 +34,6 @@ export class Graph2D {
container: document.getElementById('cy'),
wheelSensitivity: 0.1,
autounselectify: true,
style: [
{
selector: 'node',
......@@ -82,15 +80,21 @@ export class Graph2D {
layout.run();
this.filterByDate([document.getElementById('filter-date-start'), document.getElementById('filter-date-end')].map(this.toIso));
this.filterGraph();
this.applyFilterToGraph();
this.cy.on('tapstart', (e) => { this.hideContextMenu(e); this.hideGraphMenu(e); });
this.cy.on('cxttap', this.displayGraphMenu);
this.cy.on('cxttap', 'node', this.displayContextMenu);
this.cy.on('mouseover', 'node', this.highlightNode);
this.cy.on('mouseout', 'node', this.deEmphasizeNode);
this.cy.on('boxselect', 'node', this.selectNode);
}
selectNode = (e) => {
const nodeId = e.target._private.data.id;
this.cy.getElementById(nodeId).style("backgroundColor", 'red');
}
showTooltip = () => {
......@@ -152,7 +156,17 @@ export class Graph2D {
});
}
displayNewElements = (type, element) => {
postProc = filterFn => node => {
if (filterFn(node)) {
return true;
}
else {
node.hide = true;
return false;
}
}
displayNewElements = postProc => (type, element) => {
if (this.cy.getElementById(element.id).length === 0) {
if (type === "node") {
const cX = this.cy.getElementById(this.selectedNodeId)._private.position.x;
......@@ -161,7 +175,11 @@ export class Graph2D {
this.cy.add({
group: 'nodes',
data: element,
position: { x: cX + 200 * Math.cos(a), y: cY + 200 * Math.sin(a) }
position: { x: cX + 200 * Math.cos(a), y: cY + 200 * Math.sin(a) },
style:
{
display: postProc(element) ? 'element' : 'none'
}
});
} else {
this.cy.add({
......@@ -174,10 +192,13 @@ export class Graph2D {
expandNodes = (id, nodeType='all', relationType="all") => {
this.hideContextMenu();
this.graph2d.getRelated([id], nodeType, relationType)(this.displayNewElements);
this.graph2d.mutate().then(() => {
this.applyFilterToGraph();
});
const keywords = $("#filter-content").val().split(" ");
const startDate = this.toIso(document.getElementById('filter-date-start'));
const endDate = this.toIso(document.getElementById('filter-date-end'));
const filterFn = this.graph2d._filters.filterAllByNode(keywords, startDate, endDate);
this.graph2d.getRelated([id], nodeType, relationType)(this.displayNewElements(this.postProc(filterFn)));
this.graph2d.mutate();
}
collapseNodes = (id, nodeType='all', relationType="all") => {
......@@ -216,7 +237,7 @@ export class Graph2D {
}
displayContextMenu = (e) => {
this.hideGraphMenu();
$("#cytoRightClickOverlay").show();
let d = document.getElementById("contextMenu");
d.style.position = "absolute";
......@@ -232,6 +253,15 @@ export class Graph2D {
const nodeSummary = this.graph2d.getNodeSummary(this.selectedNodeId);
this.getContextSubMenu("Expand", nodeSummary, this.expandNodes, extraInfo);
this.getContextSubMenu("Collapse", nodeSummary, this.collapseNodes, extraInfo);
if (e.target._private.data.data.url) {
const url = e.target._private.data.data.url;
let newDiv = document.createElement("div");
newDiv.className = "menuItem";
newDiv.innerHTML = "<i class='fa fa-fw'></i>Inspect";
newDiv.addEventListener('click', () => window.open("http://www.regesta-imperii.de/id/" + url, "_blank"));
extraInfo.appendChild(newDiv);
}
}
clearGraph = () => {
......@@ -243,11 +273,13 @@ export class Graph2D {
hideGraphMenu = () => {
let d = document.getElementById("graph2DMenu");
d.style.display = 'none';
$("#cytoRightClickOverlay").hide();
}
displayGraphMenu = (e) => {
if (this.showClearMenu) {
this.hideContextMenu();
$("#cytoRightClickOverlay").show();
let d = document.getElementById("graph2DMenu");
d.style.position = "absolute";
......@@ -261,6 +293,8 @@ export class Graph2D {
hideContextMenu = () => {
let d = document.getElementById("contextMenu");
d.style.display = 'none';
$("#cytoRightClickOverlay").hide();
}
addNodeIds = (nodeIds) => {
......@@ -276,9 +310,10 @@ export class Graph2D {
this.graph2d.forEachCurrentNode(node => this.cy.getElementById(node.id).style("display", node.hide ? "none": "element"));
}
filterByDate = (dateValues) => {
const [startDate, endDate] = dateValues;
this.graph2d.filter([], startDate, endDate);
this.applyFilterToGraph();
filterGraph = () => {
const keywords = $("#filter-content").val().split(" ");
const startDate = this.toIso(document.getElementById('filter-date-start'));
const endDate = this.toIso(document.getElementById('filter-date-end'));
this.graph2d.filter(keywords, startDate, endDate);
}
}
\ No newline at end of file
......@@ -370,14 +370,14 @@ intergraph .tooltip-arrow {
border: 1px solid black;
background-color: white;
display: none;
z-index: 2;
z-index: 3;
}
#graph2DMenu {
border: 1px solid black;
background-color: white;
display: none;
z-index: 2;
z-index: 3;
}
#nodeId {
......@@ -408,4 +408,14 @@ intergraph .tooltip-arrow {
justify-content: center;
z-index: 3;
background-color: rgba(127, 127, 127, 0.5);
}
#cytoRightClickOverlay {
display: none;
position: absolute;
top: 0;
left: 0;
height: 100%;
width: 100%;
z-index: 2;
}
\ No newline at end of file
......@@ -80,7 +80,8 @@ function setupDateFilter(app, newGraph, id, start, end) {
dateValues[handle].innerHTML = values[handle];
app.updateFilter();
newGraph.filterByDate(dateValues.map(toIso));
newGraph.filterGraph();
newGraph.applyFilterToGraph();
});
}
......@@ -107,13 +108,18 @@ function start(settings, login, password) {
// Setup interface
$('#db_name').html(settings.database.name);
//$('#keyword').focus();
$('#keyword').prop('placeholder', settings.keywordSearch.placeholder);
settings.keywordSearch.selection.forEach((s) => {
$('').prop('placeholder', settings.keywordSearch.placeholder);
settings.keywordSearch.selection.forEach((s, ind) => {
console.log("index: ")
let o = new Option(s.option, s.layer);
o.nodeTypes = settings.layerTypes.find(x => x.name === s.layer).nodeTypes
o.placeholder = settings.keywordSearch.selection[ind].placeholder
$(o).html(s.option);
$("#input-graph-type").append(o);
});
$("#keyword").attr("placeholder", $("#input-graph-type :selected")[0].placeholder)
$("#input-graph-type").on("change",
() => $("#keyword").attr("placeholder", $("#input-graph-type :selected")[0].placeholder))
settings.source.properties.forEach((property) => {
let option = settings.source.options[property];
......@@ -241,6 +247,12 @@ function start(settings, login, password) {
$('#graphselector #cytocanvas').trigger("click"); // To set cytocanvas as default canvas
$('#cytoRightClickOverlay').click(() => {
$('#contextMenu').hide();
$('#graph2DMenu').hide();
$('#cytoRightClickOverlay').hide();
});
$( "#queryButton" ).click(query);
$( "#keyword" ).keypress(function(e) {
if(e.which == 13) {
......@@ -417,8 +429,8 @@ function start(settings, login, password) {
$("#filter-content").on("input", () => {
const keywords = $("#filter-content").val().split(" ")
graph2D.graph2d.filterByKeywords(keywords)
graph2D.applyFilterToGraph()
graph2D.filterGraph();
graph2D.applyFilterToGraph();
})
return app;
}
......
......@@ -105,8 +105,8 @@
<div class="menuItem" id="deleteNode"><i class="fa fa-trash fa-fw"></i>Remove node</div>
</div>
<div id="graph2DMenu" oncontextmenu="return false">
<div><i class="fa fa-fw"></i><b>Graph</b></div>
<div class="menuItem" id="clear2DGraph"><i class="fa fa-fw"></i>Clear Graph</div>
<div><i class="fa fa-fw"></i><b>Canvas</b></div>
<div class="menuItem" id="clear2DGraph"><i class="fa fa-fw"></i>Clear Canvas</div>
</div>
</div>
<div id="filters">
......@@ -152,6 +152,7 @@
</div>
</div>
</div>
<div id="cytoRightClickOverlay" oncontextmenu="return false"></div>
<div class="hidden" style="display: none;">
<span id="info" style="display: none"></span>
<span id="type" style="display: none"></span>
......
module.exports = { version: '183' }
module.exports = { version: '195' }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment