Files
dss/admin-ui/js/components/layout/ds-panel.js
Digital Production Factory 276ed71f31 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
2025-12-09 18:45:48 -03:00

121 lines
3.1 KiB
JavaScript

/**
* ds-panel.js
* Bottom panel component - holds team-specific tabs
*/
import { getPanelConfig } from '../../config/panel-config.js';
class DSPanel extends HTMLElement {
constructor() {
super();
this.currentTab = null;
this.tabs = [];
this.advancedMode = false;
}
/**
* Configure panel with team-specific tabs
* @param {string} teamId - Team identifier (ui, ux, qa, admin)
* @param {boolean} advancedMode - Whether advanced mode is enabled
*/
configure(teamId, advancedMode = false) {
this.advancedMode = advancedMode;
this.tabs = getPanelConfig(teamId, advancedMode);
// Set first tab as current if not already set
if (this.tabs.length > 0 && !this.currentTab) {
this.currentTab = this.tabs[0].id;
}
// Re-render with new configuration
this.render();
this.setupEventListeners();
}
connectedCallback() {
this.render();
this.setupEventListeners();
}
render() {
this.innerHTML = `
<div class="panel-header">
${this.tabs.map(tab => `
<div class="panel-tab ${tab.id === this.currentTab ? 'active' : ''}"
data-tab="${tab.id}">
${tab.label}
</div>
`).join('')}
</div>
<div class="panel-content">
<div id="panel-tab-content">
${this.renderTabContent(this.currentTab)}
</div>
</div>
`;
}
setupEventListeners() {
this.querySelectorAll('.panel-tab').forEach(tab => {
tab.addEventListener('click', (e) => {
const tabId = e.currentTarget.dataset.tab;
this.switchTab(tabId);
});
});
}
switchTab(tabId) {
if (tabId === this.currentTab) return;
this.currentTab = tabId;
// Update active state
this.querySelectorAll('.panel-tab').forEach(tab => {
tab.classList.toggle('active', tab.dataset.tab === tabId);
});
// Update content
const content = this.querySelector('#panel-tab-content');
if (content) {
content.innerHTML = this.renderTabContent(tabId);
}
// Dispatch tab-switch event
this.dispatchEvent(new CustomEvent('panel-tab-switch', {
bubbles: true,
detail: { tab: tabId }
}));
}
renderTabContent(tabId) {
// Find tab configuration
const tabConfig = this.tabs.find(tab => tab.id === tabId);
if (!tabConfig) {
return '<div style="padding: 16px; color: var(--vscode-text-dim);">Tab not found</div>';
}
// Dynamically create component based on configuration
const componentTag = tabConfig.component;
const propsString = Object.entries(tabConfig.props || {})
.map(([key, value]) => `${key}="${value}"`)
.join(' ');
return `<${componentTag} ${propsString}></${componentTag}>`;
}
// Public method for workdesks to update panel content
setTabContent(tabId, content) {
const tabContent = this.querySelector('#panel-tab-content');
if (this.currentTab === tabId && tabContent) {
if (typeof content === 'string') {
tabContent.innerHTML = content;
} else {
tabContent.innerHTML = '';
tabContent.appendChild(content);
}
}
}
}
customElements.define('ds-panel', DSPanel);