355 lines
12 KiB
TypeScript
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>
|
|
`;
|
|
}
|
|
}
|