diff --git a/sg-backend/db.py b/sg-backend/db.py index 06dbcd13c3ebcfa5fba7acb3c6533a020b3beee7..911e7dd9510088c0b214cfe728a68832c9969077 100644 --- a/sg-backend/db.py +++ b/sg-backend/db.py @@ -54,12 +54,13 @@ class Neo4j: def get_relations(self): with self.driver.session() as session: - results = session.run("MATCH p = (a)-[r]->(b) RETURN a.name as source,b.name as target, r as relation_type") + results = session.run("MATCH p = (a:Software)-[r]->(b:Software) RETURN a.name as source,b.name as target, " + "r as relation_type") return results.data() def get_nodes(self): with self.driver.session() as session: - results = session.run("MATCH (a) return Id(a) as key, a.name as name") + results = session.run("MATCH (a:Software) return Id(a) as key, a.name as name") return results.data() def insert_software(self, insert_data): @@ -81,6 +82,11 @@ class Neo4j: if len(results.data()) != 2: return {"Error": "%s/%s NOT FOUND" % (insert_data.software1, insert_data.software2)} + results = session.run("match (n where n.name = '%s') match (m where m.name= '%s') return exists( (n)--(m) ) " % + (insert_data.software1, insert_data.software2)) + if results.data()[0]['exists( (n)--(m) )']: + return {"Error": "Relation already exist"} + results = session.run( "MATCH (a:Software), (b:Software) WHERE a.name = '%s' AND b.name = '%s' CREATE (a)-[r:%s]->(b) " "RETURN type(r)" % (insert_data.software1, insert_data.software2, insert_data.relationType)) diff --git a/sg-frontend/index.html b/sg-frontend/index.html index fb6e4814765868099fd669c66f3cfd9e98126985..81e4661d915dd7d1a67214748d6d7fb185d8235e 100644 --- a/sg-frontend/index.html +++ b/sg-frontend/index.html @@ -12,7 +12,7 @@ <div class="topnav"> <a id="home" class="active" href="/">Home</a> <a id="sigma" href="#/sigma-custom">Software graph</a> - <a id="add" href="#/add-node">Software graph</a> + <a id="add" href="#/add-node">Software insert</a> </div> </div> <script type="module" src="/src/main.ts"></script> diff --git a/sg-frontend/src/components/RelationInsert.svelte b/sg-frontend/src/components/RelationInsert.svelte index 4c6fffcebfb1afd19ceb512681181ccd3a7149ed..78e5e6b927d2e10e1b33e2ece980fd1a09c71694 100644 --- a/sg-frontend/src/components/RelationInsert.svelte +++ b/sg-frontend/src/components/RelationInsert.svelte @@ -9,6 +9,26 @@ node; const BACKEND_URL = import.meta.env.VITE_BACKEND_URL; onMount(async () => { + + const relationAddButton = document.getElementById("relationAddButton"); + relationAddButton.addEventListener("click", async () => { + const response = await fetch(BACKEND_URL + "/relation-insert", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + software1: software1.label, + software2: software2.label, + relationType: document.querySelector('input[name="relationType"]:checked').value + }), + }); + if (response.ok) { + result = await response.json(); + node = result.node; + } + }); + await fetch(BACKEND_URL + "/software") .then((response) => response.json()) .then((data) => { @@ -33,14 +53,14 @@ <SoftwareSelect items="{softwares}" bind:selectedSoftware="{software1}"/> <div> <label class="radio-inline"> - <input type="radio" id="SIMILAR" name="relationType" checked>SIMILAR + <input type="radio" id="SIMILAR" name="relationType" value="SIMILAR" checked>SIMILAR </label> <label class="radio-inline"> - <input type="radio" id="HAS_SAME_CREATOR" name="relationType">HAS SAME CREATOR + <input type="radio" id="HAS_SAME_CREATOR" name="relationType" value="HAS_SAME_CREATOR">HAS SAME CREATOR </label> </div> <SoftwareSelect items="{softwares}" bind:selectedSoftware="{software2}"/> - <button type="submit">Add</button> + <button id="relationAddButton">Add</button> </form> <style> diff --git a/sg-frontend/src/components/SoftwareInsert.svelte b/sg-frontend/src/components/SoftwareInsert.svelte index 0c660165dfc8c364782db7c9fe76139125c0710b..429da71f89f20face74a964eb8b4260dc99f3dcc 100644 --- a/sg-frontend/src/components/SoftwareInsert.svelte +++ b/sg-frontend/src/components/SoftwareInsert.svelte @@ -1,58 +1,87 @@ <script> - import Select from "svelte-select"; + import {onMount} from "svelte"; + const BACKEND_URL = import.meta.env.VITE_BACKEND_URL; + + + let softwares = [], + result, + node; + + + onMount(async () => { + const softwareName = document.getElementById("softwareName"); + const newNodeButton = document.getElementById("newNodeButton"); + + newNodeButton.addEventListener("click", () => { + postSoftwareInsert(); + }); + + async function postSoftwareInsert() { + const res = await fetch(BACKEND_URL + "/software-insert", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({"newNodeName": softwareName.value}), + }); + } + + }); </script> + <form class="form-inline"> - <label for="softwareName">Software Name :</label> - <input type="text" id="softwareName" placeholder="" name="softwareName"> - <button type="submit">Submit</button> + <label for="softwareName">Software Name :</label> + <input type="text" id="softwareName" placeholder="" name="softwareName"> + <button id="newNodeButton">Submit</button> </form> <style> /* Style the form - display items horizontally */ -.form-inline { - display: flex; - flex-flow: row wrap; - align-items: center; -} - -/* Add some margins for each label */ -.form-inline label { - margin: 5px 10px 5px 0; -} - -/* Style the input fields */ -.form-inline input { - vertical-align: middle; - margin: 5px 10px 5px 0; - padding: 10px; - background-color: #fff; - border: 1px solid #ddd; -} - -/* Add responsiveness - display the form controls vertically instead of horizontally on screens that are less than 800px wide */ -@media (max-width: 800px) { - .form-inline input { - margin: 10px 0; - } - - .form-inline { - flex-direction: column; - align-items: stretch; - } -} - form { - max-width: 400px; - background: #f4f4f4; - padding: 20px; - border-radius: 4px; - color: black; - margin: auto; - } - - label { - margin: 0 0 10px; - } + .form-inline { + display: flex; + flex-flow: row wrap; + align-items: center; + } + + /* Add some margins for each label */ + .form-inline label { + margin: 5px 10px 5px 0; + } + + /* Style the input fields */ + .form-inline input { + vertical-align: middle; + margin: 5px 10px 5px 0; + padding: 10px; + background-color: #fff; + border: 1px solid #ddd; + } + + /* Add responsiveness - display the form controls vertically instead of horizontally on screens that are less than 800px wide */ + @media (max-width: 800px) { + .form-inline input { + margin: 10px 0; + } + + .form-inline { + flex-direction: column; + align-items: stretch; + } + } + + form { + max-width: 400px; + background: #f4f4f4; + padding: 20px; + border-radius: 4px; + color: black; + margin: auto; + } + + label { + margin: 0 0 10px; + } </style>