mirror of
https://github.com/Termix-SSH/Termix.git
synced 2026-10-28 14:15:24 +00:00
feat: load plugin frontends at runtime and remove plugin ids from the shell
This commit is contained in:
1 parent
49f0286a14
commit
e88d5a52e3
721 files changed
+54265
-44416
No files matched your search
@@ -1,6 +1,6 @@
|
||||
import { getErrorMessage } from "@/lib/error-message.js";
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslation } from "@termix/plugin-sdk/frontend";
|
||||
import { toast } from "sonner";
|
||||
import {
|
||||
ArrowLeft,
|
||||
@@ -35,7 +35,8 @@ import {
|
||||
import { NotificationChannelDialog } from "@/sidebar/NotificationChannelDialog";
|
||||
import { getSnippets } from "@/api/snippets-api";
|
||||
import { getSSHHosts } from "@/api/ssh-host-management-api";
|
||||
import { listFleets } from "@/api/fleets-api";
|
||||
import { invokeAction } from "@termix/plugin-sdk/frontend";
|
||||
|
||||
import {
|
||||
AutomationEditor,
|
||||
emptyDraft,
|
||||
@@ -70,6 +71,14 @@ function timeAgo(iso: string | null): string {
|
||||
return `${Math.floor(hr / 24)}d ago`;
|
||||
}
|
||||
|
||||
/** Fleets from the fleets plugin, or none when it is not running. */
|
||||
async function listFleets(): Promise<{ id: number; name: string }[]> {
|
||||
const result = await invokeAction("fleets.list");
|
||||
return Array.isArray(result)
|
||||
? (result as { id: number; name: string }[])
|
||||
: [];
|
||||
}
|
||||
|
||||
export function AutomationsPanel({
|
||||
active = true,
|
||||
onEditingChange,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { getErrorMessage } from "@/lib/error-message.js";
|
||||
import { useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslation } from "@termix/plugin-sdk/frontend";
|
||||
import { Plus } from "lucide-react";
|
||||
import { Button } from "@/components/button";
|
||||
import { Input } from "@/components/input";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslation } from "@termix/plugin-sdk/frontend";
|
||||
import { Label } from "@/components/label";
|
||||
import {
|
||||
Select,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslation } from "@termix/plugin-sdk/frontend";
|
||||
import { ChevronDown, ChevronUp, Trash2 } from "lucide-react";
|
||||
import { Button } from "@/components/button";
|
||||
import { Input } from "@/components/input";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslation } from "@termix/plugin-sdk/frontend";
|
||||
import { Input } from "@/components/input";
|
||||
import { Label } from "@/components/label";
|
||||
import {
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
/**
|
||||
* Frontend half of the automations plugin.
|
||||
*
|
||||
* AutomationsPanel is a left-sidebar railView panel (opened from the rail,
|
||||
* not a Tab), the same shape as FleetsPanel/HostsPanel/AiPanel. None of those
|
||||
* go through registerRailItem/registerTabComponent either -- per
|
||||
* src/ui/shell/pluginLoader.ts's own comment, a rail-view panel like this is
|
||||
* rendered directly by AppShell.tsx rather than registered at runtime, the
|
||||
* same way ai's AiPanel is. AutomationsPanel is reached today through a
|
||||
* direct relative import in AppShell.tsx
|
||||
* (../../plugins/automations/frontend/AutomationsPanel) and in
|
||||
* src/ui/shell/tabUtils.tsx (for its promotable/dockable tab surface), not
|
||||
* through register() below.
|
||||
*
|
||||
* register()/unregister() still follow the same shape every other plugin's
|
||||
* frontend entry does, so this is ready the moment a real frontend plugin
|
||||
* loader exists -- see plugins/ssh-terminal/frontend/index.mjs and
|
||||
* src/ui/tests/sidebar/plugin-extension-seam.test.tsx, which says outright
|
||||
* "there is no plugin loader yet".
|
||||
*/
|
||||
|
||||
export const id = "automations";
|
||||
export const railViewId = "automations";
|
||||
|
||||
export async function register({ registerRailItem, icons }) {
|
||||
registerRailItem?.({
|
||||
id: railViewId,
|
||||
icon: icons.Workflow,
|
||||
labelKey: "nav.automations",
|
||||
separatorAfter: true,
|
||||
});
|
||||
}
|
||||
|
||||
export async function unregister({ unregisterRailItem }) {
|
||||
unregisterRailItem?.(railViewId);
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
import { Workflow } from "lucide-react";
|
||||
import type {
|
||||
PanelProps,
|
||||
TabProps,
|
||||
TermixApp,
|
||||
} from "@termix/plugin-sdk/frontend";
|
||||
import { AutomationsPanel } from "./AutomationsPanel";
|
||||
import { listAutomations } from "./automations-api";
|
||||
|
||||
const VIEW_ID = "automations";
|
||||
|
||||
function Panel({ active, setEditing }: PanelProps) {
|
||||
return (
|
||||
<div className="flex-1 min-h-0 overflow-y-auto">
|
||||
<AutomationsPanel active={active} onEditingChange={setEditing} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function AutomationsTab({ isVisible }: TabProps) {
|
||||
return <AutomationsPanel active={isVisible} />;
|
||||
}
|
||||
|
||||
export function activate(app: TermixApp): void {
|
||||
app.registerRailItem({
|
||||
id: VIEW_ID,
|
||||
icon: Workflow,
|
||||
titleKey: "nav.automations",
|
||||
promotable: true,
|
||||
after: "macros",
|
||||
order: 30,
|
||||
});
|
||||
app.registerPanel(VIEW_ID, Panel);
|
||||
app.registerTab(VIEW_ID, AutomationsTab, {
|
||||
icon: Workflow,
|
||||
titleKey: "nav.automations",
|
||||
singleton: true,
|
||||
hostless: true,
|
||||
panelFrame: true,
|
||||
});
|
||||
|
||||
// The assistant's @-mentions list automations through this.
|
||||
app.registerAction("automations.list", () => listAutomations());
|
||||
|
||||
app.registerSlotContribution("onboarding.features", {
|
||||
actionId: "automations.feature",
|
||||
titleKey: "onboarding.feature_automations",
|
||||
descriptionKey: "onboarding.feature_automations_desc",
|
||||
icon: Workflow,
|
||||
});
|
||||
}
|
||||
Reference in new issue
Block a user