Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Msj #63

Open
wants to merge 14 commits into
base: master
Choose a base branch
from
11 changes: 11 additions & 0 deletions application.css
Original file line number Diff line number Diff line change
Expand Up @@ -147,3 +147,14 @@ body {
.hidden {
display: none;
}

#search-input {
width: 150px;
height: 15px;
}

#suggestions {
width: 150px;
height: 100px;
overflow: auto;
}
187 changes: 162 additions & 25 deletions application.js
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,45 @@ require(["domReady!", "stix2viz/stix2viz/stix2viz"], function (document, stix2vi
}
}


function searchNameHandler(edgeDataSet, stixIdToObject, stixNameToObject){
var searchText = document.getElementById("searchInput").value;
//여기서 searchText로 검색 진행 (일치하는 키 있으면 객체가, 없으면 undefined가 된다)
let stixObject = stixNameToObject.get(searchText);
if(stixObject)
{
if(!view.isHidden(searchText))
{
view.selectNode(stixObject.get('id'));
populateSelected(stixObject, edgeDataSet, stixIdToObject);
}
else
{
view.selectNode(undefined);
populateSelected(new Map([["", "(Hidden)"]]), edgeDataSet, stixIdToObject);
}
}
else
{
view.selectNode(undefined);
populateSelected(new Map([["", "(No Result)"]]), edgeDataSet, stixIdToObject);
}
}


function suggestionListClickHandler(edgeDataSet, stixIdToObject, stixObject){
if(stixObject)
{
view.selectNode(stixObject.get('id'));
populateSelected(stixObject, edgeDataSet, stixIdToObject);
}
else
{
view.selectNode(undefined);
populateSelected(new Map([["", "(No Result)"]]), edgeDataSet, stixIdToObject);
}
}


/* ******************************************************
* Initializes the view, then renders it.
Expand Down Expand Up @@ -145,6 +184,10 @@ require(["domReady!", "stix2viz/stix2viz/stix2viz"], function (document, stix2vi
let [nodeDataSet, edgeDataSet, stixIdToObject]
= stix2viz.makeGraphData(content, customConfig);

let stixNameToObject = new Map();
for (let object of stixIdToObject.values())
stixNameToObject.set(object.get("name"), object);

let wantsList = false;
if (nodeDataSet.length > 200)
wantsList = confirm(
Expand Down Expand Up @@ -177,6 +220,63 @@ require(["domReady!", "stix2viz/stix2viz/stix2viz"], function (document, stix2vi
);
}

let searchInput = document.createElement("input");
searchInput.setAttribute("type", "text");
searchInput.setAttribute("id", "searchInput");
searchInput.classList.add("search-input");

let searchButton = document.createElement("button");
searchButton.setAttribute("id", "searchButton");
searchButton.textContent = "search SDO";

let suggestionList = document.createElement("ul");
suggestionList.setAttribute("id", "suggestions");
suggestionList.classList.add("suggestions")

let searchDiv = document.querySelector("#canvas-container");
searchDiv.insertBefore(searchInput, searchDiv.children[1]);
searchDiv.insertBefore(searchButton, searchDiv.children[2]);
searchDiv.insertBefore(suggestionList, searchDiv.children[3]);

searchInput.addEventListener('input', function() {
const keyword = this.value;
const matchedResults = [];

for (let key of stixNameToObject.keys()){
if (key){
if(key.includes(keyword) && !view.isHidden(key)){
matchedResults.push(key);
}
}
}

suggestionList.innerHTML = '';

for (let result of matchedResults){
const li = document.createElement('li');
li.textContent = result;
li.addEventListener(
"click", e => {
e.stopPropagation(),
suggestionListClickHandler(edgeDataSet, stixIdToObject, stixNameToObject.get(li.textContent))
}
);
suggestionList.appendChild(li);
}
});
searchButton.addEventListener(
"click", e => {
e.stopPropagation(),
searchNameHandler(edgeDataSet, stixIdToObject, stixNameToObject)
}
);
searchInput.addEventListener("keydown", function(event){
if(event.keyCode === 13) {
event.stopPropagation(),
searchNameHandler(edgeDataSet, stixIdToObject, stixNameToObject)
}
});

populateLegend(...view.legendData);
}
catch (err)
Expand Down Expand Up @@ -206,18 +306,59 @@ require(["domReady!", "stix2viz/stix2viz/stix2viz"], function (document, stix2vi
evt.preventDefault();
evt.dataTransfer.dropEffect = 'copy'; // Explicitly show this is a copy.
}

function handleFiles(files) {
// files is a FileList of File objects (in our case, just one)

for (var i = 0, f; f = files[i]; i++) {
document.getElementById('chosen-files').innerText += f.name + " ";
let customConfig = document.getElementById('paste-area-custom-config').value;
var r = new FileReader();
r.onload = function(e) {vizStixWrapper(e.target.result, customConfig);};
r.readAsText(f);
let customConfig = '';
let jsonData = {};

// 단일 파일 텍스트로 읽어오는 함수
function readFile(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader();

reader.onload = function (e) {
const data = JSON.parse(e.target.result);
resolve(data);
};

reader.onerror = function (e) {
reject(e);
};

reader.readAsText(file);
});
}

// FileList 배열로 변환
const filesArray = Array.from(files);

// 모든 파일 읽고 데이터 결합하는 Promise
Promise.all(filesArray.map(readFile))
.then((fileDataArray) => {
// 여러 파일에서 데이터 결합
jsonData = fileDataArray.reduce((acc, curr) => {
if (curr.type === 'bundle') {
// type이 bundle이면 objects 값만 추출
return acc.concat(curr.objects || []);
} else {
// bundle이 아니면 그대로 결합
return acc.concat(curr);
}
}, []);

jsonData = JSON.stringify(jsonData);

vizStixWrapper(jsonData, customConfig);

document.getElementById('chosen-files').innerText = filesArray.map(file => file.name).join(' ');
})
.catch((error) => {
console.error('Error reading file:', error);
});

linkifyHeader();
}
linkifyHeader();
}

/* ---------------------------------------------------- */

/* ******************************************************
Expand Down Expand Up @@ -773,20 +914,16 @@ is not serving JSON, or is not running a webserver.\n\nA GitHub Gist can be crea
}
}

function selectedNodeClick() {
let selected = document.getElementById('selected');
if (selected.className.indexOf('clicked') === -1) {
selected.className += " clicked";
selected.style.position = 'absolute';
selected.style.left = '25px';
selected.style.width = (window.innerWidth - 110) + "px";
selected.style.top = (document.getElementById('canvas').offsetHeight + 25) + "px";
selected.scrollIntoView(true);
} else {
selected.className = "sidebar"
selected.removeAttribute("style")
function handleFilterDate() {
if(!view)
return;

let startDate = document.getElementById("startDate").value;
let endDate = document.getElementById("endDate").value;
//alert(startDate + " " + endDate);
view.toggleStixDate(startDate, endDate);
}
}


/* ******************************************************
* When the page is ready, setup the visualization and bind events
Expand All @@ -797,8 +934,8 @@ is not serving JSON, or is not running a webserver.\n\nA GitHub Gist can be crea
document.getElementById('header').addEventListener('click', resetPage, false);
uploader.addEventListener('dragover', handleDragOver, false);
uploader.addEventListener('drop', handleFileDrop, false);
document.getElementById('selected').addEventListener('click', selectedNodeClick, false);
document.getElementById("legend").addEventListener("click", legendClickHandler, {capture: true});

// filter date
document.getElementById("filter-date").addEventListener("click", handleFilterDate, false);
fetchJsonFromUrl();
});
31 changes: 26 additions & 5 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,20 @@
<meta charset="utf-8"/>
<link rel="stylesheet" type="text/css" href="application.css" />
<script src="require.js" data-main="application"></script>
<!-- toggle tooltip for "How to use" -->
<script src="tooltip.js"></script>
<style>
.tooltip {
position: fixed;
padding: 10px 20px;
border: 1px solid #b3c9ce;
border-radius: 4px;
text-align: left;
color: #333;
background: #fff;
box-shadow: 3px 3px 3px rgba(0, 0, 0, .3);
}
</style>
</head>

<body>
Expand All @@ -20,7 +34,7 @@ <h1>

<div id="uploader">
<p>Drop some STIX 2.x here!</p>
<input type="file" id="files" name="files" /><br>
<input type="file" id="files" name="files" multiple/><br>
<p>-- OR --</p>
<p>Fetch some STIX 2.x from this URL!</p>
<input type="text" id="url" name="url" placeholder="Paste URL here" /><br>
Expand All @@ -36,12 +50,19 @@ <h1>
<textarea id="paste-area-custom-config" name="pasted" placeholder="Copy/Paste, in JSON format, (if you want to specify this) your custom config for the graph as such: &#10;{&#10;&quot;&lt;objectType&gt;&quot;: &#10;&#9;{&#10;&#9;&#9;&quot;displayProperty&quot;: &lt;nameOfProperty&gt;, &#10;&#9;&#9;&quot;displayIcon&quot;: &lt;nameOfIconFile&gt;,&#10;&#9;&#9;&quot;embeddedRelationships&quot;: [...relationships...]&#10;&#9;},&#10;&quot;userLabels&quot;:&#10;&#9;{&#10;&#9;&#9;&quot;&lt;STIX ID&gt;&quot;: &quot;a label&quot;,&#10;&#9;&#9;...&#10;&#9;},&#10;&quot;include&quot;: &lt;STIX object filter criteria&gt;,&#10;&quot;exclude&quot;: &lt;STIX object filter criteria&gt;&#10;}&#10;&#10;&quot;&lt;objectType&gt;&quot; lets you customize labels per-type; &quot;userLabels&quot; lets you customize labels per-ID. For type-specific customization, please note that the above properties are the only currently-supported properties, and at least 1 of them has to be specified. ID-specific label customization will take priority over type-specific labels.&#10;&#10;Each relationship in the &quot;embeddedRelationships&quot; list is a [&quot;&lt;property path&gt;&quot;, &quot;&lt;edge label&gt;&quot;, &lt;edge direction boolean&gt;] triple. The property path should refer to a _ref(s) property somewhere within objects of that type."></textarea>
</div>
<div id="canvas-container" class="hidden">
<div id="date-selector">
<label for="startDate">Start Date:</label>
<input type="date" id="startDate" name="date" placeholder="start" />
<label for="endDate">End Date:</label>
<input type="date" id="endDate" name="date" placeholder="end" />
<button id="filter-date">Filter</button>
</div>
<div id="canvas-wrapper">
<button data-tooltip="Dragging anywhere will pan the viewing area.<br>
Use the mouse wheel to zoom.<br>
Click the 'Selected Node' area to expand/shrink it.<br>
Click legend items to toggle visibility of nodes of a particular STIX type.">How to use</button>
<div id="canvas"></div>
<p>Dragging anywhere will pan the viewing area.</p>
<p>Use the mouse wheel to zoom.</p>
<p>Click the 'Selected Node' area to expand/shrink it.</p>
<p>Click legend items to toggle visibility of nodes of a particular STIX type.</p>
</div>
<div id="selected" class="sidebar">
<h2>Selected Node</h2>
Expand Down
Loading