Files
catalog/ts_web/elements/sz-demo-view-network.ts
2026-01-03 02:44:25 +00:00

355 lines
12 KiB
TypeScript

import {
DeesElement,
customElement,
html,
css,
cssManager,
state,
type TemplateResult,
} from '@design.estate/dees-element';
import type { DeesAppui } from '@design.estate/dees-catalog';
import './index.js';
declare global {
interface HTMLElementTagNameMap {
'sz-demo-view-network': SzDemoViewNetwork;
}
}
@customElement('sz-demo-view-network')
export class SzDemoViewNetwork extends DeesElement {
private appui: DeesAppui | null = null;
@state()
private accessor currentTab: 'proxy' | 'dns' | 'domains' | 'domain-detail' = 'proxy';
async onActivate(context: { appui: DeesAppui; viewId: string }) {
this.appui = context.appui;
// Set up content tabs
this.appui.setContentTabs([
{
key: 'Reverse Proxy',
action: () => {
this.currentTab = 'proxy';
this.updateSecondaryMenu();
},
},
{
key: 'DNS Records',
action: () => {
this.currentTab = 'dns';
this.updateSecondaryMenu();
},
},
{
key: 'Domains',
action: () => {
this.currentTab = 'domains';
this.updateSecondaryMenu();
},
},
]);
this.updateSecondaryMenu();
}
private updateSecondaryMenu() {
if (!this.appui) return;
if (this.currentTab === 'proxy') {
this.appui.setSecondaryMenu({
heading: 'Reverse Proxy',
groups: [
{
name: 'Actions',
items: [
{ type: 'action', key: 'Add Route', iconName: 'lucide:Plus', action: () => { console.log('Add route'); } },
{ type: 'action', key: 'Refresh', iconName: 'lucide:RefreshCw', action: () => { console.log('Refresh'); } },
],
},
{
name: 'Statistics',
items: [
{ type: 'header', label: '42 Active Connections' },
{ type: 'header', label: '15,420 Requests Today' },
],
},
],
});
} else if (this.currentTab === 'dns') {
this.appui.setSecondaryMenu({
heading: 'DNS Records',
groups: [
{
name: 'Actions',
items: [
{ type: 'action', key: 'Add Record', iconName: 'lucide:Plus', action: () => { console.log('Add record'); } },
{ type: 'action', key: 'Import Zone', iconName: 'lucide:Upload', action: () => { console.log('Import zone'); } },
],
},
{
name: 'Zones',
items: [
{ key: 'example.com', iconName: 'lucide:Globe', action: () => { console.log('Select example.com'); } },
{ key: 'example.net', iconName: 'lucide:Globe', action: () => { console.log('Select example.net'); } },
{ key: 'myapp.io', iconName: 'lucide:Globe', action: () => { console.log('Select myapp.io'); } },
],
},
],
});
} else if (this.currentTab === 'domains' || this.currentTab === 'domain-detail') {
this.appui.setSecondaryMenu({
heading: 'Domains',
groups: [
{
name: 'Actions',
items: [
{ type: 'action', key: 'Add Domain', iconName: 'lucide:Plus', action: () => { console.log('Add domain'); } },
{ type: 'action', key: 'Verify All', iconName: 'lucide:CheckCircle', action: () => { console.log('Verify all'); } },
],
},
{
name: 'Certificates',
items: [
{ key: 'Valid', iconName: 'lucide:ShieldCheck', badge: '3', badgeVariant: 'success', action: () => { console.log('Filter valid'); } },
{ key: 'Expiring Soon', iconName: 'lucide:AlertTriangle', badge: '1', badgeVariant: 'warning', action: () => { console.log('Filter expiring'); } },
],
},
],
});
}
}
onDeactivate() {
// Cleanup if needed
}
@state()
private accessor selectedDomain: any = null;
private demoProxyRoutes = [
{ id: '1', domain: 'api.example.com', target: 'http://api-gateway:3000', ssl: true, status: 'active' as const },
{ id: '2', domain: 'app.example.com', target: 'http://frontend:8080', ssl: true, status: 'active' as const },
{ id: '3', domain: 'admin.example.com', target: 'http://admin-panel:4000', ssl: true, status: 'active' as const },
{ id: '4', domain: 'legacy.example.com', target: 'http://legacy:5000', ssl: false, status: 'inactive' as const },
];
private demoAccessLogs = [
{ timestamp: '14:30:22', method: 'GET', path: '/api/users', status: 200, duration: '45ms', ip: '192.168.1.100' },
{ timestamp: '14:30:21', method: 'POST', path: '/api/orders', status: 201, duration: '120ms', ip: '192.168.1.105' },
{ timestamp: '14:30:20', method: 'GET', path: '/api/products', status: 200, duration: '89ms', ip: '192.168.1.100' },
{ timestamp: '14:30:19', method: 'DELETE', path: '/api/cache', status: 204, duration: '12ms', ip: '192.168.1.50' },
{ timestamp: '14:30:18', method: 'GET', path: '/health', status: 200, duration: '5ms', ip: '10.0.0.1' },
];
private demoDnsRecords = [
{ id: '1', type: 'A' as const, name: '@', value: '192.168.1.100', ttl: 3600, zone: 'example.com' },
{ id: '2', type: 'A' as const, name: 'api', value: '192.168.1.100', ttl: 3600, zone: 'example.com' },
{ id: '3', type: 'CNAME' as const, name: 'www', value: 'example.com', ttl: 3600, zone: 'example.com' },
{ id: '4', type: 'MX' as const, name: '@', value: 'mail.example.com', ttl: 3600, zone: 'example.com', priority: 10 },
{ id: '5', type: 'TXT' as const, name: '@', value: 'v=spf1 include:_spf.example.com ~all', ttl: 3600, zone: 'example.com' },
];
private demoDomains = [
{ id: '1', name: 'example.com', status: 'active' as const, ssl: true, sslExpiry: '2024-04-15', dnsProvider: 'Cloudflare', recordCount: 12 },
{ id: '2', name: 'api.example.com', status: 'active' as const, ssl: true, sslExpiry: '2024-05-20', dnsProvider: 'Cloudflare', recordCount: 3 },
{ id: '3', name: 'staging.example.com', status: 'pending' as const, ssl: false, sslExpiry: null, dnsProvider: 'Cloudflare', recordCount: 2 },
{ id: '4', name: 'legacy.example.net', status: 'active' as const, ssl: true, sslExpiry: '2024-02-10', dnsProvider: 'Manual', recordCount: 5 },
];
private demoDomainDetail = {
id: '1',
name: 'example.com',
status: 'active' as const,
verified: true,
createdAt: '2024-01-10',
proxyRoutes: ['/api/*', '/app/*', '/admin/*'],
};
private demoCertificate = {
id: '1',
domain: 'example.com',
issuer: "Let's Encrypt",
validFrom: '2024-01-10',
validUntil: '2024-04-10',
daysRemaining: 45,
status: 'valid' as const,
autoRenew: true,
chain: ['R3', 'ISRG Root X1'],
};
private demoDomainDnsRecords = [
{ id: '1', type: 'A' as const, name: '@', value: '192.168.1.100', ttl: 3600 },
{ id: '2', type: 'CNAME' as const, name: 'www', value: 'example.com', ttl: 3600 },
{ id: '3', type: 'MX' as const, name: '@', value: 'mail.example.com', ttl: 3600, priority: 10 },
{ id: '4', type: 'TXT' as const, name: '@', value: 'v=spf1 include:_spf.example.com ~all', ttl: 3600 },
];
public static styles = [
cssManager.defaultStyles,
css`
:host {
display: block;
padding: 24px;
height: 100%;
overflow-y: auto;
box-sizing: border-box;
}
.page-header {
margin-bottom: 24px;
}
.page-title {
font-size: 24px;
font-weight: 700;
color: ${cssManager.bdTheme('#18181b', '#fafafa')};
margin: 0 0 8px 0;
}
.page-subtitle {
font-size: 14px;
color: ${cssManager.bdTheme('#71717a', '#a1a1aa')};
margin: 0;
}
.tabs {
display: flex;
gap: 4px;
margin-bottom: 24px;
border-bottom: 1px solid ${cssManager.bdTheme('#e4e4e7', '#27272a')};
}
.tab {
padding: 10px 16px;
font-size: 14px;
font-weight: 500;
color: ${cssManager.bdTheme('#71717a', '#a1a1aa')};
background: transparent;
border: none;
cursor: pointer;
position: relative;
transition: color 200ms ease;
}
.tab:hover {
color: ${cssManager.bdTheme('#18181b', '#fafafa')};
}
.tab.active {
color: ${cssManager.bdTheme('#18181b', '#fafafa')};
}
.tab.active::after {
content: '';
position: absolute;
bottom: -1px;
left: 0;
right: 0;
height: 2px;
background: ${cssManager.bdTheme('#18181b', '#fafafa')};
border-radius: 1px 1px 0 0;
}
.back-button {
display: inline-flex;
align-items: center;
gap: 6px;
padding: 6px 12px;
background: transparent;
border: 1px solid ${cssManager.bdTheme('#e4e4e7', '#27272a')};
border-radius: 6px;
font-size: 13px;
color: ${cssManager.bdTheme('#71717a', '#a1a1aa')};
cursor: pointer;
margin-bottom: 16px;
transition: all 200ms ease;
}
.back-button:hover {
background: ${cssManager.bdTheme('#f4f4f5', '#18181b')};
color: ${cssManager.bdTheme('#18181b', '#fafafa')};
}
`,
];
public render(): TemplateResult {
if (this.currentTab === 'domain-detail') {
return this.renderDomainDetail();
}
return html`
${this.currentTab === 'proxy' ? this.renderProxyView() : ''}
${this.currentTab === 'dns' ? this.renderDnsView() : ''}
${this.currentTab === 'domains' ? this.renderDomainsView() : ''}
`;
}
private renderProxyView(): TemplateResult {
return html`
<sz-network-proxy-view
.routes=${this.demoProxyRoutes}
.accessLogs=${this.demoAccessLogs}
.stats=${{
activeConnections: 42,
requestsToday: 15420,
bytesTransferred: '2.4 GB',
}}
@add-route=${() => console.log('Add route')}
@edit-route=${(e: CustomEvent) => console.log('Edit route:', e.detail)}
@delete-route=${(e: CustomEvent) => console.log('Delete route:', e.detail)}
></sz-network-proxy-view>
`;
}
private renderDnsView(): TemplateResult {
return html`
<sz-network-dns-view
.records=${this.demoDnsRecords}
.zones=${['example.com', 'example.net', 'myapp.io']}
.selectedZone=${'example.com'}
@add-record=${() => console.log('Add record')}
@edit-record=${(e: CustomEvent) => console.log('Edit record:', e.detail)}
@delete-record=${(e: CustomEvent) => console.log('Delete record:', e.detail)}
@change-zone=${(e: CustomEvent) => console.log('Change zone:', e.detail)}
></sz-network-dns-view>
`;
}
private renderDomainsView(): TemplateResult {
return html`
<sz-network-domains-view
.domains=${this.demoDomains}
@add-domain=${() => console.log('Add domain')}
@view-domain=${(e: CustomEvent) => { this.selectedDomain = e.detail; this.currentTab = 'domain-detail'; }}
@renew-ssl=${(e: CustomEvent) => console.log('Renew SSL:', e.detail)}
@delete-domain=${(e: CustomEvent) => console.log('Delete domain:', e.detail)}
></sz-network-domains-view>
`;
}
private renderDomainDetail(): TemplateResult {
return html`
<button class="back-button" @click=${() => this.currentTab = 'domains'}>
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<polyline points="15 18 9 12 15 6"/>
</svg>
Back to Domains
</button>
<sz-domain-detail-view
.domain=${this.demoDomainDetail}
.certificate=${this.demoCertificate}
.dnsRecords=${this.demoDomainDnsRecords}
@verify-domain=${() => console.log('Verify domain')}
@delete-domain=${() => { console.log('Delete domain'); this.currentTab = 'domains'; }}
@renew-certificate=${() => console.log('Renew certificate')}
@add-dns-record=${() => console.log('Add DNS record')}
@edit-dns-record=${(e: CustomEvent) => console.log('Edit DNS record:', e.detail)}
@delete-dns-record=${(e: CustomEvent) => console.log('Delete DNS record:', e.detail)}
></sz-domain-detail-view>
`;
}
}