@cluesmith/codev 2.0.0-rc.25 → 2.0.0-rc.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/templates/dashboard/index.html +17 -16
- package/templates/tower.html +34 -9
package/package.json
CHANGED
|
@@ -4,15 +4,15 @@
|
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
6
|
<title>AF: {{PROJECT_NAME}}</title>
|
|
7
|
-
<!-- CSS files loaded in dependency order -->
|
|
8
|
-
<link rel="stylesheet" href="
|
|
9
|
-
<link rel="stylesheet" href="
|
|
10
|
-
<link rel="stylesheet" href="
|
|
11
|
-
<link rel="stylesheet" href="
|
|
12
|
-
<link rel="stylesheet" href="
|
|
13
|
-
<link rel="stylesheet" href="
|
|
14
|
-
<link rel="stylesheet" href="
|
|
15
|
-
<link rel="stylesheet" href="
|
|
7
|
+
<!-- CSS files loaded in dependency order (relative paths for proxy compatibility) -->
|
|
8
|
+
<link rel="stylesheet" href="dashboard/css/variables.css">
|
|
9
|
+
<link rel="stylesheet" href="dashboard/css/layout.css">
|
|
10
|
+
<link rel="stylesheet" href="dashboard/css/tabs.css">
|
|
11
|
+
<link rel="stylesheet" href="dashboard/css/statusbar.css">
|
|
12
|
+
<link rel="stylesheet" href="dashboard/css/dialogs.css">
|
|
13
|
+
<link rel="stylesheet" href="dashboard/css/projects.css">
|
|
14
|
+
<link rel="stylesheet" href="dashboard/css/files.css">
|
|
15
|
+
<link rel="stylesheet" href="dashboard/css/utilities.css">
|
|
16
16
|
</head>
|
|
17
17
|
<body>
|
|
18
18
|
<header class="header">
|
|
@@ -137,12 +137,13 @@
|
|
|
137
137
|
</script>
|
|
138
138
|
|
|
139
139
|
<!-- JavaScript files loaded in dependency order -->
|
|
140
|
-
|
|
141
|
-
<script src="
|
|
142
|
-
<script src="
|
|
143
|
-
<script src="
|
|
144
|
-
<script src="
|
|
145
|
-
<script src="
|
|
146
|
-
<script src="
|
|
140
|
+
<!-- JS files (relative paths for proxy compatibility) -->
|
|
141
|
+
<script src="dashboard/js/state.js"></script>
|
|
142
|
+
<script src="dashboard/js/utils.js"></script>
|
|
143
|
+
<script src="dashboard/js/tabs.js"></script>
|
|
144
|
+
<script src="dashboard/js/dialogs.js"></script>
|
|
145
|
+
<script src="dashboard/js/projects.js"></script>
|
|
146
|
+
<script src="dashboard/js/files.js"></script>
|
|
147
|
+
<script src="dashboard/js/main.js"></script>
|
|
147
148
|
</body>
|
|
148
149
|
</html>
|
package/templates/tower.html
CHANGED
|
@@ -1125,15 +1125,14 @@
|
|
|
1125
1125
|
const statusText = instance.running ? 'Running' : 'Stopped';
|
|
1126
1126
|
const hasGate = instance.gateStatus?.hasGate;
|
|
1127
1127
|
|
|
1128
|
-
const
|
|
1129
|
-
// Use proxy URL
|
|
1128
|
+
const terminalsHtml = instance.ports.map(port => {
|
|
1129
|
+
// Use proxy URL - works both locally and through tunnel
|
|
1130
1130
|
const proxyUrl = getProxyUrl(instance, port.type);
|
|
1131
1131
|
return `
|
|
1132
1132
|
<div class="port-item">
|
|
1133
1133
|
<div class="port-info">
|
|
1134
1134
|
<span class="port-status ${port.active ? 'active' : 'inactive'}"></span>
|
|
1135
1135
|
<span class="port-type">${escapeHtml(port.type)}</span>
|
|
1136
|
-
<span class="port-url">Port ${port.port}</span>
|
|
1137
1136
|
</div>
|
|
1138
1137
|
<div class="port-actions">
|
|
1139
1138
|
<a href="${escapeHtml(proxyUrl)}" target="_blank" class="${port.active ? '' : 'disabled'}">
|
|
@@ -1184,11 +1183,10 @@
|
|
|
1184
1183
|
</div>
|
|
1185
1184
|
<div class="instance-body">
|
|
1186
1185
|
<div class="ports-list">
|
|
1187
|
-
${
|
|
1186
|
+
${terminalsHtml}
|
|
1188
1187
|
</div>
|
|
1189
1188
|
<div class="instance-meta">
|
|
1190
1189
|
<span>Last active: ${lastUsed}</span>
|
|
1191
|
-
<span>Port block: ${instance.basePort}-${instance.basePort + 99}</span>
|
|
1192
1190
|
</div>
|
|
1193
1191
|
</div>
|
|
1194
1192
|
</div>
|
|
@@ -1537,18 +1535,31 @@
|
|
|
1537
1535
|
}
|
|
1538
1536
|
|
|
1539
1537
|
// Share dialog functions (QR code for mobile access)
|
|
1538
|
+
let tunnelAbortController = null;
|
|
1539
|
+
|
|
1540
1540
|
async function showShareDialog() {
|
|
1541
1541
|
const dialog = document.getElementById('share-dialog');
|
|
1542
1542
|
const content = document.getElementById('share-content');
|
|
1543
1543
|
const stopBtn = document.getElementById('stop-tunnel-btn');
|
|
1544
1544
|
|
|
1545
1545
|
dialog.style.display = 'flex';
|
|
1546
|
-
content.innerHTML = '<div class="loading"><div class="spinner"></div><p>Starting tunnel...</p></div>';
|
|
1547
1546
|
stopBtn.style.display = 'none';
|
|
1548
1547
|
|
|
1548
|
+
// Create abort controller for cancellation
|
|
1549
|
+
tunnelAbortController = new AbortController();
|
|
1550
|
+
|
|
1551
|
+
content.innerHTML = `
|
|
1552
|
+
<div class="loading">
|
|
1553
|
+
<div class="spinner"></div>
|
|
1554
|
+
<p>Starting tunnel...</p>
|
|
1555
|
+
<p style="font-size: 12px; color: var(--muted); margin-top: 8px;">This may take up to 30 seconds</p>
|
|
1556
|
+
<button class="btn" style="margin-top: 16px;" onclick="cancelTunnelStart()">Cancel</button>
|
|
1557
|
+
</div>
|
|
1558
|
+
`;
|
|
1559
|
+
|
|
1549
1560
|
try {
|
|
1550
1561
|
// Check if tunnel is already running
|
|
1551
|
-
const statusRes = await fetch('/api/tunnel/status');
|
|
1562
|
+
const statusRes = await fetch('/api/tunnel/status', { signal: tunnelAbortController.signal });
|
|
1552
1563
|
const status = await statusRes.json();
|
|
1553
1564
|
|
|
1554
1565
|
if (status.running && status.url) {
|
|
@@ -1557,7 +1568,7 @@
|
|
|
1557
1568
|
}
|
|
1558
1569
|
|
|
1559
1570
|
// Start tunnel
|
|
1560
|
-
const res = await fetch('/api/tunnel/start', { method: 'POST' });
|
|
1571
|
+
const res = await fetch('/api/tunnel/start', { method: 'POST', signal: tunnelAbortController.signal });
|
|
1561
1572
|
const result = await res.json();
|
|
1562
1573
|
|
|
1563
1574
|
if (result.success && result.url) {
|
|
@@ -1566,8 +1577,22 @@
|
|
|
1566
1577
|
content.innerHTML = `<p style="color: var(--danger);">Failed to start tunnel: ${result.error || 'Unknown error'}</p>`;
|
|
1567
1578
|
}
|
|
1568
1579
|
} catch (e) {
|
|
1569
|
-
|
|
1580
|
+
if (e.name === 'AbortError') {
|
|
1581
|
+
content.innerHTML = '<p>Tunnel start cancelled.</p>';
|
|
1582
|
+
} else {
|
|
1583
|
+
content.innerHTML = `<p style="color: var(--danger);">Error: ${e.message}</p>`;
|
|
1584
|
+
}
|
|
1585
|
+
} finally {
|
|
1586
|
+
tunnelAbortController = null;
|
|
1587
|
+
}
|
|
1588
|
+
}
|
|
1589
|
+
|
|
1590
|
+
function cancelTunnelStart() {
|
|
1591
|
+
if (tunnelAbortController) {
|
|
1592
|
+
tunnelAbortController.abort();
|
|
1570
1593
|
}
|
|
1594
|
+
// Also stop any tunnel that might have started
|
|
1595
|
+
fetch('/api/tunnel/stop', { method: 'POST' }).catch(() => {});
|
|
1571
1596
|
}
|
|
1572
1597
|
|
|
1573
1598
|
function showQRCode(tunnelUrl) {
|