All checks were successful
Tests / unit-tests (push) Successful in 51s
- Login sa session cookie autentifikacijom - Lista projekata iz filesystem-a - Chat sa Claude CLI preko WebSocket-a - Streaming NDJSON parsiranje iz CLI stdout-a - Sesija zivi nezavisno od browsera (reconnect replay) - Sidebar sa .md fajlovima i markdown renderovanjem - Dark tema, htmx + Go templates - 47 unit testova Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
113 lines
4.2 KiB
HTML
113 lines
4.2 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="sr">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Claude Web Chat — {{.Project}}</title>
|
|
<link rel="stylesheet" href="/static/style.css">
|
|
<script src="/static/htmx.min.js"></script>
|
|
<script src="/static/ws.js"></script>
|
|
</head>
|
|
<body>
|
|
<div class="chat-container">
|
|
<!-- Sidebar -->
|
|
<div class="sidebar">
|
|
<div class="sidebar-header">
|
|
<h3>Fajlovi</h3>
|
|
<a href="/projects" style="font-size:0.85rem;">← Projekti</a>
|
|
</div>
|
|
<div class="sidebar-content" id="file-list">
|
|
{{range .Files}}
|
|
<a class="file-item" href="#" onclick="loadFile('{{.RelPath}}'); return false;">{{.Name}}</a>
|
|
{{end}}
|
|
{{if not .Files}}
|
|
<div style="padding: 1rem; color: var(--text-muted); font-size: 0.85rem;">
|
|
Nema .md fajlova
|
|
</div>
|
|
{{end}}
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Chat main area -->
|
|
<div class="chat-main">
|
|
<div class="chat-header">
|
|
<h2>{{.Project}}</h2>
|
|
<span id="ws-status" class="status">Povezivanje...</span>
|
|
</div>
|
|
|
|
<div class="chat-messages" id="chat-messages">
|
|
<!-- Messages will be appended here via OOB swap -->
|
|
</div>
|
|
|
|
<div id="typing-indicator"></div>
|
|
|
|
<div class="chat-input-area" hx-ext="ws" ws-connect="/ws?project={{.Project}}&project_dir={{.ProjectDir}}">
|
|
<form class="chat-input-form" ws-send>
|
|
<textarea id="message-input" name="message" class="chat-input" placeholder="Pošalji poruku..." rows="1"></textarea>
|
|
<button type="submit" class="btn">Pošalji</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- File viewer overlay (hidden by default) -->
|
|
<div id="file-viewer" class="file-viewer hidden">
|
|
<div class="file-viewer-header">
|
|
<h3 id="file-viewer-title"></h3>
|
|
<button class="btn" onclick="closeFileViewer()">Zatvori</button>
|
|
</div>
|
|
<div class="file-viewer-content" id="file-viewer-content">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
// Auto-resize textarea
|
|
const textarea = document.getElementById('message-input');
|
|
if (textarea) {
|
|
textarea.addEventListener('input', function() {
|
|
this.style.height = 'auto';
|
|
this.style.height = Math.min(this.scrollHeight, 200) + 'px';
|
|
});
|
|
|
|
// Submit on Enter (Shift+Enter for newline)
|
|
textarea.addEventListener('keydown', function(e) {
|
|
if (e.key === 'Enter' && !e.shiftKey) {
|
|
e.preventDefault();
|
|
this.closest('form').dispatchEvent(new Event('submit', { bubbles: true }));
|
|
}
|
|
});
|
|
}
|
|
|
|
// Auto-scroll chat
|
|
const chatMessages = document.getElementById('chat-messages');
|
|
const observer = new MutationObserver(function() {
|
|
chatMessages.scrollTop = chatMessages.scrollHeight;
|
|
});
|
|
observer.observe(chatMessages, { childList: true, subtree: true });
|
|
|
|
// File viewer
|
|
function loadFile(relPath) {
|
|
fetch('/api/file?project={{.Project}}&path=' + encodeURIComponent(relPath))
|
|
.then(r => r.json())
|
|
.then(data => {
|
|
document.getElementById('file-viewer-title').textContent = data.name;
|
|
document.getElementById('file-viewer-content').innerHTML = data.html;
|
|
document.getElementById('file-viewer').classList.remove('hidden');
|
|
})
|
|
.catch(err => console.error('Error loading file:', err));
|
|
}
|
|
|
|
function closeFileViewer() {
|
|
document.getElementById('file-viewer').classList.add('hidden');
|
|
}
|
|
|
|
// Close file viewer with Escape
|
|
document.addEventListener('keydown', function(e) {
|
|
if (e.key === 'Escape') {
|
|
closeFileViewer();
|
|
}
|
|
});
|
|
</script>
|
|
</body>
|
|
</html>
|