feat: Add operations view components for logs, overview, security, and stats
- Implemented `ops-view-logs` for displaying and filtering logs with streaming capabilities.
- Created `ops-view-overview` to show server, email, DNS statistics, and charts.
- Developed `ops-view-security` for monitoring security metrics, blocked IPs, and authentication attempts.
- Added `ops-view-stats` to present comprehensive statistics on server, email, DNS, and security metrics.
- Introduced shared styles and components including `ops-sectionheading` for consistent UI.
2025-06-08 12:03:17 +00:00
|
|
|
import * as shared from './shared/index.js';
|
|
|
|
|
import * as appstate from '../appstate.js';
|
|
|
|
|
|
|
|
|
|
import {
|
|
|
|
|
DeesElement,
|
|
|
|
|
customElement,
|
|
|
|
|
html,
|
|
|
|
|
state,
|
|
|
|
|
css,
|
|
|
|
|
cssManager,
|
|
|
|
|
} from '@design.estate/dees-element';
|
|
|
|
|
|
|
|
|
|
@customElement('ops-view-logs')
|
|
|
|
|
export class OpsViewLogs extends DeesElement {
|
|
|
|
|
@state()
|
2026-02-01 19:21:37 +00:00
|
|
|
accessor logState: appstate.ILogState = {
|
feat: Add operations view components for logs, overview, security, and stats
- Implemented `ops-view-logs` for displaying and filtering logs with streaming capabilities.
- Created `ops-view-overview` to show server, email, DNS statistics, and charts.
- Developed `ops-view-security` for monitoring security metrics, blocked IPs, and authentication attempts.
- Added `ops-view-stats` to present comprehensive statistics on server, email, DNS, and security metrics.
- Introduced shared styles and components including `ops-sectionheading` for consistent UI.
2025-06-08 12:03:17 +00:00
|
|
|
recentLogs: [],
|
|
|
|
|
isStreaming: false,
|
|
|
|
|
filters: {},
|
|
|
|
|
};
|
|
|
|
|
|
2026-02-21 14:02:48 +00:00
|
|
|
private lastPushedCount = 0;
|
|
|
|
|
|
feat: Add operations view components for logs, overview, security, and stats
- Implemented `ops-view-logs` for displaying and filtering logs with streaming capabilities.
- Created `ops-view-overview` to show server, email, DNS statistics, and charts.
- Developed `ops-view-security` for monitoring security metrics, blocked IPs, and authentication attempts.
- Added `ops-view-stats` to present comprehensive statistics on server, email, DNS, and security metrics.
- Introduced shared styles and components including `ops-sectionheading` for consistent UI.
2025-06-08 12:03:17 +00:00
|
|
|
constructor() {
|
|
|
|
|
super();
|
|
|
|
|
const subscription = appstate.logStatePart
|
|
|
|
|
.select((stateArg) => stateArg)
|
|
|
|
|
.subscribe((logState) => {
|
|
|
|
|
this.logState = logState;
|
|
|
|
|
});
|
|
|
|
|
this.rxSubscriptions.push(subscription);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static styles = [
|
|
|
|
|
cssManager.defaultStyles,
|
|
|
|
|
shared.viewHostCss,
|
2026-02-22 00:45:01 +00:00
|
|
|
css``,
|
feat: Add operations view components for logs, overview, security, and stats
- Implemented `ops-view-logs` for displaying and filtering logs with streaming capabilities.
- Created `ops-view-overview` to show server, email, DNS statistics, and charts.
- Developed `ops-view-security` for monitoring security metrics, blocked IPs, and authentication attempts.
- Added `ops-view-stats` to present comprehensive statistics on server, email, DNS, and security metrics.
- Introduced shared styles and components including `ops-sectionheading` for consistent UI.
2025-06-08 12:03:17 +00:00
|
|
|
];
|
|
|
|
|
|
|
|
|
|
public render() {
|
|
|
|
|
return html`
|
|
|
|
|
<ops-sectionheading>Logs</ops-sectionheading>
|
2026-02-20 12:55:20 +00:00
|
|
|
|
|
|
|
|
<dees-chart-log
|
|
|
|
|
.label=${'Application Logs'}
|
|
|
|
|
.autoScroll=${true}
|
|
|
|
|
.maxEntries=${2000}
|
|
|
|
|
.showMetrics=${true}
|
|
|
|
|
></dees-chart-log>
|
feat: Add operations view components for logs, overview, security, and stats
- Implemented `ops-view-logs` for displaying and filtering logs with streaming capabilities.
- Created `ops-view-overview` to show server, email, DNS statistics, and charts.
- Developed `ops-view-security` for monitoring security metrics, blocked IPs, and authentication attempts.
- Added `ops-view-stats` to present comprehensive statistics on server, email, DNS, and security metrics.
- Introduced shared styles and components including `ops-sectionheading` for consistent UI.
2025-06-08 12:03:17 +00:00
|
|
|
`;
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-19 17:23:43 +00:00
|
|
|
async connectedCallback() {
|
|
|
|
|
super.connectedCallback();
|
2026-02-21 14:02:48 +00:00
|
|
|
this.lastPushedCount = 0;
|
|
|
|
|
// Only fetch if state is empty (streaming will handle new entries)
|
|
|
|
|
if (this.logState.recentLogs.length === 0) {
|
2026-02-22 00:45:01 +00:00
|
|
|
await appstate.logStatePart.dispatchAction(appstate.fetchRecentLogsAction, { limit: 100 });
|
2026-02-21 14:02:48 +00:00
|
|
|
}
|
2026-02-19 17:23:43 +00:00
|
|
|
}
|
|
|
|
|
|
2026-02-20 12:55:20 +00:00
|
|
|
async updated(changedProperties: Map<string, any>) {
|
|
|
|
|
super.updated(changedProperties);
|
|
|
|
|
if (changedProperties.has('logState')) {
|
|
|
|
|
this.pushLogsToChart();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private async pushLogsToChart() {
|
|
|
|
|
const chartLog = this.shadowRoot?.querySelector('dees-chart-log') as any;
|
|
|
|
|
if (!chartLog) return;
|
|
|
|
|
|
|
|
|
|
// Ensure the chart element has finished its own initialization
|
|
|
|
|
await chartLog.updateComplete;
|
|
|
|
|
|
2026-02-21 18:13:10 +00:00
|
|
|
// Wait for xterm terminal to finish initializing (CDN load)
|
|
|
|
|
if (!chartLog.terminalReady) {
|
|
|
|
|
await new Promise<void>((resolve) => {
|
|
|
|
|
const check = () => {
|
|
|
|
|
if (chartLog.terminalReady) { resolve(); return; }
|
|
|
|
|
setTimeout(check, 50);
|
|
|
|
|
};
|
|
|
|
|
check();
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-21 14:02:48 +00:00
|
|
|
const allEntries = this.getMappedLogEntries();
|
|
|
|
|
if (this.lastPushedCount === 0 && allEntries.length > 0) {
|
|
|
|
|
// Initial load: push all entries
|
|
|
|
|
chartLog.updateLog(allEntries);
|
|
|
|
|
this.lastPushedCount = allEntries.length;
|
|
|
|
|
} else if (allEntries.length > this.lastPushedCount) {
|
|
|
|
|
// Incremental: only push new entries
|
|
|
|
|
const newEntries = allEntries.slice(this.lastPushedCount);
|
|
|
|
|
chartLog.updateLog(newEntries);
|
|
|
|
|
this.lastPushedCount = allEntries.length;
|
2026-02-20 12:55:20 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private getMappedLogEntries() {
|
|
|
|
|
return this.logState.recentLogs.map((log) => ({
|
|
|
|
|
timestamp: new Date(log.timestamp).toISOString(),
|
|
|
|
|
level: log.level as 'debug' | 'info' | 'warn' | 'error',
|
|
|
|
|
message: log.message,
|
|
|
|
|
source: log.category,
|
|
|
|
|
}));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|