mirror of
https://github.com/Termix-SSH/Termix.git
synced 2026-10-30 15:15:24 +00:00
feat: replace core homepage widget registry with generic extension points
This commit is contained in:
1 parent
b8bbcd2196
commit
50d43e29fb
18 files changed
+242
-147
No files matched your search
@@ -10,7 +10,11 @@ import { HomepagePreviewCard } from "./HomepagePreviewCard.js";
|
||||
import { ServiceLinksCard } from "./ServiceLinksCard.js";
|
||||
import { DashboardHomepageView } from "./DashboardHomepageView.js";
|
||||
import { setHomepageApi } from "./api.js";
|
||||
import { drainQueuedWidgets } from "./widgets/WidgetRegistry.js";
|
||||
import {
|
||||
WIDGET_POINT,
|
||||
drainQueuedWidgets,
|
||||
toExtension,
|
||||
} from "./widgets/WidgetRegistry.js";
|
||||
|
||||
// Side-effect imports so widgets register themselves.
|
||||
import "./widgets/ServiceLinkWidget";
|
||||
@@ -54,7 +58,7 @@ export function activate(app: TermixApp): void {
|
||||
app.onDispose(() => setHomepageApi(null));
|
||||
|
||||
for (const widget of drainQueuedWidgets()) {
|
||||
app.registerHomepageWidget(widget as never);
|
||||
app.registerExtension(WIDGET_POINT, toExtension(widget));
|
||||
}
|
||||
|
||||
app.registerTab("homepage", HomepageTab as ComponentType<TabProps>, {
|
||||
|
||||
@@ -1,16 +1,22 @@
|
||||
import {
|
||||
homepageWidgetType,
|
||||
useHomepageWidgetTypes,
|
||||
type HomepageWidgetContribution,
|
||||
getExtension,
|
||||
useExtensions,
|
||||
type ExtensionContribution,
|
||||
} from "@termix/plugin-sdk/frontend";
|
||||
import { useMemo } from "react";
|
||||
import type { WidgetTypeDefinition, WidgetTypeId } from "../types.js";
|
||||
|
||||
/**
|
||||
* Other plugins add widgets with app.registerExtension(WIDGET_POINT, ...),
|
||||
* putting the widget under components.view and its edit form under
|
||||
* components.editForm. Core only stores the list, so a plugin's widgets
|
||||
* stay registered while this plugin is off.
|
||||
*/
|
||||
export const WIDGET_POINT = "homepage.widgets";
|
||||
|
||||
/**
|
||||
* Each widget module calls this at import time (before activate(app) runs),
|
||||
* so the definitions are queued here and app.registerHomepageWidget is
|
||||
* called for each one from activate. Core owns the actual registry, the same
|
||||
* one other plugins (docker, tunnels, host-metrics, file-manager) register
|
||||
* their own widgets into.
|
||||
* so the definitions are queued here and registered from activate.
|
||||
*/
|
||||
const queued: WidgetTypeDefinition[] = [];
|
||||
|
||||
@@ -23,18 +29,42 @@ export function drainQueuedWidgets(): WidgetTypeDefinition[] {
|
||||
return queued.splice(0, queued.length);
|
||||
}
|
||||
|
||||
export function toExtension(def: WidgetTypeDefinition): ExtensionContribution {
|
||||
const { component, editFormComponent, ...rest } = def;
|
||||
return {
|
||||
...rest,
|
||||
components: editFormComponent
|
||||
? { view: component, editForm: editFormComponent }
|
||||
: { view: component },
|
||||
};
|
||||
}
|
||||
|
||||
function toDefinition(
|
||||
widget: HomepageWidgetContribution | undefined,
|
||||
extension: ExtensionContribution | undefined,
|
||||
): WidgetTypeDefinition | undefined {
|
||||
return widget as unknown as WidgetTypeDefinition | undefined;
|
||||
const view = extension?.components?.view;
|
||||
if (!extension || !view) return undefined;
|
||||
const { components, ...rest } = extension;
|
||||
return {
|
||||
...(rest as unknown as WidgetTypeDefinition),
|
||||
component: view,
|
||||
editFormComponent: components?.editForm,
|
||||
};
|
||||
}
|
||||
|
||||
export function getWidgetType(
|
||||
id: WidgetTypeId,
|
||||
): WidgetTypeDefinition | undefined {
|
||||
return toDefinition(homepageWidgetType(id));
|
||||
return toDefinition(getExtension(WIDGET_POINT, id));
|
||||
}
|
||||
|
||||
export function useWidgetTypes(): WidgetTypeDefinition[] {
|
||||
return useHomepageWidgetTypes() as unknown as WidgetTypeDefinition[];
|
||||
const extensions = useExtensions(WIDGET_POINT);
|
||||
return useMemo(
|
||||
() =>
|
||||
extensions
|
||||
.map(toDefinition)
|
||||
.filter((def): def is WidgetTypeDefinition => !!def),
|
||||
[extensions],
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user