Browse Source

add connection tls, connection modal

pull/1/head
Stephanie Gredell 7 months ago
parent
commit
32ce500588
  1. 4
      static/app.js
  2. 104
      static/connection.js
  3. 74
      static/game.html

4
static/app.js

@ -9,6 +9,7 @@ export class CanvasApp {
this.componentSize = { width: 120, height: 40 }; this.componentSize = { width: 120, height: 40 };
this.arrowMode = false; this.arrowMode = false;
this.connectionStart = null; this.connectionStart = null;
this.pendingConnection = null;
this.activeNode = null; this.activeNode = null;
this.selectedConnection = null; this.selectedConnection = null;
@ -216,7 +217,8 @@ export class CanvasApp {
target: c.end.id, target: c.end.id,
label: c.label || '', label: c.label || '',
direction: c.direction, direction: c.direction,
protocol: c.protocol || '' protocol: c.protocol || '',
tls: !!c.tls
})); }));
return { nodes, connections }; return { nodes, connections };

104
static/connection.js

@ -1,22 +1,25 @@
import { generateNodeId, createSVGElement } from './utils.js'; import { generateNodeId, createSVGElement } from './utils.js';
export class Connection { export class Connection {
constructor(startNode, endNode, label, protocol, app) { static _activeConnection = null;
static modalSetupDone = false;
constructor(startNode, endNode, label, protocol, app, tls) {
this.start = startNode; this.start = startNode;
this.end = endNode; this.end = endNode;
this.app = app; this.app = app;
this.label = label; this.label = label;
this.protocol = protocol; this.protocol = protocol;
this.direction = "forward"; this.direction = "forward";
this.tls = tls;
this.line = createSVGElement('line', { this.line = createSVGElement('line', {
stroke: '#ccc', 'stroke-width': 2, 'marker-end': 'url(#arrowhead)' stroke: '#ccc', 'stroke-width': 2, 'marker-end': 'url(#arrowhead-end)'
}); });
this.hitbox = createSVGElement('circle', { this.hitbox = createSVGElement('circle', {
r: 12, r: 12,
fill: 'transparent', fill: 'transparent',
cursor: 'pointer', cursor: 'pointer',
}); });
this.app.canvas.appendChild(this.hitbox);
this.text = createSVGElement('text', { this.text = createSVGElement('text', {
'text-anchor': 'middle', 'font-size': 12, fill: '#ccc' 'text-anchor': 'middle', 'font-size': 12, fill: '#ccc'
}); });
@ -30,6 +33,8 @@ export class Connection {
app.canvas.appendChild(this.line); app.canvas.appendChild(this.line);
app.canvas.appendChild(this.text); app.canvas.appendChild(this.text);
app.canvas.appendChild(this.protocolText) app.canvas.appendChild(this.protocolText)
app.canvas.appendChild(this.hitbox);
this.updatePosition(); this.updatePosition();
this.selected = false; this.selected = false;
@ -42,7 +47,17 @@ export class Connection {
this.line.addEventListener('dblclick', (e) => { this.line.addEventListener('dblclick', (e) => {
e.stopPropagation(); e.stopPropagation();
this.toggleDirection(); this.toggleDirection();
}) });
this.text.addEventListener('dblclick', (e) => {
e.stopPropagation();
this.openEditModal()
});
this.protocolText.addEventListener('click', (e) => {
e.stopPropagation();
this.openEditModal();
});
} }
updatePosition() { updatePosition() {
@ -114,7 +129,63 @@ export class Connection {
this.line.setAttribute('stroke-width', 2); this.line.setAttribute('stroke-width', 2);
} }
static setupModal(app) {
if (Connection.modalSetupDone) return;
Connection.modalSetupDone = true;
Connection.modal = document.getElementById('connection-modal');
Connection.labelInput = document.getElementById('connection-label');
Connection.tlsCheckbox = document.getElementById('connection-tls');
Connection.protocolInput = document.getElementById('connection-protocol');
Connection.saveBtn = document.getElementById('connection-save');
Connection.cancelBtn = document.getElementById('connection-cancel');
Connection.saveBtn.addEventListener('click', () => {
const label = Connection.labelInput.value.trim();
const protocol = Connection.protocolInput.value.trim();
const tls = Connection.tlsCheckbox.checked;
if (!label || !protocol) return;
if (Connection._activeConnection) {
// Editing an existing connection
const conn = Connection._activeConnection;
conn.label = label;
conn.protocol = protocol;
conn.text.textContent = label;
conn.tls = tls;
conn.protocolText.textContent = protocol;
conn.updatePosition();
} else if (app.pendingConnection) {
// Creating a new connection
const { start, end } = app.pendingConnection;
const conn = new Connection(start, end, label, protocol, app, tls);
app.connections.push(conn);
}
Connection.modal.style.display = 'none';
app.pendingConnection = null;
Connection._activeConnection = null;
if (app.connectionStart) {
app.connectionStart.group.classList.remove('selected');
app.connectionStart = null;
}
});
Connection.cancelBtn.addEventListener('click', () => {
Connection.modal.style.display = 'none';
app.pendingConnection = null;
if (app.connectionStart) {
app.connectionStart.group.classList.remove('selected');
app.connectionStart = null;
}
});
}
static handleClick(nodeObj, app) { static handleClick(nodeObj, app) {
Connection.setupModal(app);
if (!app.connectionStart) { if (!app.connectionStart) {
app.connectionStart = nodeObj; app.connectionStart = nodeObj;
nodeObj.group.classList.add('selected'); nodeObj.group.classList.add('selected');
@ -122,15 +193,22 @@ export class Connection {
app.connectionStart.group.classList.remove('selected'); app.connectionStart.group.classList.remove('selected');
app.connectionStart = null; app.connectionStart = null;
} else { } else {
const defaultLabel = 'Read traffic'; app.pendingConnection = { start: app.connectionStart, end: nodeObj };
const label = prompt('Enter connection label:', defaultLabel); Connection.labelInput.value = 'Read traffic';
const protocol = prompt('Protocol (e.g. HTTP, gRPC, Kafka):', 'HTTP'); Connection.protocolInput.value = 'HTTP';
if (label && protocol) { Connection.tlsCheckbox.checked = false;
const conn = new Connection(app.connectionStart, nodeObj, label, protocol, app); Connection.modal.style.display = 'block';
app.connections.push(conn);
}
app.connectionStart.group.classList.remove('selected');
app.connectionStart = null;
} }
} }
openEditModal() {
Connection.setupModal(this.app);
Connection._activeConnection = this;
Connection.labelInput.value = this.label;
Connection.protocolInput.value = this.protocol;
Connection.tlsCheckbox.checked = this.tls;
Connection.modal.style.display = 'block';
}
} }

74
static/game.html

@ -483,6 +483,46 @@
position: absolute; position: absolute;
left: 0; left: 0;
} }
.modal {
position: absolute;
top: 30%;
left: 50%;
transform: translate(-50%, -30%);
background: #121212;
padding: 20px;
border-radius: 8px;
border: 1px solid #444;
z-index: 999;
color: #ccc;
}
.modal-content label {
display: block;
margin: 10px 0;
}
.modal-actions {
margin-top: 10px;
text-align: right;
}
.modal input {
width: 100%;
padding: 6px;
margin-top: 4px;
background: #222;
border: 1px solid #444;
color: #fff;
border-radius: 4px;
}
.modal select {
width: 100%;
padding: 6px;
margin-top: 4px;
background: #222;
border: 1px solid #444;
color: #fff;
border-radius: 4px;
}
</style> </style>
</head> </head>
<body> <body>
@ -613,6 +653,40 @@
</div> </div>
<div id="canvas-container"> <div id="canvas-container">
<div id="connection-modal" style="display: none;" class="modal">
<div class="modal-content">
<h3>Create Connection</h3>
<label>
Label:
<input type="text" id="connection-label" value="Read traffic">
</label>
<label>
Protocol:
<select id="connection-protocol">
<option>HTTP</option>
<option>HTTPS</option>
<option>gRPC</option>
<option>WebSocket</option>
<option>GraphQL</option>
<option>Kafka</option>
<option>AMQP</option>
<option>MQTT</option>
<option>SQL</option>
<option>NoSQL</option>
<option>Redis</option>
<option>TLS</option>
</select>
</label>
<label style="margin-top: 10px;">
<input type="checkbox" id="connection-tls">
Enable TLS (encryption)
</label>
<div class="modal-actions">
<button id="connection-save">Save</button>
<button id="connection-cancel">Cancel</button>
</div>
</div>
</div>
<div id="canvas-toolbar"> <div id="canvas-toolbar">
<button id="arrow-tool-btn" class="toolbar-btn">Arrow Tool</button> <button id="arrow-tool-btn" class="toolbar-btn">Arrow Tool</button>
</div> </div>

Loading…
Cancel
Save