HUGE update. New settings location, new styles, better dark mode, console, and ROUTING!!!

This commit is contained in:
2025-09-08 21:48:51 -05:00
parent 7c9bbcb90a
commit d9ecfb63ad
4 changed files with 474 additions and 33 deletions
+37 -14
View File
@@ -43,30 +43,44 @@
<input type="number" id="simSpeed" value="1" min="0.1" step="0.1" autocomplete="off"> <input type="number" id="simSpeed" value="1" min="0.1" step="0.1" autocomplete="off">
</div> </div>
</details> </details>
<details id="visualizationSettings">
<summary>Visualization Settings</summary>
<div id="visualizationSettingsContent">
<div id="visualizationSettingsToggles">
<input type="checkbox" id="showRanges">
<label for="showRanges">Show Ranges</label>
</div>
<div id="visualizationSettingsToggles">
<input type="checkbox" id="showTTL" checked>
<label for="showTTL">Show TTL Colors</label>
</div>
<div id="visualizationSettingsToggles">
<input type="checkbox" id="darkMode" checked>
<label for="darkMode">Dark Mode</label>
</div>
</div>
</details>
<div style="display: flex; flex-grow: 1; height: auto;"></div> <div style="display: flex; flex-grow: 1; height: auto;"></div>
<hr style="width: 100%;"/> <hr style="width: 100%;"/>
<div id="darkModeContainer"> <div id="darkModeContainer">
<input type="checkbox" id="darkMode" class="simToggle"> <input type="checkbox" id="quickPlace" class="simToggle">
<label for="darkMode">Dark Mode</label> <label for="quickPlace">Quick Place</label>
</div> </div>
</div> </div>
<div id="centerColumn" style="display: flex; flex-direction: column; align-items: center; justify-content: center; width: 70%; height: 100%; margin: 0 auto;"> <div id="centerColumn" style="display: flex; flex-direction: column; align-items: center; justify-content: center; width: 70%; height: 100%; margin: 0 auto;">
<div id="simContainer"></div> <div id="simContainer"></div>
<div id="routingProgressContainer" style="display: none;">
<progress id="routingProgress" value="0" max="100"></progress>
</div>
<div id="controlContainer"> <div id="controlContainer">
<div id="controlButtons"> <div id="controlButtons">
<button id="addNode" class="controlButton">Add Node</button> <button id="addNode" class="controlButton">Add Node</button>
<button id="sendPacket" class="controlButton">Send Packet</button> <button id="sendPacket" class="controlButton">Send Flood Packet</button>
<button id="quickPacket" class="controlButton">Quick Packet</button> <button id="quickPacket" class="controlButton">Quick Flood Packet</button>
<button id="resetTTLColors" class="controlButton">Reset TTL Colors</button> <button id="resetTTLColors" class="controlButton">Reset TTL Colors</button>
<button id="createRandomGraph" class="controlButton">Create Random Network</button> <button id="createRoutingTables" class="controlButton">Create Routing Tables</button>
</div> <button id="createRandomGraph" class="controlButton">Create Network</button>
<div id="simToggles">
<input type="checkbox" id="showRanges" class="simToggle">
<label for="showRanges">Show Ranges</label>
<input type="checkbox" id="showTTL" class="simToggle" checked>
<label for="showTTL">Show TTL Colors</label>
<input type="checkbox" id="quickPlace" class="simToggle">
<label for="quickPlace">Quick Place</label>
</div> </div>
</div> </div>
</div> </div>
@@ -78,7 +92,10 @@
<div id="randomGraphModalContent"> <div id="randomGraphModalContent">
<label for="randomGraphNodes">Number of Nodes</label> <label for="randomGraphNodes">Number of Nodes</label>
<input type="number" id="randomGraphNodes" value="10" autocomplete="off"> <input type="number" id="randomGraphNodes" value="10" autocomplete="off">
<button id="createRandomGraphConfirm" class="controlButton">Create</button> <div id="randomGraphModalButtons" style="display: flex; flex-direction: row; gap: 10px; justify-content: end; align-items: center;">
<button id="createRandomGraphCancel" class="controlButton" onclick="document.getElementById('randomGraphModal').style.display = 'none';">Cancel</button>
<button id="createRandomGraphConfirm" class="controlButton">Create</button>
</div>
</div> </div>
</div> </div>
<div id="warningModal"> <div id="warningModal">
@@ -88,6 +105,12 @@
<button id="warningModalConfirm" class="controlButton" onclick="document.getElementById('warningModal').style.display = 'none';">OK</button> <button id="warningModalConfirm" class="controlButton" onclick="document.getElementById('warningModal').style.display = 'none';">OK</button>
</div> </div>
</div> </div>
<div id="successModal">
<div id="successModalContent">
<p id="successModalMessage"></p>
<button id="successModalConfirm" class="controlButton" onclick="document.getElementById('successModal').style.display = 'none';">OK</button>
</div>
</div>
</div> </div>
<script type="text/javascript" src="script.js"></script> <script type="text/javascript" src="script.js"></script>
</body> </body>
+244 -5
View File
@@ -5,6 +5,8 @@ var TTL = 5;
var MAX_OUTGOING_CONNECTIONS = 3; var MAX_OUTGOING_CONNECTIONS = 3;
var MAX_INCOMING_CONNECTIONS = 3; var MAX_INCOMING_CONNECTIONS = 3;
var warningModalShown = false; var warningModalShown = false;
var displayWarningWhenDone = false;
var stillRouting = false;
function smoothColorTransition(color1, color2, min, max, current) { function smoothColorTransition(color1, color2, min, max, current) {
// Clamp current between min and max // Clamp current between min and max
@@ -101,6 +103,10 @@ onEdgeEngine.createEdgesTable();
onEdgeEngine.initMovement(); onEdgeEngine.initMovement();
onEdgeEngine.setArrivalCallback(({ from, to, dot }) => { onEdgeEngine.setArrivalCallback(({ from, to, dot }) => {
var ttl = parseInt(dot.id.split('-')[2]); var ttl = parseInt(dot.id.split('-')[2]);
if (stillRouting) {
routePacket(to, dot.id.split('-')[3], dot.id);
return;
}
if (document.getElementById('showTTL').checked) { if (document.getElementById('showTTL').checked) {
edges.update({id: `${from}->${to}`, color: {color: smoothColorTransition('#eb4034', '#40eb34', 0, TTL, ttl+1), highlight: smoothColorTransition('#eb4034', '#40eb34', 0, TTL, ttl+1)}}); edges.update({id: `${from}->${to}`, color: {color: smoothColorTransition('#eb4034', '#40eb34', 0, TTL, ttl+1), highlight: smoothColorTransition('#eb4034', '#40eb34', 0, TTL, ttl+1)}});
} else { } else {
@@ -184,6 +190,97 @@ function quickPacket(startNode, packetInfo, fromNode) {
} }
} }
// This is a modified version of quickPacket that contains some extra logic to save routing tables.
// It also disables the TTL colors for unreachable nodes to save performance.
function quickRoute(startNode, packetInfo, fromNode) {
const packetId = packetInfo.split('-')[0];
const ttlStart = parseInt(packetInfo.split('-')[2]);
const originNode = packetInfo.split('-')[3];
const queue = [{ nodeId: startNode, ttl: ttlStart, from: fromNode }];
while (queue.length > 0) {
const { nodeId, ttl, from } = queue.shift();
if (ttl < 0) {
displayWarningWhenDone = true;
continue;
}
if (nodeTable[nodeId]?.packetCache?.includes(packetId)) {
continue;
}
nodeTable[nodeId].packetCache.push(packetId);
nodeTable[nodeId].routingTable[originNode] = from;
if (document.getElementById('showTTL').checked) {
nodes.update({id: nodeId, color: {background: smoothColorTransition('#eb4034', '#40eb34', 0, TTL, ttl)}});
edges.update({id: `${from}->${nodeId}`, color: {color: smoothColorTransition('#eb4034', '#40eb34', 0, TTL, ttl+1), highlight: smoothColorTransition('#eb4034', '#40eb34', 0, TTL, ttl)}});
} else {
nodes.update({id: nodeId, color: {background: '#97c2fc'}});
edges.update({id: `${from}->${nodeId}`, color: {color: '#2b7ce9', highlight: '#2b7ce9'}});
}
const neighborsSnapshot = (nodeTable[nodeId]?.outgoing?.slice()) || [];
for (let neighbor of neighborsSnapshot) {
if (neighbor === originNode || neighbor === from) {
continue;
}
queue.push({ nodeId: neighbor, ttl: ttl - 1, from: nodeId });
}
}
}
function routePacket(currentNode, goalNode, packetInfo, first=false) {
stillRouting = true;
const packetId = packetInfo.split('-')[0];
var packetShift = generateRealisticLabel();
let ttl = parseInt(packetInfo.split('-')[2]);
nodes.update({id: currentNode, color: {background: '#97c2fc'}});
nodes.update({id: goalNode, color: {background: '#ff00d9'}});
if (ttl <= 0) {
consoleLog(`Packet ${packetId} TTL expired. Dropping packet.`);
stillRouting = false;
return;
}
if (currentNode === goalNode) {
consoleLog(`Packet ${packetId} reached ${goalNode}.`);
stillRouting = false;
return;
}
if (document.getElementById('showTTL').checked) {
nodes.update({id: currentNode, color: {background: smoothColorTransition('#eb4034', '#40eb34', 0, TTL, ttl)}});
} else {
if (first) {
nodes.update({id: currentNode, color: {background: '#ff00d9'}});
} else {
nodes.update({id: currentNode, color: {background: 'yellow'}});
}
}
ttl--;
const nextNode = nodeTable[currentNode].routingTable[goalNode];
if (nextNode) {
var movingNode = {
id: `${packetId}-${packetShift}-${ttl}-${goalNode}`,
label: packetId + `-${ttl}`,
shape: 'dot',
size: 10,
color: {
background: 'white',
border: 'black'
},
font: {color: document.getElementById('darkMode').checked ? '#e0e0e0' : '#000'}
};
onEdgeEngine.createDotNode(movingNode, currentNode, nextNode);
} else {
consoleLog(`No route found from ${currentNode} to ${goalNode}. Dropping packet.`);
console.log(nodeTable[currentNode].routingTable);
stillRouting = false;
}
}
const markNeighborsAsFailed = (nodeId, from, packetId, visited = new Set()) => { const markNeighborsAsFailed = (nodeId, from, packetId, visited = new Set()) => {
if (visited.has(nodeId)) { if (visited.has(nodeId)) {
return; return;
@@ -492,7 +589,7 @@ function onNodeAdd() {
document.getElementById('addNode').addEventListener('click', function() { document.getElementById('addNode').addEventListener('click', function() {
const nodeId = generateRealisticLabel(); const nodeId = generateRealisticLabel();
nodes.add({id: nodeId, label: nodeId}); nodes.add({id: nodeId, label: nodeId});
nodeTable[nodeId] = {'incoming': [], 'outgoing': [], 'packetCache': []}; nodeTable[nodeId] = {'incoming': [], 'outgoing': [], 'packetCache': [], 'routingTable': {}};
onNodeAdd(); onNodeAdd();
}); });
@@ -503,7 +600,7 @@ network.on('click', function(properties) {
if (document.getElementById('quickPlace').checked) { if (document.getElementById('quickPlace').checked) {
const nodeId = generateRealisticLabel(); const nodeId = generateRealisticLabel();
nodes.add({id: nodeId, label: nodeId, x: properties.pointer.canvas.x, y: properties.pointer.canvas.y}); nodes.add({id: nodeId, label: nodeId, x: properties.pointer.canvas.x, y: properties.pointer.canvas.y});
nodeTable[nodeId] = {'incoming': [], 'outgoing': [], 'packetCache': []}; nodeTable[nodeId] = {'incoming': [], 'outgoing': [], 'packetCache': [], 'routingTable': {}};
onNodeAdd(); onNodeAdd();
} }
}); });
@@ -513,11 +610,12 @@ network.on('doubleClick', function(properties) {
return; return;
} }
if (properties.nodes.length > 0) { if (properties.nodes.length > 0) {
navigator.clipboard.writeText(properties.nodes[0]);
return; return;
} }
const nodeId = generateRealisticLabel(); const nodeId = generateRealisticLabel();
nodes.add({id: nodeId, label: nodeId, x: properties.pointer.canvas.x, y: properties.pointer.canvas.y}); nodes.add({id: nodeId, label: nodeId, x: properties.pointer.canvas.x, y: properties.pointer.canvas.y});
nodeTable[nodeId] = {'incoming': [], 'outgoing': [], 'packetCache': []}; nodeTable[nodeId] = {'incoming': [], 'outgoing': [], 'packetCache': [], 'routingTable': {}};
onNodeAdd(); onNodeAdd();
}); });
@@ -607,8 +705,8 @@ document.getElementById('createRandomGraphConfirm').addEventListener('click', fu
let nodeCounter = 0; let nodeCounter = 0;
const interval = setInterval(() => { const interval = setInterval(() => {
const nodeId = generateRealisticLabel(); const nodeId = generateRealisticLabel();
nodes.add({id: nodeId, label: nodeId, x: Math.random() * 100, y: Math.random() * 100}); nodes.add({id: nodeId, label: nodeId, x: Math.random() * 1000, y: Math.random() * 1000});
nodeTable[nodeId] = {'incoming': [], 'outgoing': [], 'packetCache': []}; nodeTable[nodeId] = {'incoming': [], 'outgoing': [], 'packetCache': [], 'routingTable': {}};
onNodeAdd(); onNodeAdd();
nodeCounter++; nodeCounter++;
if (nodeCounter >= nodeCount) { if (nodeCounter >= nodeCount) {
@@ -646,6 +744,36 @@ document.getElementById('quickPacket').addEventListener('click', async function(
quickPacket(selectedNode, `${packetId}-${packetShift}-${ttl}-${selectedNode}`, selectedNode); quickPacket(selectedNode, `${packetId}-${packetShift}-${ttl}-${selectedNode}`, selectedNode);
}); });
document.getElementById('createRoutingTables').addEventListener('click', function() {
let nodeCounter = 0;
document.getElementById('routingProgressContainer').style.display = 'flex';
document.getElementById('routingProgress').value = 0;
document.getElementById('routingProgress').max = Object.keys(nodeTable).length;
const interval = setInterval(() => {
const packetId = generateRealisticLabel();
var packetShift = generateRealisticLabel();
let ttl = TTL;
const nodeId = Object.keys(nodeTable)[nodeCounter];
quickRoute(nodeId, `${packetId}-${packetShift}-${ttl}-${nodeId}`, nodeId);
nodeCounter++;
document.getElementById('routingProgress').value = nodeCounter;
if (nodeCounter >= Object.keys(nodeTable).length) {
clearInterval(interval);
document.getElementById('routingProgressContainer').style.display = 'none';
document.getElementById('routingProgress').value = 0;
if (displayWarningWhenDone) {
displayWarningWhenDone = false;
document.getElementById('warningModal').style.display = 'block';
document.getElementById('warningModalMessage').innerHTML = 'TTL hit zero while routing, some routes may be missing. If you experience issues, try increasing the TTL and routing again.';
document.getElementById('warningModalCustomContent').innerHTML = '';
} else {
document.getElementById('successModal').style.display = 'block';
document.getElementById('successModalMessage').innerHTML = 'Routing tables created successfully.';
}
}
}, 10);
});
window.onload = function() { window.onload = function() {
if (localStorage.getItem('darkMode') === 'true') { if (localStorage.getItem('darkMode') === 'true') {
document.getElementById('darkMode').checked = true; document.getElementById('darkMode').checked = true;
@@ -654,4 +782,115 @@ window.onload = function() {
document.getElementById('darkMode').checked = false; document.getElementById('darkMode').checked = false;
document.getElementById('styleSheet').href = 'style.css'; document.getElementById('styleSheet').href = 'style.css';
} }
let consoleContainer = document.createElement('div');
consoleContainer.id = 'consoleContainer';
document.getElementById('simContainer').appendChild(consoleContainer);
let openConsoleButton = document.createElement('button');
openConsoleButton.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-terminal-icon lucide-terminal"><path d="M12 19h8"/><path d="m4 17 6-6-6-6"/></svg>';
openConsoleButton.id = 'openConsole';
openConsoleButton.addEventListener('click', function() {
const consoleElement = document.getElementById('consoleContainer');
const currentDisplay = window.getComputedStyle(consoleElement).display;
consoleElement.style.display = currentDisplay === 'none' ? 'flex' : 'none';
});
let consoleInputContainer = document.createElement('div');
consoleInputContainer.id = 'consoleInputContainer';
consoleContainer.appendChild(consoleInputContainer);
let consoleCarrot = document.createElement('pre');
consoleCarrot.innerHTML = '>';
consoleInputContainer.appendChild(consoleCarrot);
let consoleInput = document.createElement('input');
consoleInput.id = 'consoleInput';
consoleInput.placeholder = 'Enter command';
consoleInputContainer.appendChild(consoleInput);
let consoleInputHistory = [];
let consoleInputHistoryIndex = 0;
// Handle Enter key for command execution
consoleInput.addEventListener('keypress', function(event) {
if (event.key === 'Enter') {
const command = consoleInput.value.trim();
if (command) { // Only add non-empty commands to history
consoleInputHistory.push(command);
}
consoleInputHistoryIndex = consoleInputHistory.length;
const rootCommand = command.split(' ')[0];
const args = command.split(' ')[1];
switch (rootCommand) {
case 'help':
switch (args) {
case 'routePacket':
consoleLog('Sends a packet from one specific node to another. Usage: routePacket [startNode]->[endNode]');
break;
case 'exit':
consoleLog('Exits the console');
break;
default:
consoleLog('Available commands: help, routePacket, exit');
break;
}
break;
case 'routePacket':
if (!args) {
consoleLog('Usage: routePacket [startNode]->[endNode]');
break;
}
document.getElementById('resetTTLColors').click();
const packetInfo = `${generateRealisticLabel()}-${generateRealisticLabel()}-${TTL}-${args.split('->')[1]}`;
nodes.update({id: args.split('->')[0], color: {background: '#ff00d9'}});
nodes.update({id: args.split('->')[1], color: {background: '#ff00d9'}});
routePacket(args.split('->')[0], args.split('->')[1], packetInfo, true);
break;
case 'exit':
document.getElementById('consoleContainer').style.display = 'none';
break;
default:
consoleLog(`Unknown command "${rootCommand}"`);
break;
}
consoleInput.value = '';
}
});
// Handle arrow keys for history navigation
consoleInput.addEventListener('keydown', function(event) {
if (event.key === 'ArrowUp') {
event.preventDefault(); // Prevent cursor movement
if (consoleInputHistory.length === 0) return;
if (consoleInputHistoryIndex > 0) {
consoleInputHistoryIndex--;
}
consoleInput.value = consoleInputHistory[consoleInputHistoryIndex] || '';
} else if (event.key === 'ArrowDown') {
event.preventDefault(); // Prevent cursor movement
if (consoleInputHistory.length === 0) return;
consoleInputHistoryIndex++;
if (consoleInputHistoryIndex >= consoleInputHistory.length) {
consoleInputHistoryIndex = consoleInputHistory.length;
consoleInput.value = ''; // Clear input when going beyond history
} else {
consoleInput.value = consoleInputHistory[consoleInputHistoryIndex] || '';
}
}
});
let consoleOutput = document.createElement('pre');
consoleOutput.id = 'consoleOutput';
consoleContainer.appendChild(consoleOutput);
document.getElementById('simContainer').appendChild(openConsoleButton);
}
function consoleLog(message) {
const consoleOutput = document.getElementById('consoleOutput');
consoleOutput.innerHTML = `${message}`;
consoleOutput.scrollTop = consoleOutput.scrollHeight;
} }
+102 -6
View File
@@ -93,7 +93,7 @@ html, body {
gap: 10px; gap: 10px;
} }
#simpleSettingsContent, #engineSettingsContent, #hardwareConstraintsContent { #simpleSettingsContent, #engineSettingsContent, #hardwareConstraintsContent, #visualizationSettingsContent {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 10px; gap: 10px;
@@ -101,21 +101,21 @@ html, body {
padding-top: 10px; padding-top: 10px;
} }
#simpleSettings, #hardwareConstraints, #engineSettings { #simpleSettings, #hardwareConstraints, #engineSettings, #visualizationSettings {
margin-bottom: 10px; margin-bottom: 10px;
} }
#randomGraphModal, #warningModal { #randomGraphModal, #warningModal, #successModal {
display: none; display: none;
position: absolute; position: absolute;
top: 0%; top: 0%;
left: 0%; left: 0%;
transform: translate(0%, 0%); transform: translate(0%, 0%);
background-color: rgba(0, 0, 0, 0.8); background-color: rgba(0, 0, 0, 0.8);
padding: 20px;
border: none; border: none;
width: 100%; width: 100vw;
height: 100%; height: 100vh;
z-index: 100;
} }
#warningModalContent { #warningModalContent {
@@ -131,6 +131,19 @@ html, body {
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.5); box-shadow: 0 4px 20px rgba(0, 0, 0, 0.5);
} }
#successModalContent {
padding: 20px;
background-color: #2d2d2d;
border: 2px solid #00ff00;
border-radius: 8px;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: #e0e0e0;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.5);
}
#randomGraphModalContent { #randomGraphModalContent {
padding: 20px; padding: 20px;
background-color: #2d2d2d; background-color: #2d2d2d;
@@ -144,6 +157,16 @@ html, body {
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.5); box-shadow: 0 4px 20px rgba(0, 0, 0, 0.5);
} }
#createRandomGraphCancel {
margin-top: 10px;
color: white;
border: none;
padding: 8px 16px;
border-radius: 4px;
cursor: pointer;
transition: background-color 0.2s ease;
}
#createRandomGraphConfirm { #createRandomGraphConfirm {
margin-top: 10px; margin-top: 10px;
background-color: #4a9eff; background-color: #4a9eff;
@@ -205,4 +228,77 @@ button:active {
/* Checkbox and radio button styling */ /* Checkbox and radio button styling */
input[type="checkbox"], input[type="radio"] { input[type="checkbox"], input[type="radio"] {
accent-color: #4a9eff; accent-color: #4a9eff;
}
#routingProgressContainer {
display: none;
width: 100%;
flex-direction: column;
align-items: center;
justify-content: center;
}
#routingProgress {
width: 90%;
}
#openConsole {
position: absolute;
top: 10px;
right: 10px;
z-index: 10;
display: flex;
align-items: center;
justify-content: center;
}
#consoleContainer {
position: absolute;
bottom: 0px;
left: 0px;
z-index: 10;
width: 100%;
height: 10%;
background-color: #000000;
border-top: 1px solid #ffffff;
display: none;
flex-direction: column;
align-items: center;
justify-content: center;
padding-left: 10px;
overflow: hidden;
}
#consoleInput {
width: 100%;
height: 100%;
background-color: #000000;
color: #e0e0e0;
border: none;
padding: 10px;
box-sizing: border-box;
}
#consoleInput:focus {
outline: none;
box-shadow: none;
border-color: transparent;
}
#consoleInputContainer {
width: 100%;
height: 50%;
display: flex;
flex-direction: row;
align-items: center;
justify-content: start;
gap: 0px;
}
#consoleOutput {
width: 100%;
height: 50%;
background-color: #000000;
color: #e0e0e0;
} }
+91 -8
View File
@@ -52,7 +52,7 @@ html, body {
position: absolute; position: absolute;
border: 1px solid black; border: 1px solid black;
border-radius: 50%; border-radius: 50%;
z-index: 1000; z-index: 10;
opacity: 0.2; opacity: 0.2;
background-color: red; background-color: red;
pointer-events: none; pointer-events: none;
@@ -73,7 +73,7 @@ html, body {
gap: 10px; gap: 10px;
} }
#simpleSettingsContent, #engineSettingsContent, #hardwareConstraintsContent { #simpleSettingsContent, #engineSettingsContent, #hardwareConstraintsContent, #visualizationSettingsContent {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 10px; gap: 10px;
@@ -81,21 +81,21 @@ html, body {
padding-top: 10px; padding-top: 10px;
} }
#simpleSettings, #hardwareConstraints, #engineSettings { #simpleSettings, #hardwareConstraints, #engineSettings, #visualizationSettings {
margin-bottom: 10px; margin-bottom: 10px;
} }
#randomGraphModal, #warningModal { #randomGraphModal, #warningModal, #successModal {
display: none; display: none;
position: absolute; position: absolute;
top: 0%; top: 0%;
left: 0%; left: 0%;
transform: translate(0%, 0%); transform: translate(0%, 0%);
background-color: rgba(0, 0, 0, 0.5); background-color: rgba(0, 0, 0, 0.5);
padding: 20px;
border: 1px solid #000; border: 1px solid #000;
width: 100%; width: 100vw;
height: 100%; height: 100vh;
z-index: 100;
} }
#warningModalContent { #warningModalContent {
@@ -108,6 +108,16 @@ html, body {
transform: translate(-50%, -50%); transform: translate(-50%, -50%);
} }
#successModalContent {
padding: 20px;
background-color: #fff;
border: 1px solid #00ff00;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
#randomGraphModalContent { #randomGraphModalContent {
padding: 20px; padding: 20px;
background-color: #fff; background-color: #fff;
@@ -118,6 +128,79 @@ html, body {
transform: translate(-50%, -50%); transform: translate(-50%, -50%);
} }
#createRandomGraphConfirm { #createRandomGraphConfirm, #createRandomGraphCancel {
margin-top: 10px; margin-top: 10px;
}
#routingProgressContainer {
display: none;
width: 100%;
flex-direction: column;
align-items: center;
justify-content: center;
}
#routingProgress {
width: 90%;
}
#openConsole {
position: absolute;
top: 10px;
right: 10px;
z-index: 10;
display: flex;
align-items: center;
justify-content: center;
}
#consoleContainer {
position: absolute;
bottom: 0px;
left: 0px;
z-index: 10;
width: 100%;
height: 10%;
background-color: #ffffff;
border-top: 1px solid #000000;
display: none;
flex-direction: column;
align-items: center;
justify-content: center;
padding-left: 10px;
overflow: hidden;
}
#consoleInput {
width: 100%;
height: 100%;
background-color: #ffffff;
color: #000000;
border: none;
padding: 10px;
box-sizing: border-box;
}
#consoleInput:focus {
outline: none;
box-shadow: none;
border-color: transparent;
}
#consoleInputContainer {
width: 100%;
height: 50%;
display: flex;
flex-direction: row;
align-items: center;
justify-content: start;
gap: 0px;
}
#consoleOutput {
width: 100%;
height: 50%;
background-color: #ffffff;
color: #000000;
} }