Sprint 8: add widget manifest and data source engine
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
import { Type } from '@angular/core';
|
||||
import { WidgetConfig } from '../../shared/models/config';
|
||||
import { SectionConfig } from '../../shared/models/config';
|
||||
|
||||
export interface WidgetRenderNode {
|
||||
id: string;
|
||||
@@ -9,3 +11,11 @@ export interface WidgetRenderNode {
|
||||
visible?: boolean;
|
||||
source: WidgetConfig;
|
||||
}
|
||||
|
||||
export interface ResolvedWidgetRenderNode {
|
||||
type: string;
|
||||
version: string;
|
||||
component: Type<unknown>;
|
||||
section: SectionConfig;
|
||||
data: unknown;
|
||||
}
|
||||
|
||||
@@ -1,23 +1,77 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { WidgetConfig } from '../../shared/models/config';
|
||||
import { WidgetRegistryService } from '../../widgets/registry/widget-registry.service';
|
||||
import { Observable, map, shareReplay } from 'rxjs';
|
||||
import { WidgetConfig, SectionConfig } from '../../shared/models/config';
|
||||
import { ConfigService } from '../../core/config/config.service';
|
||||
import { RuntimeDiagnosticsService } from '../../core/runtime/runtime-diagnostics.service';
|
||||
import { UnknownWidgetComponent } from '../../widgets/ui';
|
||||
import { ResolvedWidget } from '../../widgets/contracts/widget-component.contract';
|
||||
import { DataSourceResolverService } from '../../widgets/resolvers/data-source-resolver.service';
|
||||
import { WidgetRegistryService } from '../../widgets/registry/widget-registry.service';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class WidgetHostService {
|
||||
constructor(private readonly registry: WidgetRegistryService) {}
|
||||
private readonly resolvedWidgets = new Map<string, Observable<ResolvedWidget>>();
|
||||
private readonly loggedUnknownWidgets = new Set<string>();
|
||||
|
||||
resolveWidget(widget: WidgetConfig): ResolvedWidget | null {
|
||||
const registered = this.registry.resolve(widget.type, widget.version);
|
||||
if (!registered) {
|
||||
return null;
|
||||
constructor(
|
||||
private readonly registry: WidgetRegistryService,
|
||||
private readonly dataSourceResolver: DataSourceResolverService,
|
||||
private readonly diagnostics: RuntimeDiagnosticsService,
|
||||
private readonly configService: ConfigService
|
||||
) {}
|
||||
|
||||
resolveWidget(widget: WidgetConfig, section: SectionConfig, pageId: string): Observable<ResolvedWidget> {
|
||||
const cacheKey = `${pageId}:${section.id}:${widget.id}`;
|
||||
const cached = this.resolvedWidgets.get(cacheKey);
|
||||
if (cached) {
|
||||
return cached;
|
||||
}
|
||||
|
||||
return {
|
||||
type: registered.type,
|
||||
version: registered.version,
|
||||
component: registered.component,
|
||||
props: widget.props ?? {}
|
||||
};
|
||||
const registered = this.registry.resolve(widget.type, widget.version);
|
||||
const resolved$ = this.dataSourceResolver.resolve(widget, section).pipe(
|
||||
map((data) => {
|
||||
if (!registered) {
|
||||
this.logUnknownWidget(pageId, section.id, widget);
|
||||
|
||||
return {
|
||||
type: widget.type,
|
||||
version: widget.version,
|
||||
component: UnknownWidgetComponent,
|
||||
section,
|
||||
data
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
type: registered.type,
|
||||
version: registered.version,
|
||||
component: registered.component,
|
||||
section,
|
||||
data
|
||||
};
|
||||
}),
|
||||
shareReplay({ bufferSize: 1, refCount: true })
|
||||
);
|
||||
|
||||
this.resolvedWidgets.set(cacheKey, resolved$);
|
||||
return resolved$;
|
||||
}
|
||||
|
||||
private logUnknownWidget(pageId: string, sectionId: string, widget: WidgetConfig): void {
|
||||
const diagnosticKey = `${pageId}:${sectionId}:${widget.id}`;
|
||||
if (this.loggedUnknownWidgets.has(diagnosticKey)) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.loggedUnknownWidgets.add(diagnosticKey);
|
||||
|
||||
const tenantId = this.configService.getBootstrapSnapshot()?.tenant.id ?? 'unknown';
|
||||
this.diagnostics.logUnknownWidget({
|
||||
tenant: tenantId,
|
||||
page: pageId,
|
||||
section: sectionId,
|
||||
widget: `${widget.type}@${widget.version}`,
|
||||
reason: 'not_registered_in_widget_registry'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user