Newer
Older
TelosDB / src / frontend / index.html
@楽曲作りまくりおじさん 楽曲作りまくりおじさん 5 days ago 6 KB feat: add sidecar status indicator to UI
<!DOCTYPE html>
<html lang="ja">

<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>SQLite Vector MCP Server</title>
    <style>
        body {
            font-family: sans-serif;
            padding: 20px;
        }

        .status {
            color: green;
            font-weight: bold;
        }

        .section {
            margin: 20px 0;
            padding: 15px;
            border: 1px solid #ddd;
            border-radius: 4px;
        }

        .section h3 {
            margin-top: 0;
        }

        code {
            background: #f5f5f5;
            padding: 2px 6px;
            border-radius: 3px;
            font-family: monospace;
        }

        table {
            width: 100%;
            border-collapse: collapse;
        }

        table td {
            padding: 8px;
            border-bottom: 1px solid #eee;
        }

        table td:first-child {
            font-weight: bold;
            width: 150px;
        }

        .json-block {
            background: #f5f5f5;
            padding: 10px;
            border-radius: 4px;
            border: 1px solid #ddd;
            margin: 10px 0;
            position: relative;
        }

        .json-block pre {
            margin: 0;
            overflow-x: auto;
        }

        .copy-btn {
            position: absolute;
            top: 5px;
            right: 5px;
            padding: 5px 10px;
            background: #007bff;
            color: white;
            border: none;
            border-radius: 3px;
            cursor: pointer;
            font-size: 12px;
        }

        .copy-btn:hover {
            background: #0056b3;
        }

        .copy-feedback {
            position: absolute;
            top: 35px;
            right: 5px;
            color: green;
            font-size: 12px;
            display: none;
        }
    </style>
</head>

<body>
    <h1>SQLite Vector MCP Server</h1>
    <p>
        Status: <span id="status" class="status">Loading...</span> |
        Sidecar: <span id="sidecar-status" style="font-weight: bold; color: orange;">Checking...</span> |
        Connected Clients: <span id="conn-count" style="font-weight: bold;">0</span> |
        Stored Items: <span id="item-count" style="font-weight: bold;">0</span>
    </p>

    <div class="section">
        <h3>MCP Configuration</h3>
        <div id="mcp-info">Loading MCP configuration...</div>
    </div>

    <script type="module">
        const { invoke } = window.__TAURI__.core;
        const { listen } = window.__TAURI__.event;

        async function updateDbStats() {
            try {
                const stats = await invoke('get_db_stats');
                document.getElementById('item-count').textContent = stats.itemCount;
            } catch (error) {
                console.error('Failed to update DB stats:', error);
            }
        }

        // Listen for updates
        listen('mcp-connection-update', (event) => {
            document.getElementById('conn-count').textContent = event.payload;
        });

        listen('mcp-db-update', () => {
            updateDbStats();
        });

        // Load MCP info
        async function loadMcpInfo() {
            try {
                updateDbStats();
                updateSidecarStatus();
                const mcpData = await invoke('get_mcp_info');
                displayMcpInfo(mcpData);
                document.getElementById('status').textContent = 'Running ✓';
            } catch (error) {
                console.error('Failed to load MCP info:', error);
                document.getElementById('mcp-info').innerHTML = `<p style="color: red;">Error: ${error}</p>`;
                document.getElementById('status').textContent = 'Error loading MCP info';
            }
        }

        async function updateSidecarStatus() {
            try {
                const isRunning = await invoke('get_sidecar_status');
                const el = document.getElementById('sidecar-status');
                if (isRunning) {
                    el.textContent = 'Running ✓';
                    el.style.color = 'green';
                } else {
                    el.textContent = 'Stopped ✗';
                    el.style.color = 'red';
                }
            } catch (error) {
                console.error('Failed to check sidecar status:', error);
            }
        }

        // Poll sidecar status every 5 seconds
        setInterval(updateSidecarStatus, 5000);

        function displayMcpInfo(mcpData) {
            const mcpInfoDiv = document.getElementById('mcp-info');

            if (!mcpData.mcpServers || Object.keys(mcpData.mcpServers).length === 0) {
                mcpInfoDiv.innerHTML = '<p>No MCP servers configured.</p>';
                return;
            }

            // Create JSON output
            const jsonOutput = {
                mcpServers: mcpData.mcpServers
            };
            const jsonString = JSON.stringify(jsonOutput, null, 2);

            // Create HTML with JSON display and copy button
            let html = '<div class="json-block">';
            html += '<button class="copy-btn" onclick="copyToClipboard(this)">Copy JSON</button>';
            html += '<div class="copy-feedback" style="display:none;">✓ Copied!</div>';
            html += '<pre id="mcp-json">' + escapeHtml(jsonString) + '</pre>';
            html += '</div>';
            html += '<p style="font-size: 12px; color: #666;">Use this JSON configuration in your MCP client settings.</p>';

            mcpInfoDiv.innerHTML = html;
        }

        function escapeHtml(text) {
            const map = {
                '&': '&amp;',
                '<': '&lt;',
                '>': '&gt;',
                '"': '&quot;',
                "'": '&#039;'
            };
            return text.replace(/[&<>"']/g, m => map[m]);
        }

        function copyToClipboard(btn) {
            const jsonElement = document.getElementById('mcp-json');
            const text = jsonElement.textContent;

            navigator.clipboard.writeText(text).then(() => {
                const feedback = btn.nextElementSibling;
                feedback.style.display = 'block';
                setTimeout(() => {
                    feedback.style.display = 'none';
                }, 2000);
            }).catch(err => {
                console.error('Failed to copy:', err);
                alert('コピーに失敗しました');
            });
        }

        // Load on page load
        window.addEventListener('load', loadMcpInfo);
    </script>
</body>

</html>