focus searched nodes/edges on the canvas
This commit is contained in:
parent
a7928f119d
commit
052e4742f5
29
editor.css
29
editor.css
@ -55,7 +55,12 @@ body {
|
|||||||
color: rgb(75, 151, 151);
|
color: rgb(75, 151, 151);
|
||||||
}
|
}
|
||||||
|
|
||||||
.submenu #search-container {
|
#searchmenu {
|
||||||
|
width: 400px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
#searchmenu #search-container {
|
||||||
/* position: fixed;
|
/* position: fixed;
|
||||||
top: 0px;
|
top: 0px;
|
||||||
bottom: 0px; */
|
bottom: 0px; */
|
||||||
@ -71,7 +76,7 @@ body {
|
|||||||
#search-container input {
|
#search-container input {
|
||||||
/* height: 100%; */
|
/* height: 100%; */
|
||||||
height: 40px;
|
height: 40px;
|
||||||
width: 300px;
|
width: 100%;
|
||||||
border-radius: 15px;
|
border-radius: 15px;
|
||||||
border: 1px solid rgb(117, 117, 117);
|
border: 1px solid rgb(117, 117, 117);
|
||||||
padding-left: 10px;
|
padding-left: 10px;
|
||||||
@ -123,12 +128,30 @@ body {
|
|||||||
#search-results {
|
#search-results {
|
||||||
display: none;
|
display: none;
|
||||||
position: relative;
|
position: relative;
|
||||||
min-height: 20px;
|
|
||||||
padding: 20 20 20 20;
|
padding: 20 20 20 20;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#search-results div {
|
||||||
|
line-height: 2;
|
||||||
|
padding-top: 5px;
|
||||||
|
padding-bottom: 5px;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
transition: all 100ms ease-out 50ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
#search-results div:hover {
|
||||||
|
font-weight: 500;
|
||||||
|
color: rgb(75, 151, 151);
|
||||||
|
}
|
||||||
|
|
||||||
|
#search-results div:active {
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
.submenu {
|
.submenu {
|
||||||
font-family: 'Inter';
|
font-family: 'Inter';
|
||||||
width: fit-content;
|
width: fit-content;
|
||||||
|
|||||||
@ -5,6 +5,7 @@
|
|||||||
<script src="https://unpkg.com/force-graph@1.43.0/dist/force-graph.min.js"></script>
|
<script src="https://unpkg.com/force-graph@1.43.0/dist/force-graph.min.js"></script>
|
||||||
<!-- <script src="./force-graph-master/src/force-graph.js"></script> -->
|
<!-- <script src="./force-graph-master/src/force-graph.js"></script> -->
|
||||||
<!--<script src="../../dist/force-graph.js"></script>-->
|
<!--<script src="../../dist/force-graph.js"></script>-->
|
||||||
|
<script src="https://cdn.jsdelivr.net/gh/nextapps-de/flexsearch@0.7.31/dist/flexsearch.bundle.js"></script>
|
||||||
<link rel="STYLESHEET" type="text/css" href="./editor.css">
|
<link rel="STYLESHEET" type="text/css" href="./editor.css">
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
@ -126,9 +127,9 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="menuitem" onclick="openSearchMenu(this)">
|
<div class="menuitem" onclick="openSearchMenu(this)">
|
||||||
<div class="menubutton">Search</div>
|
<div class="menubutton">Search</div>
|
||||||
<div class="submenu menu-lightmode" onclick="event.stopPropagation()">
|
<div id="searchmenu" class="submenu menu-lightmode" onclick="event.stopPropagation()">
|
||||||
<div id="search-container">
|
<div id="search-container">
|
||||||
<input type="text" placeholder="Nodes, Edges, ..." onclick="showSearchResults()">
|
<input id="search-input" type="text" placeholder="Nodes, Edges, ..." onclick="showSearchResults()" oninput="search(this.value)">
|
||||||
<span class="search-button">
|
<span class="search-button">
|
||||||
<svg height="18" width="18" xmlns="http://www.w3.org/2000/svg">
|
<svg height="18" width="18" xmlns="http://www.w3.org/2000/svg">
|
||||||
<circle cx="11" cy="7" r="6" stroke-width="2" fill="none" />
|
<circle cx="11" cy="7" r="6" stroke-width="2" fill="none" />
|
||||||
|
|||||||
54
editor.js
54
editor.js
@ -128,11 +128,61 @@ function openAboutMenu(menuitem) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function openSearchMenu(menuitem) {
|
function openSearchMenu(menuitem) {
|
||||||
|
document.getElementById('search-input').value = null;
|
||||||
|
while (searchResults.firstChild)
|
||||||
|
searchResults.removeChild(searchResults.lastChild);
|
||||||
openMenuItem(menuitem);
|
openMenuItem(menuitem);
|
||||||
}
|
}
|
||||||
|
|
||||||
document.getElementById('filepanel').style.opacity = 0;
|
document.getElementById('filepanel').style.opacity = 0;
|
||||||
|
|
||||||
|
//Search
|
||||||
|
const searchIndex = new FlexSearch.Index({tokenize: 'forward'});
|
||||||
|
// const searchDocument = new FlexSearch.Document();
|
||||||
|
// const searchWorker = new FlexSearch.Worker();
|
||||||
|
|
||||||
|
function search(text) {
|
||||||
|
while (searchResults.firstChild)
|
||||||
|
searchResults.removeChild(searchResults.lastChild);
|
||||||
|
var results = searchIndex.search(text, 10);
|
||||||
|
results.forEach(result => {
|
||||||
|
var target = null;
|
||||||
|
if (result.startsWith('state_name_')) {
|
||||||
|
result = result.replace('state_name_', '');
|
||||||
|
workflow.states.forEach(state => {
|
||||||
|
if (state.id === result)
|
||||||
|
target = state;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
result = result.replace('action_name_', '');
|
||||||
|
workflow.actions.forEach(action => {
|
||||||
|
if (action.id === result)
|
||||||
|
target = action;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
var r = document.createElement('div');
|
||||||
|
r.innerHTML = target.name;
|
||||||
|
searchResults.appendChild(r);
|
||||||
|
function defineFocus(div, target) {
|
||||||
|
div.onclick = (_ => {
|
||||||
|
var x = y = null;
|
||||||
|
if (target.actionData) {
|
||||||
|
x = target.source.x + (target.target.x - target.source.x);
|
||||||
|
y = target.source.y + (target.target.y - target.source.y);
|
||||||
|
} else {
|
||||||
|
x = target.x;
|
||||||
|
y = target.y;
|
||||||
|
}
|
||||||
|
closeMenuItem();
|
||||||
|
wfGraph.centerAt(x, y, 400);
|
||||||
|
wfGraph.zoom(5, 400);
|
||||||
|
select(target);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
defineFocus(r, target);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
function showSearchResults() {
|
function showSearchResults() {
|
||||||
searchResults.style.display = 'block';
|
searchResults.style.display = 'block';
|
||||||
}
|
}
|
||||||
@ -571,7 +621,7 @@ function prepareWorkflow() {
|
|||||||
selectedActor.value = NO_ACTOR;
|
selectedActor.value = NO_ACTOR;
|
||||||
selectedViewer.value = NO_VIEWER;
|
selectedViewer.value = NO_VIEWER;
|
||||||
|
|
||||||
//Parse workflow
|
//Parse workflow & create search index
|
||||||
|
|
||||||
workflow.states.forEach(state => {
|
workflow.states.forEach(state => {
|
||||||
var messages = [];
|
var messages = [];
|
||||||
@ -581,6 +631,7 @@ function prepareWorkflow() {
|
|||||||
state.stateData.viewers.forEach(v => viewers.push(new Role(v)));
|
state.stateData.viewers.forEach(v => viewers.push(new Role(v)));
|
||||||
state.stateData.viewers = viewers;
|
state.stateData.viewers = viewers;
|
||||||
state.stateData.payload = new Payload(state.stateData.payload);
|
state.stateData.payload = new Payload(state.stateData.payload);
|
||||||
|
searchIndex.add('state_name_' + state.id, state.name);
|
||||||
})
|
})
|
||||||
|
|
||||||
workflow.actions.forEach(action => {
|
workflow.actions.forEach(action => {
|
||||||
@ -597,6 +648,7 @@ function prepareWorkflow() {
|
|||||||
action.actionData['actor Viewers'].forEach(v => viewActors.push(new Role(v)));
|
action.actionData['actor Viewers'].forEach(v => viewActors.push(new Role(v)));
|
||||||
action.actionData['actor Viewers'] = viewActors;
|
action.actionData['actor Viewers'] = viewActors;
|
||||||
action.actionData.form = new Payload(action.actionData.form);
|
action.actionData.form = new Payload(action.actionData.form);
|
||||||
|
searchIndex.add('action_name_' + action.id, action.name);
|
||||||
})
|
})
|
||||||
|
|
||||||
workflow.actions.forEach(act => act.actionData.actors.forEach(a => {
|
workflow.actions.forEach(act => act.actionData.actors.forEach(a => {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user