Initial commit: Clean DSS implementation

Migrated from design-system-swarm with fresh git history.
Old project history preserved in /home/overbits/apps/design-system-swarm

Core components:
- MCP Server (Python FastAPI with mcp 1.23.1)
- Claude Plugin (agents, commands, skills, strategies, hooks, core)
- DSS Backend (dss-mvp1 - token translation, Figma sync)
- Admin UI (Node.js/React)
- Server (Node.js/Express)
- Storybook integration (dss-mvp1/.storybook)

Self-contained configuration:
- All paths relative or use DSS_BASE_PATH=/home/overbits/dss
- PYTHONPATH configured for dss-mvp1 and dss-claude-plugin
- .env file with all configuration
- Claude plugin uses ${CLAUDE_PLUGIN_ROOT} for portability

Migration completed: $(date)
🤖 Clean migration with full functionality preserved
This commit is contained in:
Digital Production Factory
2025-12-09 18:45:48 -03:00
commit 276ed71f31
884 changed files with 373737 additions and 0 deletions

View File

@@ -0,0 +1,249 @@
/**
* ds-console-viewer.js
* Console log viewer with real-time streaming and filtering
*/
import toolBridge from '../../services/tool-bridge.js';
class DSConsoleViewer extends HTMLElement {
constructor() {
super();
this.logs = [];
this.currentFilter = 'all';
this.autoScroll = true;
this.refreshInterval = null;
}
connectedCallback() {
this.render();
this.startAutoRefresh();
}
disconnectedCallback() {
this.stopAutoRefresh();
}
render() {
const filteredLogs = this.currentFilter === 'all'
? this.logs
: this.logs.filter(log => log.level === this.currentFilter);
this.innerHTML = `
<div style="display: flex; flex-direction: column; height: 100%;">
<!-- Header Controls -->
<div style="
display: flex;
justify-content: space-between;
align-items: center;
padding: 8px 12px;
border-bottom: 1px solid var(--vscode-border);
background-color: var(--vscode-sidebar);
">
<div style="display: flex; gap: 8px;">
<button class="filter-btn ${this.currentFilter === 'all' ? 'active' : ''}" data-filter="all" style="
padding: 4px 12px;
background-color: ${this.currentFilter === 'all' ? 'var(--vscode-accent)' : 'transparent'};
border: 1px solid var(--vscode-border);
color: var(--vscode-text);
border-radius: 2px;
cursor: pointer;
font-size: 11px;
">All</button>
<button class="filter-btn ${this.currentFilter === 'log' ? 'active' : ''}" data-filter="log" style="
padding: 4px 12px;
background-color: ${this.currentFilter === 'log' ? 'var(--vscode-accent)' : 'transparent'};
border: 1px solid var(--vscode-border);
color: var(--vscode-text);
border-radius: 2px;
cursor: pointer;
font-size: 11px;
">Log</button>
<button class="filter-btn ${this.currentFilter === 'warn' ? 'active' : ''}" data-filter="warn" style="
padding: 4px 12px;
background-color: ${this.currentFilter === 'warn' ? 'var(--vscode-accent)' : 'transparent'};
border: 1px solid var(--vscode-border);
color: var(--vscode-text);
border-radius: 2px;
cursor: pointer;
font-size: 11px;
">Warn</button>
<button class="filter-btn ${this.currentFilter === 'error' ? 'active' : ''}" data-filter="error" style="
padding: 4px 12px;
background-color: ${this.currentFilter === 'error' ? 'var(--vscode-accent)' : 'transparent'};
border: 1px solid var(--vscode-border);
color: var(--vscode-text);
border-radius: 2px;
cursor: pointer;
font-size: 11px;
">Error</button>
</div>
<div style="display: flex; gap: 8px; align-items: center;">
<label style="font-size: 11px; display: flex; align-items: center; gap: 4px; cursor: pointer;">
<input type="checkbox" id="auto-scroll-toggle" ${this.autoScroll ? 'checked' : ''}>
Auto-scroll
</label>
<button id="clear-logs-btn" class="button" style="padding: 4px 12px; font-size: 11px;">
Clear
</button>
<button id="refresh-logs-btn" class="button" style="padding: 4px 12px; font-size: 11px;">
Refresh
</button>
</div>
</div>
<!-- Console Output -->
<div id="console-output" style="
flex: 1;
overflow-y: auto;
padding: 8px;
font-family: 'Consolas', 'Monaco', monospace;
font-size: 12px;
background-color: var(--vscode-bg);
">
${filteredLogs.length === 0 ? `
<div style="padding: 16px; text-align: center; color: var(--vscode-text-dim);">
No console logs${this.currentFilter !== 'all' ? ` (${this.currentFilter})` : ''}
</div>
` : filteredLogs.map(log => this.renderLogEntry(log)).join('')}
</div>
</div>
`;
this.setupEventListeners();
if (this.autoScroll) {
this.scrollToBottom();
}
}
renderLogEntry(log) {
const levelColors = {
log: 'var(--vscode-text)',
warn: '#ff9800',
error: '#f44336',
info: '#2196f3',
debug: 'var(--vscode-text-dim)'
};
const color = levelColors[log.level] || 'var(--vscode-text)';
return `
<div style="
padding: 4px 8px;
border-bottom: 1px solid var(--vscode-border);
display: flex;
gap: 12px;
">
<span style="color: var(--vscode-text-dim); min-width: 80px; flex-shrink: 0;">
${log.timestamp}
</span>
<span style="color: ${color}; font-weight: 600; min-width: 50px; flex-shrink: 0;">
[${log.level.toUpperCase()}]
</span>
<span style="color: var(--vscode-text); flex: 1; word-break: break-word;">
${this.escapeHtml(log.message)}
</span>
</div>
`;
}
setupEventListeners() {
// Filter buttons
this.querySelectorAll('.filter-btn').forEach(btn => {
btn.addEventListener('click', (e) => {
this.currentFilter = e.target.dataset.filter;
this.render();
});
});
// Auto-scroll toggle
const autoScrollToggle = this.querySelector('#auto-scroll-toggle');
if (autoScrollToggle) {
autoScrollToggle.addEventListener('change', (e) => {
this.autoScroll = e.target.checked;
});
}
// Clear button
const clearBtn = this.querySelector('#clear-logs-btn');
if (clearBtn) {
clearBtn.addEventListener('click', () => {
this.logs = [];
this.render();
});
}
// Refresh button
const refreshBtn = this.querySelector('#refresh-logs-btn');
if (refreshBtn) {
refreshBtn.addEventListener('click', () => {
this.fetchLogs();
});
}
}
async fetchLogs() {
try {
const result = await toolBridge.getBrowserLogs(this.currentFilter, 100);
if (result && result.logs) {
this.logs = result.logs.map(log => ({
timestamp: new Date(log.timestamp).toLocaleTimeString(),
level: log.level || 'log',
message: log.message || JSON.stringify(log)
}));
this.render();
}
} catch (error) {
console.error('Failed to fetch logs:', error);
this.addLog('error', `Failed to fetch logs: ${error.message}`);
}
}
addLog(level, message) {
const now = new Date();
this.logs.push({
timestamp: now.toLocaleTimeString(),
level,
message
});
// Keep only last 100 logs
if (this.logs.length > 100) {
this.logs = this.logs.slice(-100);
}
this.render();
}
startAutoRefresh() {
// Fetch logs every 2 seconds
this.fetchLogs();
this.refreshInterval = setInterval(() => {
this.fetchLogs();
}, 2000);
}
stopAutoRefresh() {
if (this.refreshInterval) {
clearInterval(this.refreshInterval);
this.refreshInterval = null;
}
}
scrollToBottom() {
const output = this.querySelector('#console-output');
if (output) {
output.scrollTop = output.scrollHeight;
}
}
escapeHtml(text) {
const div = document.createElement('div');
div.textContent = text;
return div.innerHTML;
}
}
customElements.define('ds-console-viewer', DSConsoleViewer);
export default DSConsoleViewer;