feat(admin-ui): introduce view layer and refactor admin UI to use view components, consolidate demos, and update interfaces
This commit is contained in:
4
ts_web/views/index.ts
Normal file
4
ts_web/views/index.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export * from './upladmin-dashboard-view/upladmin-dashboard-view.js';
|
||||
export * from './upladmin-monitors-view/upladmin-monitors-view.js';
|
||||
export * from './upladmin-incidents-view/upladmin-incidents-view.js';
|
||||
export * from './upladmin-config-view/upladmin-config-view.js';
|
||||
124
ts_web/views/upladmin-config-view/upladmin-config-view.ts
Normal file
124
ts_web/views/upladmin-config-view/upladmin-config-view.ts
Normal file
@@ -0,0 +1,124 @@
|
||||
import {
|
||||
DeesElement,
|
||||
customElement,
|
||||
html,
|
||||
state,
|
||||
css,
|
||||
cssManager,
|
||||
} from '@design.estate/dees-element';
|
||||
import type { DeesAppuiBase } from '@design.estate/dees-catalog';
|
||||
|
||||
// View lifecycle interfaces (defined locally as they're not exported from dees-catalog)
|
||||
interface IViewActivationContext {
|
||||
appui: DeesAppuiBase;
|
||||
viewId: string;
|
||||
params?: Record<string, string>;
|
||||
}
|
||||
|
||||
interface IViewLifecycle {
|
||||
onActivate?: (context: IViewActivationContext) => void | Promise<void>;
|
||||
onDeactivate?: () => void | Promise<void>;
|
||||
}
|
||||
import { adminState } from '../../services/admin-state.js';
|
||||
import '../../elements/upladmin-statuspage-config/upladmin-statuspage-config.js';
|
||||
|
||||
type TConfigSection = 'branding' | 'urls' | 'behavior' | 'advanced';
|
||||
|
||||
@customElement('upladmin-config-view')
|
||||
export class UpladminConfigView extends DeesElement implements IViewLifecycle {
|
||||
@state()
|
||||
accessor activeSection: TConfigSection = 'branding';
|
||||
|
||||
@state()
|
||||
accessor loading: boolean = false;
|
||||
|
||||
private appuiRef: DeesAppuiBase | null = null;
|
||||
|
||||
public static styles = [
|
||||
cssManager.defaultStyles,
|
||||
css`
|
||||
:host {
|
||||
display: block;
|
||||
height: 100%;
|
||||
}
|
||||
`,
|
||||
];
|
||||
|
||||
async onActivate(context: IViewActivationContext): Promise<void> {
|
||||
this.appuiRef = context.appui;
|
||||
|
||||
// Check route params for section
|
||||
if (context.params?.section) {
|
||||
const section = context.params.section as TConfigSection;
|
||||
if (['branding', 'urls', 'behavior', 'advanced'].includes(section)) {
|
||||
this.activeSection = section;
|
||||
}
|
||||
}
|
||||
|
||||
// Set secondary menu for configuration sections
|
||||
this.updateSecondaryMenu();
|
||||
|
||||
// No content tabs for config
|
||||
context.appui.setContentTabs([]);
|
||||
}
|
||||
|
||||
private updateSecondaryMenu(): void {
|
||||
if (!this.appuiRef) return;
|
||||
|
||||
this.appuiRef.setSecondaryMenu({
|
||||
heading: 'Configuration',
|
||||
groups: [
|
||||
{
|
||||
name: 'Settings',
|
||||
iconName: 'lucide:settings',
|
||||
items: [
|
||||
{
|
||||
key: 'branding',
|
||||
iconName: 'lucide:palette',
|
||||
action: () => this.setSection('branding'),
|
||||
},
|
||||
{
|
||||
key: 'urls',
|
||||
iconName: 'lucide:link',
|
||||
action: () => this.setSection('urls'),
|
||||
},
|
||||
{
|
||||
key: 'behavior',
|
||||
iconName: 'lucide:sliders',
|
||||
action: () => this.setSection('behavior'),
|
||||
},
|
||||
{
|
||||
key: 'advanced',
|
||||
iconName: 'lucide:wrench',
|
||||
action: () => this.setSection('advanced'),
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
// Select current section
|
||||
this.appuiRef.setSecondaryMenuSelection(this.activeSection);
|
||||
}
|
||||
|
||||
private setSection(section: TConfigSection): void {
|
||||
this.activeSection = section;
|
||||
this.appuiRef?.setSecondaryMenuSelection(section);
|
||||
}
|
||||
|
||||
private handleConfigSave = (e: CustomEvent): void => {
|
||||
console.log('Config saved:', e.detail);
|
||||
// In a real implementation, this would save to the backend
|
||||
};
|
||||
|
||||
render() {
|
||||
return html`
|
||||
<upladmin-statuspage-config
|
||||
.config=${adminState.config || {}}
|
||||
.activeSection=${this.activeSection}
|
||||
.loading=${this.loading}
|
||||
@configSave=${this.handleConfigSave}
|
||||
></upladmin-statuspage-config>
|
||||
`;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
import {
|
||||
DeesElement,
|
||||
customElement,
|
||||
html,
|
||||
state,
|
||||
css,
|
||||
cssManager,
|
||||
} from '@design.estate/dees-element';
|
||||
import type { DeesAppuiBase } from '@design.estate/dees-catalog';
|
||||
|
||||
// View lifecycle interfaces (defined locally as they're not exported from dees-catalog)
|
||||
interface IViewActivationContext {
|
||||
appui: DeesAppuiBase;
|
||||
viewId: string;
|
||||
params?: Record<string, string>;
|
||||
}
|
||||
|
||||
interface IViewLifecycle {
|
||||
onActivate?: (context: IViewActivationContext) => void | Promise<void>;
|
||||
onDeactivate?: () => void | Promise<void>;
|
||||
}
|
||||
import { adminState } from '../../services/admin-state.js';
|
||||
import '../../elements/upladmin-dashboard/upladmin-dashboard.js';
|
||||
|
||||
@customElement('upladmin-dashboard-view')
|
||||
export class UpladminDashboardView extends DeesElement implements IViewLifecycle {
|
||||
@state()
|
||||
accessor loading: boolean = true;
|
||||
|
||||
public static styles = [
|
||||
cssManager.defaultStyles,
|
||||
css`
|
||||
:host {
|
||||
display: block;
|
||||
height: 100%;
|
||||
}
|
||||
`,
|
||||
];
|
||||
|
||||
async onActivate(context: IViewActivationContext): Promise<void> {
|
||||
// Dashboard has no secondary menu - clear any existing
|
||||
context.appui.clearSecondaryMenu();
|
||||
|
||||
// No content tabs for dashboard
|
||||
context.appui.setContentTabs([]);
|
||||
|
||||
// Load data
|
||||
this.loading = false;
|
||||
}
|
||||
|
||||
render() {
|
||||
return html`
|
||||
<upladmin-dashboard
|
||||
.monitors=${adminState.monitors}
|
||||
.incidents=${adminState.incidents}
|
||||
.loading=${this.loading}
|
||||
></upladmin-dashboard>
|
||||
`;
|
||||
}
|
||||
}
|
||||
292
ts_web/views/upladmin-incidents-view/upladmin-incidents-view.ts
Normal file
292
ts_web/views/upladmin-incidents-view/upladmin-incidents-view.ts
Normal file
@@ -0,0 +1,292 @@
|
||||
import {
|
||||
DeesElement,
|
||||
customElement,
|
||||
html,
|
||||
state,
|
||||
css,
|
||||
cssManager,
|
||||
} from '@design.estate/dees-element';
|
||||
import type { DeesAppuiBase } from '@design.estate/dees-catalog';
|
||||
|
||||
// View lifecycle interfaces (defined locally as they're not exported from dees-catalog)
|
||||
interface IViewActivationContext {
|
||||
appui: DeesAppuiBase;
|
||||
viewId: string;
|
||||
params?: Record<string, string>;
|
||||
}
|
||||
|
||||
interface IViewLifecycle {
|
||||
onActivate?: (context: IViewActivationContext) => void | Promise<void>;
|
||||
onDeactivate?: () => void | Promise<void>;
|
||||
}
|
||||
import { adminState } from '../../services/admin-state.js';
|
||||
import type { IIncidentDetails, TIncidentSeverity, TIncidentStatus } from '../../interfaces/index.js';
|
||||
import '../../elements/upladmin-incident-list/upladmin-incident-list.js';
|
||||
import '../../elements/upladmin-incident-form/upladmin-incident-form.js';
|
||||
import '../../elements/upladmin-incident-update/upladmin-incident-update.js';
|
||||
|
||||
type TViewMode = 'list' | 'form' | 'update';
|
||||
type TTimeFilter = 'current' | 'past' | 'all';
|
||||
|
||||
@customElement('upladmin-incidents-view')
|
||||
export class UpladminIncidentsView extends DeesElement implements IViewLifecycle {
|
||||
@state()
|
||||
accessor currentMode: TViewMode = 'list';
|
||||
|
||||
@state()
|
||||
accessor selectedIncidentId: string | null = null;
|
||||
|
||||
@state()
|
||||
accessor timeFilter: TTimeFilter = 'current';
|
||||
|
||||
@state()
|
||||
accessor severityFilter: TIncidentSeverity | 'all' = 'all';
|
||||
|
||||
@state()
|
||||
accessor loading: boolean = false;
|
||||
|
||||
private appuiRef: DeesAppuiBase | null = null;
|
||||
|
||||
public static styles = [
|
||||
cssManager.defaultStyles,
|
||||
css`
|
||||
:host {
|
||||
display: block;
|
||||
height: 100%;
|
||||
}
|
||||
`,
|
||||
];
|
||||
|
||||
async onActivate(context: IViewActivationContext): Promise<void> {
|
||||
this.appuiRef = context.appui;
|
||||
|
||||
// Check route params and view ID
|
||||
if (context.params?.id) {
|
||||
if (context.viewId === 'incident-update') {
|
||||
this.currentMode = 'update';
|
||||
this.selectedIncidentId = context.params.id;
|
||||
} else {
|
||||
this.currentMode = 'form';
|
||||
this.selectedIncidentId = context.params.id === 'create' ? null : context.params.id;
|
||||
}
|
||||
} else {
|
||||
this.currentMode = 'list';
|
||||
this.selectedIncidentId = null;
|
||||
}
|
||||
|
||||
// Set secondary menu
|
||||
this.updateSecondaryMenu();
|
||||
|
||||
// No content tabs - incident-list has internal tabs
|
||||
context.appui.setContentTabs([]);
|
||||
}
|
||||
|
||||
private updateSecondaryMenu(): void {
|
||||
if (!this.appuiRef) return;
|
||||
|
||||
const activeCount = adminState.getActiveIncidents().length;
|
||||
const pastCount = adminState.incidents.filter((i) => i.status === 'resolved' || i.status === 'postmortem').length;
|
||||
|
||||
this.appuiRef.setSecondaryMenu({
|
||||
heading: 'Incidents',
|
||||
groups: [
|
||||
{
|
||||
name: 'Filter',
|
||||
iconName: 'lucide:filter',
|
||||
items: [
|
||||
{
|
||||
key: 'current',
|
||||
iconName: 'lucide:alertCircle',
|
||||
action: () => this.setTimeFilter('current'),
|
||||
badge: activeCount,
|
||||
badgeVariant: activeCount > 0 ? 'error' : 'default',
|
||||
},
|
||||
{
|
||||
key: 'past',
|
||||
iconName: 'lucide:history',
|
||||
action: () => this.setTimeFilter('past'),
|
||||
badge: pastCount,
|
||||
},
|
||||
{
|
||||
key: 'all',
|
||||
iconName: 'lucide:list',
|
||||
action: () => this.setTimeFilter('all'),
|
||||
badge: adminState.incidents.length,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'Severity',
|
||||
iconName: 'lucide:alertTriangle',
|
||||
collapsed: true,
|
||||
items: [
|
||||
{
|
||||
key: 'critical',
|
||||
iconName: 'lucide:xCircle',
|
||||
action: () => this.setSeverityFilter('critical'),
|
||||
},
|
||||
{
|
||||
key: 'major',
|
||||
iconName: 'lucide:alertOctagon',
|
||||
action: () => this.setSeverityFilter('major'),
|
||||
},
|
||||
{
|
||||
key: 'minor',
|
||||
iconName: 'lucide:alertTriangle',
|
||||
action: () => this.setSeverityFilter('minor'),
|
||||
},
|
||||
{
|
||||
key: 'maintenance',
|
||||
iconName: 'lucide:wrench',
|
||||
action: () => this.setSeverityFilter('maintenance'),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'Actions',
|
||||
iconName: 'lucide:zap',
|
||||
items: [
|
||||
{
|
||||
key: 'create',
|
||||
iconName: 'lucide:plus',
|
||||
action: () => this.showForm(null),
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
// Select current filter
|
||||
this.appuiRef.setSecondaryMenuSelection(this.timeFilter);
|
||||
}
|
||||
|
||||
private setTimeFilter(filter: TTimeFilter): void {
|
||||
this.timeFilter = filter;
|
||||
this.severityFilter = 'all';
|
||||
this.appuiRef?.setSecondaryMenuSelection(filter);
|
||||
}
|
||||
|
||||
private setSeverityFilter(severity: TIncidentSeverity): void {
|
||||
this.severityFilter = severity;
|
||||
this.appuiRef?.setSecondaryMenuSelection(severity);
|
||||
}
|
||||
|
||||
private showForm(incidentId: string | null): void {
|
||||
this.currentMode = 'form';
|
||||
this.selectedIncidentId = incidentId;
|
||||
}
|
||||
|
||||
private showUpdate(incidentId: string): void {
|
||||
this.currentMode = 'update';
|
||||
this.selectedIncidentId = incidentId;
|
||||
}
|
||||
|
||||
private showList(): void {
|
||||
this.currentMode = 'list';
|
||||
this.selectedIncidentId = null;
|
||||
}
|
||||
|
||||
private get filteredIncidents(): IIncidentDetails[] {
|
||||
let incidents = adminState.incidents;
|
||||
|
||||
// Apply time filter
|
||||
if (this.timeFilter === 'current') {
|
||||
incidents = incidents.filter(
|
||||
(i) => i.status !== 'resolved' && i.status !== 'postmortem'
|
||||
);
|
||||
} else if (this.timeFilter === 'past') {
|
||||
incidents = incidents.filter(
|
||||
(i) => i.status === 'resolved' || i.status === 'postmortem'
|
||||
);
|
||||
}
|
||||
|
||||
// Apply severity filter
|
||||
if (this.severityFilter !== 'all') {
|
||||
incidents = incidents.filter((i) => i.severity === this.severityFilter);
|
||||
}
|
||||
|
||||
return incidents;
|
||||
}
|
||||
|
||||
private handleIncidentSave = (e: CustomEvent): void => {
|
||||
console.log('Incident saved:', e.detail);
|
||||
this.showList();
|
||||
};
|
||||
|
||||
private handleUpdateSave = (e: CustomEvent): void => {
|
||||
console.log('Update saved:', e.detail);
|
||||
this.showList();
|
||||
};
|
||||
|
||||
private handleCancel = (): void => {
|
||||
this.showList();
|
||||
};
|
||||
|
||||
private handleIncidentEdit = (e: CustomEvent): void => {
|
||||
const incident = e.detail?.incident as IIncidentDetails;
|
||||
if (incident) {
|
||||
this.showForm(incident.id);
|
||||
}
|
||||
};
|
||||
|
||||
private handleIncidentAddUpdate = (e: CustomEvent): void => {
|
||||
const incident = e.detail?.incident as IIncidentDetails;
|
||||
if (incident) {
|
||||
this.showUpdate(incident.id);
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
if (this.currentMode === 'update') {
|
||||
const incident = this.selectedIncidentId
|
||||
? adminState.incidents.find((i) => i.id === this.selectedIncidentId)
|
||||
: null;
|
||||
|
||||
return html`
|
||||
<upladmin-incident-update
|
||||
.incident=${incident}
|
||||
.loading=${this.loading}
|
||||
@updateSave=${this.handleUpdateSave}
|
||||
@cancel=${this.handleCancel}
|
||||
></upladmin-incident-update>
|
||||
`;
|
||||
}
|
||||
|
||||
if (this.currentMode === 'form') {
|
||||
const incident = this.selectedIncidentId
|
||||
? adminState.incidents.find((i) => i.id === this.selectedIncidentId)
|
||||
: null;
|
||||
|
||||
return html`
|
||||
<upladmin-incident-form
|
||||
.incident=${incident
|
||||
? {
|
||||
id: incident.id,
|
||||
title: incident.title,
|
||||
severity: incident.severity,
|
||||
status: incident.status,
|
||||
affectedServices: incident.affectedServices,
|
||||
impact: incident.impact,
|
||||
rootCause: incident.rootCause,
|
||||
resolution: incident.resolution,
|
||||
}
|
||||
: null}
|
||||
.availableServices=${adminState.monitors}
|
||||
.loading=${this.loading}
|
||||
@incidentSave=${this.handleIncidentSave}
|
||||
@cancel=${this.handleCancel}
|
||||
></upladmin-incident-form>
|
||||
`;
|
||||
}
|
||||
|
||||
return html`
|
||||
<upladmin-incident-list
|
||||
.incidents=${this.filteredIncidents}
|
||||
.loading=${this.loading}
|
||||
@incidentAdd=${() => this.showForm(null)}
|
||||
@incidentEdit=${this.handleIncidentEdit}
|
||||
@incidentAddUpdate=${this.handleIncidentAddUpdate}
|
||||
></upladmin-incident-list>
|
||||
`;
|
||||
}
|
||||
}
|
||||
244
ts_web/views/upladmin-monitors-view/upladmin-monitors-view.ts
Normal file
244
ts_web/views/upladmin-monitors-view/upladmin-monitors-view.ts
Normal file
@@ -0,0 +1,244 @@
|
||||
import {
|
||||
DeesElement,
|
||||
customElement,
|
||||
html,
|
||||
state,
|
||||
css,
|
||||
cssManager,
|
||||
} from '@design.estate/dees-element';
|
||||
import type { DeesAppuiBase } from '@design.estate/dees-catalog';
|
||||
|
||||
// View lifecycle interfaces (defined locally as they're not exported from dees-catalog)
|
||||
interface IViewActivationContext {
|
||||
appui: DeesAppuiBase;
|
||||
viewId: string;
|
||||
params?: Record<string, string>;
|
||||
}
|
||||
|
||||
interface IViewLifecycle {
|
||||
onActivate?: (context: IViewActivationContext) => void | Promise<void>;
|
||||
onDeactivate?: () => void | Promise<void>;
|
||||
}
|
||||
import { adminState } from '../../services/admin-state.js';
|
||||
import type { IServiceStatus, TStatusType } from '../../interfaces/index.js';
|
||||
import '../../elements/upladmin-monitor-list/upladmin-monitor-list.js';
|
||||
import '../../elements/upladmin-monitor-form/upladmin-monitor-form.js';
|
||||
|
||||
type TViewMode = 'list' | 'form';
|
||||
type TStatusFilter = 'all' | 'issues' | 'maintenance';
|
||||
|
||||
@customElement('upladmin-monitors-view')
|
||||
export class UpladminMonitorsView extends DeesElement implements IViewLifecycle {
|
||||
@state()
|
||||
accessor currentMode: TViewMode = 'list';
|
||||
|
||||
@state()
|
||||
accessor selectedMonitorId: string | null = null;
|
||||
|
||||
@state()
|
||||
accessor statusFilter: TStatusFilter = 'all';
|
||||
|
||||
@state()
|
||||
accessor categoryFilter: string = 'all';
|
||||
|
||||
@state()
|
||||
accessor loading: boolean = false;
|
||||
|
||||
private appuiRef: DeesAppuiBase | null = null;
|
||||
|
||||
public static styles = [
|
||||
cssManager.defaultStyles,
|
||||
css`
|
||||
:host {
|
||||
display: block;
|
||||
height: 100%;
|
||||
}
|
||||
`,
|
||||
];
|
||||
|
||||
async onActivate(context: IViewActivationContext): Promise<void> {
|
||||
this.appuiRef = context.appui;
|
||||
|
||||
// Check route params for edit mode
|
||||
if (context.params?.id) {
|
||||
this.currentMode = 'form';
|
||||
this.selectedMonitorId = context.params.id === 'create' ? null : context.params.id;
|
||||
} else {
|
||||
this.currentMode = 'list';
|
||||
this.selectedMonitorId = null;
|
||||
}
|
||||
|
||||
// Set secondary menu with categories
|
||||
this.updateSecondaryMenu();
|
||||
|
||||
// Set content tabs for status filtering
|
||||
context.appui.setContentTabs([
|
||||
{
|
||||
key: 'All',
|
||||
iconName: 'lucide:activity',
|
||||
action: () => this.setStatusFilter('all'),
|
||||
},
|
||||
{
|
||||
key: 'Issues',
|
||||
iconName: 'lucide:alertTriangle',
|
||||
action: () => this.setStatusFilter('issues'),
|
||||
},
|
||||
{
|
||||
key: 'Maintenance',
|
||||
iconName: 'lucide:wrench',
|
||||
action: () => this.setStatusFilter('maintenance'),
|
||||
},
|
||||
]);
|
||||
}
|
||||
|
||||
private updateSecondaryMenu(): void {
|
||||
if (!this.appuiRef) return;
|
||||
|
||||
const categories = this.getCategories();
|
||||
|
||||
this.appuiRef.setSecondaryMenu({
|
||||
heading: 'Monitors',
|
||||
groups: [
|
||||
{
|
||||
name: 'Categories',
|
||||
iconName: 'lucide:folder',
|
||||
items: [
|
||||
{
|
||||
key: 'all',
|
||||
iconName: 'lucide:list',
|
||||
action: () => this.setCategoryFilter('all'),
|
||||
badge: adminState.monitors.length,
|
||||
},
|
||||
...categories.map((cat) => ({
|
||||
key: cat,
|
||||
iconName: 'lucide:folder',
|
||||
action: () => this.setCategoryFilter(cat),
|
||||
badge: adminState.monitors.filter((m) => m.category === cat).length,
|
||||
})),
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'Actions',
|
||||
iconName: 'lucide:zap',
|
||||
items: [
|
||||
{
|
||||
key: 'add',
|
||||
iconName: 'lucide:plus',
|
||||
action: () => this.showForm(null),
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
// Select current category
|
||||
this.appuiRef.setSecondaryMenuSelection(this.categoryFilter);
|
||||
}
|
||||
|
||||
private getCategories(): string[] {
|
||||
const cats = new Set<string>();
|
||||
for (const m of adminState.monitors) {
|
||||
if (m.category) cats.add(m.category);
|
||||
}
|
||||
return Array.from(cats).sort();
|
||||
}
|
||||
|
||||
private setStatusFilter(filter: TStatusFilter): void {
|
||||
this.statusFilter = filter;
|
||||
}
|
||||
|
||||
private setCategoryFilter(category: string): void {
|
||||
this.categoryFilter = category;
|
||||
this.appuiRef?.setSecondaryMenuSelection(category);
|
||||
}
|
||||
|
||||
private showForm(monitorId: string | null): void {
|
||||
this.currentMode = 'form';
|
||||
this.selectedMonitorId = monitorId;
|
||||
}
|
||||
|
||||
private showList(): void {
|
||||
this.currentMode = 'list';
|
||||
this.selectedMonitorId = null;
|
||||
}
|
||||
|
||||
private get filteredMonitors(): IServiceStatus[] {
|
||||
let monitors = adminState.monitors;
|
||||
|
||||
// Apply category filter
|
||||
if (this.categoryFilter !== 'all') {
|
||||
monitors = monitors.filter((m) => m.category === this.categoryFilter);
|
||||
}
|
||||
|
||||
// Apply status filter
|
||||
if (this.statusFilter === 'issues') {
|
||||
monitors = monitors.filter((m) =>
|
||||
['degraded', 'partial_outage', 'major_outage', 'error'].includes(m.currentStatus)
|
||||
);
|
||||
} else if (this.statusFilter === 'maintenance') {
|
||||
monitors = monitors.filter((m) => m.currentStatus === 'maintenance');
|
||||
}
|
||||
|
||||
return monitors;
|
||||
}
|
||||
|
||||
private handleMonitorSave = (e: CustomEvent): void => {
|
||||
// Handle save logic
|
||||
console.log('Monitor saved:', e.detail);
|
||||
this.showList();
|
||||
};
|
||||
|
||||
private handleCancel = (): void => {
|
||||
this.showList();
|
||||
};
|
||||
|
||||
private handleMonitorEdit = (e: CustomEvent): void => {
|
||||
const monitor = e.detail?.monitor as IServiceStatus;
|
||||
if (monitor) {
|
||||
this.showForm(monitor.id);
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
if (this.currentMode === 'form') {
|
||||
const monitor = this.selectedMonitorId
|
||||
? adminState.monitors.find((m) => m.id === this.selectedMonitorId)
|
||||
: null;
|
||||
|
||||
return html`
|
||||
<upladmin-monitor-form
|
||||
.monitor=${monitor
|
||||
? {
|
||||
id: monitor.id,
|
||||
name: monitor.name,
|
||||
displayName: monitor.displayName,
|
||||
description: monitor.description,
|
||||
category: monitor.category,
|
||||
dependencies: monitor.dependencies,
|
||||
statusMode: monitor.statusMode || 'auto',
|
||||
manualStatus: monitor.manualStatus,
|
||||
paused: monitor.paused || false,
|
||||
checkType: monitor.checkType || 'assumption',
|
||||
checkConfig: monitor.checkConfig || { domain: '' },
|
||||
intervalMs: monitor.intervalMs || 60000,
|
||||
}
|
||||
: null}
|
||||
.availableMonitors=${adminState.monitors}
|
||||
.categories=${this.getCategories()}
|
||||
.loading=${this.loading}
|
||||
@monitorSave=${this.handleMonitorSave}
|
||||
@cancel=${this.handleCancel}
|
||||
></upladmin-monitor-form>
|
||||
`;
|
||||
}
|
||||
|
||||
return html`
|
||||
<upladmin-monitor-list
|
||||
.monitors=${this.filteredMonitors}
|
||||
.loading=${this.loading}
|
||||
@monitorAdd=${() => this.showForm(null)}
|
||||
@monitorEdit=${this.handleMonitorEdit}
|
||||
></upladmin-monitor-list>
|
||||
`;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user