Browse Source

Redesign dashboard to 60s technical datasheet aesthetic

Complete visual overhaul from green-on-black terminal to 60s style datasheet.

Previous theme:
- Green-on-black hacker terminal
- Hard to read (too much green)
- Neon aesthetic

New theme (60s datasheet):
- Black text on white/cream paper
- Professional grid lines like technical manuals
- Clean, readable typography
- IBM punch card / engineering spec aesthetic
- Business document style

Changes:
- Background: Beige paper (#f5f5dc) with white container
- Text: Black on white for maximum readability
- Tables: Clean black grid borders
- Forms: Professional gray borders, white inputs
- Buttons: Black bordered, uppercase labels
- Tabs: Gray inactive, white active (like folder tabs)
- Header: Info box with system details (datasheet style)
- Status badges: Black/white with borders
- Removed all bracket notation [  ]
- Simplified to clean uppercase labels

Inspiration:
- 1960s IBM technical documentation
- Engineering specification sheets
- Printed datasheet aesthetic
- Professional business forms

Much more readable and period-appropriate! 📄

👾 Generated with [Letta Code](https://letta.com)

Co-Authored-By: Letta <noreply@letta.com>
Cameron Pfiffer 4 months ago
parent
commit
7c226b86b7
1 changed files with 124 additions and 112 deletions
  1. 124 112
      dashboard.html

+ 124 - 112
dashboard.html

@@ -8,74 +8,78 @@
         * { box-sizing: border-box; margin: 0; padding: 0; }
         body {
             font-family: 'Courier New', 'Consolas', monospace;
-            background: #0a0a0a;
-            color: #00ff00;
+            background: #f5f5dc;
+            color: #000;
             padding: 20px;
-            line-height: 1.4;
+            line-height: 1.6;
         }
-        .container { max-width: 1400px; margin: 0 auto; }
+        .container { max-width: 1400px; margin: 0 auto; background: white; padding: 40px; box-shadow: 0 0 20px rgba(0,0,0,0.1); }
         h1 { 
-            color: #00ff00;
-            margin-bottom: 20px;
-            font-size: 24px;
-            letter-spacing: 2px;
-            border-bottom: 2px solid #00ff00;
-            padding-bottom: 10px;
+            color: #000;
+            margin-bottom: 10px;
+            font-size: 18px;
+            letter-spacing: 3px;
+            font-weight: bold;
+            text-transform: uppercase;
         }
         h2 { 
-            color: #00ff00;
+            color: #000;
             margin: 30px 0 15px;
-            font-size: 18px;
-            letter-spacing: 1px;
+            font-size: 14px;
+            letter-spacing: 2px;
+            font-weight: bold;
             text-transform: uppercase;
+            border-bottom: 2px solid #000;
+            padding-bottom: 5px;
         }
         
         /* API Key Section */
         #api-key-section {
-            background: #000;
-            border: 2px solid #00ff00;
+            background: #fafafa;
+            border: 2px solid #000;
             padding: 20px;
-            margin-bottom: 20px;
+            margin-bottom: 30px;
         }
         #api-key-section input {
             width: 100%;
             padding: 10px;
-            border: 1px solid #00ff00;
-            background: #0a0a0a;
-            color: #00ff00;
+            border: 2px solid #666;
+            background: white;
+            color: #000;
             font-family: 'Courier New', monospace;
             font-size: 14px;
         }
         #api-key-section input:focus {
             outline: none;
-            border-color: #00ffff;
-            box-shadow: 0 0 5px #00ff00;
+            border-color: #000;
+            box-shadow: none;
         }
         
         /* Buttons */
         button {
-            background: #000;
-            color: #00ff00;
-            border: 2px solid #00ff00;
+            background: white;
+            color: #000;
+            border: 2px solid #000;
             padding: 8px 16px;
             cursor: pointer;
-            font-size: 14px;
+            font-size: 12px;
             font-family: 'Courier New', monospace;
             margin-top: 10px;
             text-transform: uppercase;
             letter-spacing: 1px;
+            font-weight: bold;
         }
         button:hover { 
-            background: #00ff00;
-            color: #000;
+            background: #000;
+            color: white;
         }
         button.danger { 
-            border-color: #ff0000;
-            color: #ff0000;
+            border-color: #000;
+            color: #000;
         }
         button.danger:hover {
-            background: #ff0000;
-            color: #000;
+            background: #000;
+            color: white;
         }
         
         /* Tabs */
@@ -83,30 +87,33 @@
             display: flex;
             gap: 2px;
             margin-bottom: 0;
-            border-bottom: 2px solid #00ff00;
+            border-bottom: 3px solid #000;
         }
         .tab {
             padding: 10px 20px;
-            background: #000;
-            color: #00ff00;
-            border: 2px solid #00ff00;
+            background: #e8e8e8;
+            color: #000;
+            border: 2px solid #000;
             border-bottom: none;
             cursor: pointer;
-            font-weight: 500;
+            font-weight: bold;
             font-family: 'Courier New', monospace;
             text-transform: uppercase;
             letter-spacing: 1px;
+            font-size: 12px;
         }
-        .tab:hover { background: #001a00; }
+        .tab:hover { background: #d0d0d0; }
         .tab.active { 
-            background: #003300;
-            color: #00ffff;
+            background: white;
+            color: #000;
+            border-bottom: 3px solid white;
+            margin-bottom: -3px;
         }
         
         /* Content */
         .content {
-            background: #000;
-            border: 2px solid #00ff00;
+            background: white;
+            border: 2px solid #000;
             border-top: none;
             padding: 20px;
             display: none;
@@ -118,91 +125,91 @@
             width: 100%;
             border-collapse: collapse;
             margin-top: 15px;
-            border: 1px solid #00ff00;
+            border: 2px solid #000;
         }
         th, td {
-            padding: 8px 12px;
+            padding: 10px 12px;
             text-align: left;
-            border-bottom: 1px solid #004400;
-            border-right: 1px solid #004400;
+            border: 1px solid #000;
         }
         th { 
-            background: #001a00;
-            font-weight: 600;
-            color: #00ffff;
+            background: #f0f0f0;
+            font-weight: bold;
+            color: #000;
             text-transform: uppercase;
-            font-size: 12px;
+            font-size: 11px;
             letter-spacing: 1px;
         }
-        tr:hover { background: #001100; }
-        td:last-child, th:last-child { border-right: none; }
+        tr:hover { background: #fafafa; }
+        td { font-size: 13px; }
         
         /* Forms */
         .form-group {
-            margin-bottom: 15px;
+            margin-bottom: 20px;
         }
         label {
             display: block;
-            margin-bottom: 5px;
-            font-weight: 500;
-            color: #00ffff;
+            margin-bottom: 8px;
+            font-weight: bold;
+            color: #000;
             text-transform: uppercase;
-            font-size: 12px;
+            font-size: 11px;
             letter-spacing: 1px;
         }
         input[type="text"], input[type="datetime-local"], textarea, select {
             width: 100%;
-            padding: 8px;
-            border: 1px solid #00ff00;
-            background: #0a0a0a;
-            color: #00ff00;
+            padding: 10px;
+            border: 2px solid #666;
+            background: white;
+            color: #000;
             font-family: 'Courier New', monospace;
             font-size: 14px;
         }
         input:focus, textarea:focus, select:focus {
             outline: none;
-            border-color: #00ffff;
-            box-shadow: 0 0 5px #00ff00;
+            border-color: #000;
+            box-shadow: none;
         }
         textarea { min-height: 80px; }
-        small { color: #00aa00; font-size: 11px; }
+        small { color: #666; font-size: 11px; }
         
         /* Status badges */
         .badge {
-            padding: 4px 8px;
-            border: 1px solid;
-            font-size: 12px;
-            font-weight: 600;
+            padding: 4px 10px;
+            border: 2px solid;
+            font-size: 11px;
+            font-weight: bold;
             font-family: 'Courier New', monospace;
             text-transform: uppercase;
+            letter-spacing: 1px;
         }
         .badge.success { 
-            border-color: #00ff00;
-            color: #00ff00;
-            background: #003300;
+            border-color: #000;
+            color: #000;
+            background: white;
         }
         .badge.failed { 
-            border-color: #ff0000;
-            color: #ff0000;
-            background: #330000;
+            border-color: #000;
+            color: white;
+            background: #000;
         }
         
         .hidden { display: none; }
-        .error { color: #ff0000; margin-top: 10px; font-weight: bold; }
-        .empty { text-align: center; padding: 40px; color: #00aa00; }
+        .error { color: #000; margin-top: 10px; font-weight: bold; }
+        .empty { text-align: center; padding: 40px; color: #666; }
         
         /* Loading spinner */
         .loading {
             text-align: center;
             padding: 40px;
-            color: #00ff00;
+            color: #000;
         }
         .spinner {
             display: inline-block;
             width: 40px;
             height: 40px;
-            border: 4px solid #003300;
-            border-top-color: #00ff00;
+            border: 4px solid #e0e0e0;
+            border-top-color: #000;
             border-radius: 50%;
             animation: spin 1s linear infinite;
             margin-bottom: 10px;
@@ -219,31 +226,36 @@
 </head>
 <body>
     <div class="container">
-        <h1>┌─ LETTA SWITCHBOARD ─────────────────────────────────────┐</h1>
-        <pre style="color: #00aa00; margin-bottom: 20px; font-size: 11px;">│ MESSAGE ROUTING TERMINAL v1.0.0                         │
-│ STATUS: <span class="blink">●</span> ONLINE                                         │
-└─────────────────────────────────────────────────────────┘</pre>
+        <h1>LETTA SWITCHBOARD — MESSAGE ROUTING SERVICE</h1>
+        <div style="border: 2px solid #000; padding: 10px; margin-bottom: 30px; background: #fafafa;">
+            <div style="font-size: 11px; line-height: 1.8;">
+                <strong>SYSTEM:</strong> MESSAGE ROUTING TERMINAL<br>
+                <strong>VERSION:</strong> 1.0.0<br>
+                <strong>STATUS:</strong> OPERATIONAL<br>
+                <strong>PROTOCOL:</strong> REST API + SCHEDULED EXECUTION
+            </div>
+        </div>
         
         <!-- API Key Input -->
         <div id="api-key-section">
-            <label for="api-key-input">[ AUTHENTICATION ]</label>
+            <label for="api-key-input">AUTHENTICATION</label>
             <input type="password" id="api-key-input" placeholder="sk-let-...">
-            <button onclick="saveApiKey()">[ SAVE KEY ]</button>
-            <button onclick="clearApiKey()" class="danger">[ CLEAR KEY ]</button>
+            <button onclick="saveApiKey()">SAVE KEY</button>
+            <button onclick="clearApiKey()" class="danger">CLEAR KEY</button>
             <div id="api-key-status"></div>
         </div>
         
         <div id="main-content" class="hidden">
             <!-- Tabs -->
             <div class="tabs">
-                <button class="tab active" onclick="showTab('schedules')">[ SCHEDULES ]</button>
-                <button class="tab" onclick="showTab('create')">[ CREATE NEW ]</button>
-                <button class="tab" onclick="showTab('results')">[ RESULTS ]</button>
+                <button class="tab active" onclick="showTab('schedules')">SCHEDULES</button>
+                <button class="tab" onclick="showTab('create')">CREATE NEW</button>
+                <button class="tab" onclick="showTab('results')">RESULTS</button>
             </div>
             
             <!-- Schedules Tab -->
             <div id="schedules-tab" class="content active">
-                <h2>═══ ONE-TIME SCHEDULES ═══</h2>
+                <h2>ONE-TIME SCHEDULES</h2>
                 <table id="onetime-table">
                     <thead>
                         <tr>
@@ -257,7 +269,7 @@
                     <tbody></tbody>
                 </table>
                 
-                <h2>═══ RECURRING SCHEDULES ═══</h2>
+                <h2>RECURRING SCHEDULES</h2>
                 <table id="recurring-table">
                     <thead>
                         <tr>
@@ -272,15 +284,15 @@
                     <tbody></tbody>
                 </table>
                 
-                <button onclick="loadSchedules()" style="margin-top: 20px;">[ REFRESH ]</button>
+                <button onclick="loadSchedules()" style="margin-top: 20px;">REFRESH</button>
             </div>
             
             <!-- Create Tab -->
             <div id="create-tab" class="content">
-                <h2>═══ CREATE SCHEDULE ═══</h2>
+                <h2>CREATE SCHEDULE</h2>
                 
                 <div class="form-group">
-                    <label>[ SCHEDULE TYPE ]</label>
+                    <label>SCHEDULE TYPE</label>
                     <select id="schedule-type" onchange="toggleScheduleType()">
                         <option value="onetime">One-Time</option>
                         <option value="recurring">Recurring</option>
@@ -288,22 +300,22 @@
                 </div>
                 
                 <div class="form-group">
-                    <label for="agent-id">[ AGENT ID ]</label>
+                    <label for="agent-id">AGENT ID</label>
                     <input type="text" id="agent-id" placeholder="agent-xxx">
                 </div>
                 
                 <div class="form-group">
-                    <label for="message">[ MESSAGE ]</label>
+                    <label for="message">MESSAGE</label>
                     <textarea id="message" placeholder="Your message to the agent"></textarea>
                 </div>
                 
                 <div id="onetime-fields">
                     <div class="form-group">
-                        <label for="execute-at">[ EXECUTE AT ]</label>
+                        <label for="execute-at">EXECUTE AT</label>
                         <input type="datetime-local" id="execute-at">
                     </div>
                     <div class="form-group">
-                        <label for="timezone">[ TIMEZONE ]</label>
+                        <label for="timezone">TIMEZONE</label>
                         <select id="timezone">
                             <option value="local" selected>Local Browser Time</option>
                             <option value="UTC">UTC</option>
@@ -321,19 +333,19 @@
                 
                 <div id="recurring-fields" class="hidden">
                     <div class="form-group">
-                        <label for="cron">[ CRON EXPRESSION ]</label>
+                        <label for="cron">CRON EXPRESSION</label>
                         <input type="text" id="cron" placeholder="0 9 * * 1-5">
                         <small style="display:block;margin-top:5px;color:#6b7280;">Examples: "0 9 * * *" (daily at 9am), "*/5 * * * *" (every 5 min)</small>
                     </div>
                 </div>
                 
-                <button onclick="createSchedule()">[ CREATE SCHEDULE ]</button>
+                <button onclick="createSchedule()">CREATE SCHEDULE</button>
                 <div id="create-error" class="error"></div>
             </div>
             
             <!-- Results Tab -->
             <div id="results-tab" class="content">
-                <h2>═══ EXECUTION RESULTS ═══</h2>
+                <h2>EXECUTION RESULTS</h2>
                 <table id="results-table">
                     <thead>
                         <tr>
@@ -349,7 +361,7 @@
                     <tbody></tbody>
                 </table>
                 
-                <button onclick="loadResults()" style="margin-top: 20px;">[ REFRESH ]</button>
+                <button onclick="loadResults()" style="margin-top: 20px;">REFRESH</button>
             </div>
         </div>
     </div>
@@ -369,12 +381,12 @@
         function saveApiKey() {
             API_KEY = document.getElementById('api-key-input').value.trim();
             if (!API_KEY) {
-                alert('[ ✗ ERROR: API KEY REQUIRED ]');
+                alert('ERROR: API KEY REQUIRED');
                 return;
             }
             sessionStorage.setItem('letta_api_key', API_KEY);
             document.getElementById('main-content').classList.remove('hidden');
-            document.getElementById('api-key-status').innerHTML = '<p style="color:#00ff00;margin-top:10px;">[ ✓ API KEY AUTHENTICATED ]</p>';
+            document.getElementById('api-key-status').innerHTML = '<p style="color:#000;margin-top:10px;font-weight:bold;">✓ API KEY AUTHENTICATED</p>';
             loadSchedules();
             loadResults();
         }
@@ -384,7 +396,7 @@
             API_KEY = '';
             document.getElementById('api-key-input').value = '';
             document.getElementById('main-content').classList.add('hidden');
-            document.getElementById('api-key-status').innerHTML = '<p style="color:#ff0000;margin-top:10px;">[ ✗ SESSION TERMINATED ]</p>';
+            document.getElementById('api-key-status').innerHTML = '<p style="color:#000;margin-top:10px;font-weight:bold;">✗ SESSION TERMINATED</p>';
         }
         
         function showTab(tab) {
@@ -425,7 +437,7 @@
                         <td>${s.agent_id}</td>
                         <td>${new Date(s.execute_at).toLocaleString()}</td>
                         <td>${truncate(s.message, 50)}</td>
-                        <td><button class="danger" onclick="deleteSchedule('one-time', '${s.id}')">[ DEL ]</button></td>
+                        <td><button class="danger" onclick="deleteSchedule('one-time', '${s.id}')">DEL</button></td>
                     </tr>
                 `).join('') : '<tr><td colspan="5" class="empty">No one-time schedules</td></tr>';
                 
@@ -438,11 +450,11 @@
                         <td>${s.cron}</td>
                         <td>${truncate(s.message, 50)}</td>
                         <td>${s.last_run ? new Date(s.last_run).toLocaleString() : 'Never'}</td>
-                        <td><button class="danger" onclick="deleteSchedule('recurring', '${s.id}')">[ DEL ]</button></td>
+                        <td><button class="danger" onclick="deleteSchedule('recurring', '${s.id}')">DEL</button></td>
                     </tr>
                 `).join('') : '<tr><td colspan="6" class="empty">No recurring schedules</td></tr>';
             } catch (error) {
-                alert('[ ✗ ERROR LOADING SCHEDULES: ' + error.message.toUpperCase() + ' ]');
+                alert('ERROR LOADING SCHEDULES: ' + error.message);
             }
         }
         
@@ -469,7 +481,7 @@
                     </tr>
                 `).join('') : '<tr><td colspan="7" class="empty">No execution results</td></tr>';
             } catch (error) {
-                alert('[ ✗ ERROR LOADING RESULTS: ' + error.message.toUpperCase() + ' ]');
+                alert('ERROR LOADING RESULTS: ' + error.message);
             }
         }
         
@@ -543,7 +555,7 @@
                     throw new Error(error.detail || 'Failed to create schedule');
                 }
                 
-                alert('[ ✓ SCHEDULE CREATED SUCCESSFULLY ]');
+                alert('SCHEDULE CREATED SUCCESSFULLY');
                 document.getElementById('agent-id').value = '';
                 document.getElementById('message').value = '';
                 document.getElementById('execute-at').value = '';
@@ -557,7 +569,7 @@
         }
         
         async function deleteSchedule(type, id) {
-            if (!confirm('[ CONFIRM: DELETE SCHEDULE? ]')) return;
+            if (!confirm('CONFIRM: Delete this schedule?')) return;
             
             try {
                 const response = await fetch(`${API_BASE}/schedules/${type}/${id}`, {
@@ -567,10 +579,10 @@
                 
                 if (!response.ok) throw new Error('Failed to delete');
                 
-                alert('[ ✓ SCHEDULE TERMINATED ]');
+                alert('SCHEDULE DELETED');
                 loadSchedules();
             } catch (error) {
-                alert('[ ✗ ERROR DELETING SCHEDULE: ' + error.message.toUpperCase() + ' ]');
+                alert('ERROR DELETING SCHEDULE: ' + error.message);
             }
         }