+77
-82
@@ -69,14 +69,7 @@ async function performLogin(authToken) {
|
|||||||
if (data.role === 'admin') document.getElementById('settingsBtn').classList.remove('d-none');
|
if (data.role === 'admin') document.getElementById('settingsBtn').classList.remove('d-none');
|
||||||
document.getElementById('loginOverlay').style.display = 'none';
|
document.getElementById('loginOverlay').style.display = 'none';
|
||||||
window.history.replaceState({}, '', '/');
|
window.history.replaceState({}, '', '/');
|
||||||
// Init canvas if not already
|
initApp();
|
||||||
if (!canvas) {
|
|
||||||
canvas = document.getElementById('networkCanvas');
|
|
||||||
ctx = canvas.getContext('2d');
|
|
||||||
resizeCanvas();
|
|
||||||
}
|
|
||||||
loadTeams().then(() => loadEvents());
|
|
||||||
loadNetworkData();
|
|
||||||
} else {
|
} else {
|
||||||
errEl.textContent = data.error || 'Login failed';
|
errEl.textContent = data.error || 'Login failed';
|
||||||
errEl.style.display = 'block';
|
errEl.style.display = 'block';
|
||||||
@@ -111,83 +104,85 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
if (btn) btn.textContent = 'Authenticating...';
|
if (btn) btn.textContent = 'Authenticating...';
|
||||||
performLogin(authToken);
|
performLogin(authToken);
|
||||||
} else {
|
} else {
|
||||||
checkSession().then(() => {
|
checkSession().then(initApp).catch(() => {});
|
||||||
canvas = document.getElementById('networkCanvas');
|
|
||||||
ctx = canvas.getContext('2d');
|
|
||||||
resizeCanvas();
|
|
||||||
|
|
||||||
loadTeams().then(() => loadEvents());
|
|
||||||
loadNetworkData();
|
|
||||||
|
|
||||||
document.getElementById('saveEvent').addEventListener('click', saveEvent);
|
|
||||||
document.getElementById('saveNode').addEventListener('click', saveNode);
|
|
||||||
document.getElementById('saveLink').addEventListener('click', saveLink);
|
|
||||||
document.getElementById('saveShape').addEventListener('click', saveShape);
|
|
||||||
document.getElementById('addUserBtn').addEventListener('click', addUser);
|
|
||||||
document.getElementById('logoutBtn').addEventListener('click', logout);
|
|
||||||
document.getElementById('teamFilter').addEventListener('change', renderTimeline);
|
|
||||||
document.getElementById('searchEvents').addEventListener('input', renderTimeline);
|
|
||||||
document.getElementById('shapeOpacity').addEventListener('input', (e) => {
|
|
||||||
document.getElementById('opacityVal').textContent = parseFloat(e.target.value).toFixed(2);
|
|
||||||
});
|
|
||||||
|
|
||||||
canvas.addEventListener('mousedown', onMouseDown);
|
|
||||||
canvas.addEventListener('mousemove', onMouseMove);
|
|
||||||
canvas.addEventListener('mouseup', onMouseUp);
|
|
||||||
canvas.addEventListener('dblclick', onDblClick);
|
|
||||||
canvas.addEventListener('contextmenu', (e) => e.preventDefault());
|
|
||||||
window.addEventListener('resize', () => { resizeCanvas(); renderNetwork(); });
|
|
||||||
|
|
||||||
document.addEventListener('keydown', (e) => {
|
|
||||||
if ((e.ctrlKey || e.metaKey) && e.key === 'c') {
|
|
||||||
if (!document.activeElement || document.activeElement.tagName !== 'INPUT') {
|
|
||||||
if (selectedNodeId) copyNode(selectedNodeId);
|
|
||||||
else if (selectedShapeId) copyShape(selectedShapeId);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if ((e.ctrlKey || e.metaKey) && e.key === 'v') {
|
|
||||||
if (!document.activeElement || document.activeElement.tagName !== 'INPUT') {
|
|
||||||
if (copyBuffer) pasteItem();
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if ((e.ctrlKey || e.metaKey) && e.key === 'a') {
|
|
||||||
if (!document.activeElement || document.activeElement.tagName !== 'INPUT') {
|
|
||||||
e.preventDefault();
|
|
||||||
selectedNodeIds = canvasNodes.map(n => n.id);
|
|
||||||
selectedNodeId = selectedNodeIds.length > 0 ? selectedNodeIds[0] : null;
|
|
||||||
selectedShapeId = null;
|
|
||||||
renderNodeList(); renderShapeList(); renderNetwork();
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (e.key === 'Delete') {
|
|
||||||
if (!document.activeElement || document.activeElement.tagName !== 'INPUT') {
|
|
||||||
if (selectedNodeIds.length > 0) deleteSelectedNodes();
|
|
||||||
else if (selectedShapeId) deleteSelectedShape(selectedShapeId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (e.key === 'Escape') {
|
|
||||||
selectedNodeId = null; selectedNodeIds = [];
|
|
||||||
selectedShapeId = null;
|
|
||||||
renderNetwork();
|
|
||||||
renderNodeList();
|
|
||||||
renderShapeList();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
document.querySelectorAll('[data-bs-toggle="tab"]').forEach(tab => {
|
|
||||||
tab.addEventListener('shown.bs.tab', () => {
|
|
||||||
if (tab.id === 'network-tab') { resizeCanvas(); renderNetwork(); }
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
document.documentElement.setAttribute('data-bs-theme', 'dark');
|
|
||||||
}).catch(() => {});
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function initApp() {
|
||||||
|
canvas = document.getElementById('networkCanvas');
|
||||||
|
ctx = canvas.getContext('2d');
|
||||||
|
resizeCanvas();
|
||||||
|
|
||||||
|
loadTeams().then(() => loadEvents());
|
||||||
|
loadNetworkData();
|
||||||
|
|
||||||
|
document.getElementById('saveEvent').addEventListener('click', saveEvent);
|
||||||
|
document.getElementById('saveNode').addEventListener('click', saveNode);
|
||||||
|
document.getElementById('saveLink').addEventListener('click', saveLink);
|
||||||
|
document.getElementById('saveShape').addEventListener('click', saveShape);
|
||||||
|
document.getElementById('addUserBtn').addEventListener('click', addUser);
|
||||||
|
document.getElementById('logoutBtn').addEventListener('click', logout);
|
||||||
|
document.getElementById('teamFilter').addEventListener('change', renderTimeline);
|
||||||
|
document.getElementById('searchEvents').addEventListener('input', renderTimeline);
|
||||||
|
document.getElementById('shapeOpacity').addEventListener('input', (e) => {
|
||||||
|
document.getElementById('opacityVal').textContent = parseFloat(e.target.value).toFixed(2);
|
||||||
|
});
|
||||||
|
|
||||||
|
canvas.addEventListener('mousedown', onMouseDown);
|
||||||
|
canvas.addEventListener('mousemove', onMouseMove);
|
||||||
|
canvas.addEventListener('mouseup', onMouseUp);
|
||||||
|
canvas.addEventListener('dblclick', onDblClick);
|
||||||
|
canvas.addEventListener('contextmenu', (e) => e.preventDefault());
|
||||||
|
window.addEventListener('resize', () => { resizeCanvas(); renderNetwork(); });
|
||||||
|
|
||||||
|
document.addEventListener('keydown', (e) => {
|
||||||
|
if ((e.ctrlKey || e.metaKey) && e.key === 'c') {
|
||||||
|
if (!document.activeElement || document.activeElement.tagName !== 'INPUT') {
|
||||||
|
if (selectedNodeId) copyNode(selectedNodeId);
|
||||||
|
else if (selectedShapeId) copyShape(selectedShapeId);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ((e.ctrlKey || e.metaKey) && e.key === 'v') {
|
||||||
|
if (!document.activeElement || document.activeElement.tagName !== 'INPUT') {
|
||||||
|
if (copyBuffer) pasteItem();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ((e.ctrlKey || e.metaKey) && e.key === 'a') {
|
||||||
|
if (!document.activeElement || document.activeElement.tagName !== 'INPUT') {
|
||||||
|
e.preventDefault();
|
||||||
|
selectedNodeIds = canvasNodes.map(n => n.id);
|
||||||
|
selectedNodeId = selectedNodeIds.length > 0 ? selectedNodeIds[0] : null;
|
||||||
|
selectedShapeId = null;
|
||||||
|
renderNodeList(); renderShapeList(); renderNetwork();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (e.key === 'Delete') {
|
||||||
|
if (!document.activeElement || document.activeElement.tagName !== 'INPUT') {
|
||||||
|
if (selectedNodeIds.length > 0) deleteSelectedNodes();
|
||||||
|
else if (selectedShapeId) deleteSelectedShape(selectedShapeId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (e.key === 'Escape') {
|
||||||
|
selectedNodeId = null; selectedNodeIds = [];
|
||||||
|
selectedShapeId = null;
|
||||||
|
renderNetwork();
|
||||||
|
renderNodeList();
|
||||||
|
renderShapeList();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
document.querySelectorAll('[data-bs-toggle="tab"]').forEach(tab => {
|
||||||
|
tab.addEventListener('shown.bs.tab', () => {
|
||||||
|
if (tab.id === 'network-tab') { resizeCanvas(); renderNetwork(); }
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
document.documentElement.setAttribute('data-bs-theme', 'dark');
|
||||||
|
}
|
||||||
|
|
||||||
function resizeCanvas() {
|
function resizeCanvas() {
|
||||||
const wrapper = document.getElementById('networkCanvasWrapper');
|
const wrapper = document.getElementById('networkCanvasWrapper');
|
||||||
canvas.width = wrapper.clientWidth;
|
canvas.width = wrapper.clientWidth;
|
||||||
|
|||||||
Reference in New Issue
Block a user