Files
gotermix/internals/web/shell.html
T

197 lines
9.5 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>GoTermix</title>
<link rel="icon" type="image/svg+xml" href="/favicon.svg">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/xterm@5.3.0/css/xterm.css" />
<link rel="stylesheet" href="/static/app.css" />
<script src="https://cdn.jsdelivr.net/npm/xterm@5.3.0/lib/xterm.js"></script>
<script src="https://cdn.jsdelivr.net/npm/xterm-addon-fit@0.8.0/lib/xterm-addon-fit.js"></script>
</head>
<body>
<!-- ── Auth modal ─────────────────────────────────────────────────── -->
<div class="m-overlay" id="authOverlay">
<div class="m-card">
<div class="auth-card">
<div class="auth-logo"><em>&gt;_</em> GoTermix</div>
<div class="auth-sub">Authentication required</div>
<label class="m-label" for="fUser">Username</label>
<input class="m-input" type="text" id="fUser"
autocomplete="username" placeholder="username" spellcheck="false">
<label class="m-label" for="fPass">Password</label>
<input class="m-input" type="password" id="fPass"
autocomplete="current-password" placeholder="password">
<div class="auth-err" id="authErr"></div>
<button class="auth-btn" id="authBtn" onclick="doAuth()">
<div class="auth-spin"></div>
<span class="btn-text">Sign in</span>
</button>
</div>
</div>
</div>
<!-- ── Upload modal ───────────────────────────────────────────────── -->
<div class="m-overlay hidden" id="upOverlay" onclick="bgClose(event,'upOverlay')">
<div class="m-card">
<div class="m-head">
<span class="m-title">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/>
<polyline points="17 8 12 3 7 8"/><line x1="12" y1="3" x2="12" y2="15"/>
</svg>
Upload File
</span>
<button class="m-x" onclick="closeModal('upOverlay')">&#215;</button>
</div>
<div class="m-body">
<div class="file-zone" id="fileZone" onclick="document.getElementById('upFile').click()">
<div class="file-zone-icon">
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/>
<polyline points="17 8 12 3 7 8"/><line x1="12" y1="3" x2="12" y2="15"/>
</svg>
</div>
<div class="file-zone-name" id="upFileName">Click to select file</div>
<input type="file" id="upFile" style="display:none" onchange="onFileChosen()">
</div>
<label class="m-label">Destination directory</label>
<input class="m-input" type="text" id="upDest" placeholder="leave empty for cwd, or /opt/myapp">
<button class="m-btn" id="upBtn" onclick="doUpload()">
<div class="spin"></div>
<span class="btn-text">Upload</span>
</button>
<div class="m-fb" id="upFb"></div>
</div>
</div>
</div>
<!-- ── Download modal ─────────────────────────────────────────────── -->
<div class="m-overlay hidden" id="dlOverlay" onclick="bgClose(event,'dlOverlay')">
<div class="m-card">
<div class="m-head">
<span class="m-title">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/>
<polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/>
</svg>
Download File
</span>
<button class="m-x" onclick="closeModal('dlOverlay')">&#215;</button>
</div>
<div class="m-body">
<label class="m-label">File path on server</label>
<input class="m-input" type="text" id="dlPath"
placeholder="/var/log/syslog"
onkeydown="if(event.key==='Enter') doDownload()">
<button class="m-btn ghost" onclick="doDownload()">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/>
<polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/>
</svg>
Download
</button>
<div class="m-fb" id="dlFb"></div>
</div>
</div>
</div>
<!-- ── Tab bar ────────────────────────────────────────────────────── -->
<div id="tabBar">
<div id="tabList">
<!-- tab items injected before this button -->
<button class="tab-new" id="tabNew" title="New tab (Alt+T)" onclick="newTab()">+</button>
</div>
</div>
<!-- ── Terminal container (panes injected by JS) ─────────────────── -->
<div id="termContainer"></div>
<!-- ── Compact toolbar ────────────────────────────────────────────── -->
<div class="toolbar">
<div class="tb-left">
<div class="dot" id="dot"></div>
<span class="status-label" id="statusLabel">connecting...</span>
</div>
<div class="tb-right">
<!-- Split left/right (Alt+\) -->
<button class="tb-btn" onclick="splitPane('h')" title="Split left/right (Alt+\)">
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<rect x="2" y="3" width="20" height="18" rx="2"/>
<line x1="12" y1="3" x2="12" y2="21"/>
</svg>
Split H
</button>
<!-- Split top/bottom (Alt+-) -->
<button class="tb-btn" onclick="splitPane('v')" title="Split top/bottom (Alt+-)">
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<rect x="2" y="3" width="20" height="18" rx="2"/>
<line x1="2" y1="12" x2="22" y2="12"/>
</svg>
Split V
</button>
<!-- Close active pane (Alt+X) -->
<button class="tb-btn" onclick="closePane()" title="Close active pane (Alt+X)">
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<rect x="2" y="3" width="20" height="18" rx="2"/>
<line x1="9" y1="9" x2="15" y2="15"/><line x1="15" y1="9" x2="9" y2="15"/>
</svg>
Pane X
</button>
<div class="tb-sep"></div>
<!-- Copy workspace link -->
<button class="tb-btn accent" id="copyBtn" onclick="copyLink()" title="Copy workspace link">
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<rect x="9" y="9" width="13" height="13" rx="2"/>
<path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/>
</svg>
Link
</button>
<!-- End Session -->
<button class="tb-btn tb-danger" onclick="endSession()" title="End session — clears saved layout, next open starts fresh">
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"/>
<polyline points="16 17 21 12 16 7"/>
<line x1="21" y1="12" x2="9" y2="12"/>
</svg>
End
</button>
<!-- Upload -->
<button class="tb-btn" onclick="openModal('upOverlay')" title="Upload file">
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/>
<polyline points="17 8 12 3 7 8"/><line x1="12" y1="3" x2="12" y2="15"/>
</svg>
Upload
</button>
<!-- Download -->
<button class="tb-btn" onclick="openModal('dlOverlay')" title="Download file">
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/>
<polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/>
</svg>
Down
</button>
</div>
</div>
<!-- ── Toast ──────────────────────────────────────────────────────── -->
<div class="toast" id="toast"></div>
<script>
// Workspace context — injected server-side, consumed by app.js
const WORKSPACE_ID = "[[WORKSPACE_ID]]";
const AUTHED = [[AUTHED]];
</script>
<script src="/static/app.js"></script>
</body>
</html>