diff --git a/sg-frontend/index.html b/sg-frontend/index.html index 81e4661d915dd7d1a67214748d6d7fb185d8235e..0c6cce9579b16a21ec4d15954fa0b201ec70013a 100644 --- a/sg-frontend/index.html +++ b/sg-frontend/index.html @@ -8,38 +8,9 @@ </head> <body> -<div id="app"> - <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 insert</a> - </div> -</div> +<div id="app"></div> <script type="module" src="/src/main.ts"></script> </body> -<style> - .topnav { - overflow: hidden; - background-color: #333; - } - .topnav a { - float: left; - color: #f2f2f2; - text-align: center; - padding: 14px 16px; - text-decoration: none; - font-size: 17px; - } - - .topnav a:hover { - background-color: #ddd; - color: black; - } - - .topnav a.active { - background-color: #04AA6D; - color: white; - }</style> -</html> +</html> \ No newline at end of file diff --git a/sg-frontend/src/App.svelte b/sg-frontend/src/App.svelte index 1ffb7ff7af9939f4e675697c57b62525817d9805..0672a061aa9d0bfa5ef1ca3cce5ba2ea2c2a3e06 100644 --- a/sg-frontend/src/App.svelte +++ b/sg-frontend/src/App.svelte @@ -1,22 +1,35 @@ <script> - import Router from "svelte-spa-router"; - import Index from "./routes/Index.svelte"; - import Add from "./routes/Add.svelte"; - import Graph from "./routes/Graph.svelte"; - import NotFound from "./routes/NotFound.svelte"; + import Router from "svelte-spa-router"; + import Index from "./routes/Index.svelte"; + import Add from "./routes/Add.svelte"; + import Graph from "./routes/Graph.svelte"; + import NotFound from "./routes/NotFound.svelte"; import Sigma from "./routes/Sigma.svelte"; import SigmaCustom from "./routes/SigmaCustom.svelte"; import AddNode from "./routes/AddNode.svelte"; + import Navbar from "./components/Navbar.svelte"; - let routes = { - "/": Index, - "/add": Add, - "/graph": Graph, - "/sigma": Sigma, - "/sigma-custom": SigmaCustom, - "/add-node": AddNode, - "*": NotFound - } + let routes = { + "/": Index, + "/add": Add, + "/graph": Graph, + "/sigma": Sigma, + "/sigma-custom": SigmaCustom, + "/add-node": AddNode, + "*": NotFound + } </script> +<div> + <Navbar/> + <Router {routes}/> +</div> -<Router {routes} /> \ No newline at end of file +<style> + :root { + --primary: #1d3557; + --secondary: #457b9d; + --tertiary: #a8dadc; + --quaternary: #f1faee; + --quinary: #e63946; + } +</style> \ No newline at end of file diff --git a/sg-frontend/src/components/Navbar.svelte b/sg-frontend/src/components/Navbar.svelte new file mode 100644 index 0000000000000000000000000000000000000000..d256de65d8f4299fe17ce7bb94ea9d482495b4ac --- /dev/null +++ b/sg-frontend/src/components/Navbar.svelte @@ -0,0 +1,35 @@ +<script> + +</script> + +<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 insert</a> +</div> + +<style> + .topnav { + overflow: hidden; + background-color: var(--primary); + } + + .topnav a { + float: left; + color: var(--tertiary); + text-align: center; + padding: 14px 16px; + text-decoration: none; + font-size: 17px; + } + + .topnav a:hover { + background-color: var(--quaternary); + color: black; + } + + .topnav a.active { + background-color: var(--tertiary); + color: var(--primary); + } +</style> \ No newline at end of file diff --git a/sg-frontend/src/components/SoftwareInsert.svelte b/sg-frontend/src/components/SoftwareInsert.svelte index 702fc318d9c8038854a6d5720fca4907f8bc4019..ef898086198cc74f05ae7c1edde47a82c8dffded 100644 --- a/sg-frontend/src/components/SoftwareInsert.svelte +++ b/sg-frontend/src/components/SoftwareInsert.svelte @@ -16,6 +16,7 @@ newNodeButton.addEventListener("click", (e) => { postSoftwareInsert(); e.preventDefault(); + window.location.reload(); }); async function postSoftwareInsert() { diff --git a/sg-frontend/src/components/SoftwareMerger.svelte b/sg-frontend/src/components/SoftwareMerger.svelte index 6466e824eaa3949ad16d75595f4746c043a4e678..947413f24de8785717c3866224bd5d4c45bb6c5c 100644 --- a/sg-frontend/src/components/SoftwareMerger.svelte +++ b/sg-frontend/src/components/SoftwareMerger.svelte @@ -1,108 +1,119 @@ <script> - import { onMount } from "svelte"; + import {onMount} from "svelte"; import SoftwareSelect from "./SoftwareSelect.svelte"; + const BACKEND_URL = import.meta.env.VITE_BACKEND_URL; - console.log(import.meta.env.VITE_BACKEND_URL); - let softwares = [], - software1, - software2, - result, - node; - onMount(async () => { - await fetch(BACKEND_URL + "/software") - .then((response) => response.json()) - .then((data) => { - console.log(data); - let tempSoft = []; - data["softwares"].forEach((element) => { - node = Object.values(Object.values(element))[0]; - delete Object.assign(node, { ["label"]: node["name"] })["name"]; - tempSoft.push(node); - }); - softwares = tempSoft; - console.log(softwares); - }) - .catch((error) => { - console.log(error); - return []; - }); - }); - function checkVars() { - console.log({ onChange: { software1: software1, softwares: softwares } }); - if (software1 && software2) { - console.log("OK"); - postSoftwareMerger(); - } - } + console.log(import.meta.env.VITE_BACKEND_URL); + let softwares = [], + software1, + software2, + result, + node; + onMount(async () => { + await fetch(BACKEND_URL + "/software") + .then((response) => response.json()) + .then((data) => { + console.log(data); + let tempSoft = []; + data["softwares"].forEach((element) => { + node = Object.values(Object.values(element))[0]; + delete Object.assign(node, {["label"]: node["name"]})["name"]; + tempSoft.push(node); + }); + softwares = tempSoft; + console.log(softwares); + }) + .catch((error) => { + console.log(error); + return []; + }); + }); + + function checkVars() { + console.log({onChange: {software1: software1, softwares: softwares}}); + if (software1 && software2) { + console.log("OK"); + postSoftwareMerger(); + } + } - $: (software1, software2), checkVars(); + $: (software1, software2), checkVars(); - async function postSoftwareMerger() { - const res = await fetch(BACKEND_URL + "/software-search", { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ - software1: software1.label, - software2: software2.label, - }), - }); + async function postSoftwareMerger() { + const res = await fetch(BACKEND_URL + "/software-search", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + software1: software1.label, + software2: software2.label, + }), + }); - const data = await res.json(); - data.softwares.shift(); - data.softwares.pop(); - result = data.softwares; - console.log(result); - console.log("AFTER"); - console.log({ onChange: { software1: software1, softwares: softwares } }); - } + const data = await res.json(); + data.softwares.shift(); + data.softwares.pop(); + result = data.softwares; + console.log(result); + console.log("AFTER"); + console.log({onChange: {software1: software1, softwares: softwares}}); + } </script> <p>First Software</p> -<SoftwareSelect items="{softwares}" bind:selectedSoftware="{software1}" /> +<SoftwareSelect items="{softwares}" bind:selectedSoftware="{software1}"/> <p>Second Software</p> -<SoftwareSelect items="{softwares}" bind:selectedSoftware="{software2}" /> +<SoftwareSelect items="{softwares}" bind:selectedSoftware="{software2}"/> {#if result} - <div style="max-width: 470px; text-align: left; margin: auto;"> - <h2>Results</h2> - {#if result.length > 0} - <p> - Features are more similar to {software1.label} at the start,<br />and - gradually more to {software2.label}.<br />Alternatives found : - </p> - {/if} + <div style="max-width: 470px; text-align: left; margin: auto;"> + <h2>Results</h2> + + {#if result.length > 0} + <p> + Features are more similar to {software1.label} at the start,<br/>and + gradually more to {software2.label}.<br/>Alternatives found : + </p> + {/if} - <p>From {software1.label}</p> - <!-- - <ul class="list-disc"> - {#each result as software} - <li>{software.name}</li> - {:else} - <p>No alternative in between</p> - {/each} - </ul> - --> - <div class="overflow-x-auto"> - <table class="table w-full"> - <thead> - <tr> - <th>Software</th> - </tr> - </thead> - <tbody> - {#each result as software} - <tr> - <td>{software.name}</td> - </tr> - {:else} - <p>No alternative in between</p> - {/each} - </tbody> - </table> - </div> + <p>From: <b>{software1.label}</b> + <br> + 🔽 + </p> - <p>To {software2.label}</p> - </div> + <ul class="list-disc"> + {#each result as software} + <li><b>{software.name}</b></li> + {:else} + <p>No alternative in between</p> + {/each} + </ul> + + <!-- <div class="overflow-x-auto">--> + <!-- <table class="table w-full">--> + <!-- <thead>--> + <!-- <tr>--> + <!-- <th>Software</th>--> + <!-- </tr>--> + <!-- </thead>--> + <!-- <tbody>--> + <!-- {#each result as software}--> + <!-- <tr>--> + <!-- <td>{software.name}</td>--> + <!-- </tr>--> + <!-- {:else}--> + <!-- <p>No alternative in between</p>--> + <!-- {/each}--> + <!-- </tbody>--> + <!-- </table>--> + <!-- </div>--> + + <p> + 🔽 + <br> + To: <b>{software2.label}</b></p> + </div> {/if} + +<style></style> \ No newline at end of file diff --git a/sg-frontend/src/constants.ts b/sg-frontend/src/constants.ts new file mode 100644 index 0000000000000000000000000000000000000000..a1b9f5183ac05a85cbc103d6724843363a0d33a7 --- /dev/null +++ b/sg-frontend/src/constants.ts @@ -0,0 +1,9 @@ +export const colors: { [key: string]: string } = { + similar: '#FF0000', + same_creator: '#00FF00', + primary: '#1d3557', + secondary: '#457b9d', + tertiary: '#a8dadc', + quaternary: '#f1faee', + quinary: '#e63946', +} \ No newline at end of file diff --git a/sg-frontend/src/routes/SigmaCustom.svelte b/sg-frontend/src/routes/SigmaCustom.svelte index 430516090a0c42783bc1e0066f89681b0d399851..ca8fdccc0cb7d32c7bb51654cc2cec37aae3d96c 100644 --- a/sg-frontend/src/routes/SigmaCustom.svelte +++ b/sg-frontend/src/routes/SigmaCustom.svelte @@ -1,5 +1,5 @@ <script lang="ts"> - import {Coordinates, EdgeDisplayData, NodeDisplayData} from "sigma/types"; + import {EdgeDisplayData, NodeDisplayData} from "sigma/types"; import FA2Layout from "graphology-layout-forceatlas2/worker"; import forceAtlas2 from "graphology-layout-forceatlas2"; import {circular} from "graphology-layout"; @@ -8,12 +8,27 @@ import ForceSupervisor from "graphology-layout-force/worker"; import {onMount} from 'svelte'; + import {colors} from "../constants"; onMount(() => { fetch("http://localhost:8000/software-graph") .then(response => response.json()) .then(data => { - + data["nodes"].forEach(function (node) { + node.attributes.color = colors.primary; + }); + data["edges"].forEach(function (edge) { + switch (edge.label) { + case "SIMILAR": + edge.attributes.color = colors.secondary; + break; + case "HAS_SAME_CREATOR": + edge.attributes.color = colors.tertiary + break; + } + edge.attributes.size = 5; + }); + console.log(data) // Retrieve some useful DOM elements: const container = document.getElementById("sigma-container") as HTMLElement; @@ -99,6 +114,7 @@ if (state.hoveredNode && !graph.hasExtremity(edge, state.hoveredNode)) { res.hidden = true; + } if (state.suggestions && (!state.suggestions.has(graph.source(edge)) || !state.suggestions.has(graph.target(edge)))) { @@ -182,17 +198,26 @@ </script> -<h1>Software Map</h1> -<div id="content"> + + <h1>Software Map</h1> + + <p> + <span style="color: {colors.secondary}">|</span> : Similar features + <br> + <span style="color: {colors.tertiary}">|</span> : Same creator + + </p> +<div> <div id="sigma-container"/> </div> <style> - #content{ + #content { max-width: none !important; margin: 0; padding: 0; } + h1 { position: absolute; z-index: 1; @@ -203,6 +228,13 @@ text-align: center; } + p { + position: absolute; + margin-left: 50px; + margin-top: 50px; + z-index: 1; + } + html, body, #sigma-container {