Apply LotusGuild design system convergence (aesthetic_diff.md)

- §5: Section headers now ╠═══ TITLE ═══╣ (was ═══ TITLE ═══)
- §8+§18: Replace inline-style showTerminalNotification() with lt.toast.*
  delegate wrapper; load base.js from /base.js
- §12: Fix --text-muted #008822→#00bb33 (WCAG AA contrast)

base.js symlinked from web_template into public/ so lt.* is available.
showTerminalNotification() is kept as a thin wrapper so all existing
call sites continue to work unchanged.

README: Remove completed pending items (toast, text-muted, position)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-14 21:40:36 -04:00
parent 18a6b642d1
commit 3f6e04d1ab
3 changed files with 53 additions and 46 deletions

View File

@@ -4,6 +4,22 @@ A distributed workflow orchestration platform for managing and executing complex
> **Security Notice:** This repository is hosted on Gitea and is version-controlled. **Never commit secrets, credentials, passwords, API keys, or any sensitive information to this repo.** All sensitive configuration belongs exclusively in `.env` files which are listed in `.gitignore` and must never be committed. This includes database passwords, worker API keys, webhook secrets, and internal IP details.
**Design System**: [web_template](https://code.lotusguild.org/LotusGuild/web_template) — shared CSS, JS, and layout patterns for all LotusGuild apps
## Styling & Layout
PULSE uses the **LotusGuild Terminal Design System**. For all styling, component, and layout documentation see:
- [`web_template/README.md`](https://code.lotusguild.org/LotusGuild/web_template/src/branch/main/README.md) — full component reference, CSS variables, JS API
- [`web_template/base.css`](https://code.lotusguild.org/LotusGuild/web_template/src/branch/main/base.css) — unified CSS (`.lt-*` classes)
- [`web_template/base.js`](https://code.lotusguild.org/LotusGuild/web_template/src/branch/main/base.js) — `window.lt` utilities (toast, modal, WebSocket helpers, fetch)
- [`web_template/aesthetic_diff.md`](https://code.lotusguild.org/LotusGuild/web_template/src/branch/main/aesthetic_diff.md) — cross-app divergence analysis and convergence guide
- [`web_template/node/middleware.js`](https://code.lotusguild.org/LotusGuild/web_template/src/branch/main/node/middleware.js) — Express auth, CSRF, CSP nonce middleware
**Pending convergence items (see aesthetic_diff.md):**
- Extract inline `<style>` from `public/index.html` into `public/style.css` and extend `base.css`
- Use `lt.autoRefresh.start(refreshData, 30000)` instead of raw `setInterval`
## Overview
PULSE is a centralized workflow execution system designed to orchestrate operations across distributed infrastructure. It provides a powerful web-based interface with a vintage CRT terminal aesthetic for defining, managing, and executing workflows that can span multiple servers, require human interaction, and perform complex automation tasks at scale.
@@ -307,12 +323,34 @@ MAX_CONCURRENT_TASKS=5 # Max parallel tasks (default: 5)
PULSE uses MariaDB with the following tables:
- **users**: User accounts from Authelia SSO
- **workers**: Worker node registry with metadata
- **workflows**: Workflow definitions (JSON)
- **executions**: Execution history with logs
| Table | Purpose |
|-------|---------|
| `users` | User accounts synced from Authelia SSO |
| `workers` | Worker node registry with connection metadata |
| `workflows` | Workflow definitions stored as JSON |
| `executions` | Execution history with logs, status, and timestamps |
See [Claude.md](Claude.md) for complete schema details.
### `executions` Table Key Columns
| Column | Description |
|--------|-------------|
| `id` | Auto-increment primary key |
| `worker_id` | Foreign key to workers |
| `command` | The command that was executed |
| `status` | `running`, `completed`, `failed` |
| `output` | Command output / log (JSON or text) |
| `created_at` | Execution start timestamp |
| `completed_at` | Execution end timestamp |
### `workers` Table Key Columns
| Column | Description |
|--------|-------------|
| `id` | Auto-increment primary key |
| `name` | Worker name (from `WORKER_NAME` env) |
| `last_seen` | Last heartbeat timestamp |
| `status` | `online`, `offline` |
| `metadata` | JSON blob of system info |
## Troubleshooting

1
public/base.js Symbolic link
View File

@@ -0,0 +1 @@
/root/code/web_template/base.js

View File

@@ -20,7 +20,7 @@
--bg-terminal-border: #003300;
--text-primary: #00ff41;
--text-secondary: #00cc33;
--text-muted: #008822;
--text-muted: #00bb33;
/* Border & UI */
--border-color: #00ff41;
@@ -271,11 +271,11 @@
text-shadow: var(--glow-amber);
}
.card h3::before {
content: '═══ ';
content: '═══ ';
color: var(--terminal-green);
}
.card h3::after {
content: ' ═══';
content: ' ═══';
color: var(--terminal-green);
}
.status {
@@ -803,6 +803,7 @@
animation: slide-in 0.3s ease-out;
}
</style>
<script src="/base.js"></script>
</head>
<body>
<div class="container">
@@ -2899,45 +2900,12 @@
}
}
// Show terminal notification
// Show terminal notification — delegates to lt.toast from base.js
function showTerminalNotification(message, type = 'info') {
const notification = document.createElement('div');
notification.style.cssText = `
position: fixed;
top: 80px;
right: 20px;
background: #001a00;
border: 2px solid var(--terminal-green);
color: var(--terminal-green);
padding: 15px 20px;
font-family: var(--font-mono);
z-index: 10000;
animation: slide-in 0.3s ease-out;
box-shadow: 0 0 20px rgba(0, 255, 65, 0.3);
`;
if (type === 'error') {
notification.style.borderColor = '#ff4444';
notification.style.color = '#ff4444';
message = '✗ ' + message;
} else if (type === 'success') {
message = '✓ ' + message;
} else {
message = ' ' + message;
}
notification.textContent = message;
document.body.appendChild(notification);
// Play beep
terminalBeep(type);
// Remove after 3 seconds
setTimeout(() => {
notification.style.opacity = '0';
notification.style.transition = 'opacity 0.5s';
setTimeout(() => notification.remove(), 500);
}, 3000);
if (type === 'success') return lt.toast.success(message);
if (type === 'error') return lt.toast.error(message);
if (type === 'warning') return lt.toast.warning(message);
return lt.toast.info(message);
}
function connectWebSocket() {