feat(admin-ui): introduce view layer and refactor admin UI to use view components, consolidate demos, and update interfaces
This commit is contained in:
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