mirror of
https://github.com/Termix-SSH/Termix.git
synced 2026-10-19 10:01:12 +00:00
fix: host defaults tabs sit where the host editor puts them and skip plugins with nothing to default
This commit is contained in:
1 parent
f101d29d8a
commit
d2a1be2eb0
2 files changed
+77
-4
No files matched your search
@@ -12,12 +12,13 @@ import {
|
||||
registerHostEditorSection,
|
||||
unregisterHostEditorSection,
|
||||
} from "@/sidebar/HostManagerTabs";
|
||||
import type { PluginSummary } from "@/api/plugins-api";
|
||||
import type { PluginSettingsField, PluginSummary } from "@/api/plugins-api";
|
||||
import {
|
||||
HostPluginSections,
|
||||
type HostPluginSettings,
|
||||
} from "./HostPluginSections";
|
||||
import { hasVisibleFields } from "./settings-fields-util";
|
||||
import { isDefaultableField } from "@/sidebar/host-defaults/catalog";
|
||||
|
||||
const TAB_PREFIX = "feature:";
|
||||
|
||||
@@ -29,6 +30,16 @@ interface HostFormLike {
|
||||
pluginSettings?: HostPluginSettings;
|
||||
}
|
||||
|
||||
function hasDefaultableFields(host: {
|
||||
enableKey?: string;
|
||||
fields: PluginSettingsField[];
|
||||
}): boolean {
|
||||
return (
|
||||
!!host.enableKey ||
|
||||
host.fields.some((field) => !field.hidden && isDefaultableField(field))
|
||||
);
|
||||
}
|
||||
|
||||
/** Adds, updates and removes generated tabs to match the plugin list. */
|
||||
export function syncHostFeatureTabs(plugins: PluginSummary[]): string[] {
|
||||
const existing = hostEditorSectionList();
|
||||
@@ -36,6 +47,19 @@ export function syncHostFeatureTabs(plugins: PluginSummary[]): string[] {
|
||||
(section) => section.pluginId && !section.id.startsWith(TAB_PREFIX),
|
||||
);
|
||||
const ownSections = new Set(own.map((section) => section.pluginId));
|
||||
// The defaults tab sits where the plugin's own section does on a host.
|
||||
const ownPlacement = new Map<
|
||||
string,
|
||||
{ group: "top" | "ssh"; order?: number }
|
||||
>();
|
||||
for (const section of own) {
|
||||
if (!ownPlacement.has(section.pluginId!)) {
|
||||
ownPlacement.set(section.pluginId!, {
|
||||
group: section.group,
|
||||
order: section.order,
|
||||
});
|
||||
}
|
||||
}
|
||||
// A plugin whose own sections are all about one host still gets its
|
||||
// switches in the defaults editor, through a generated tab shown only there.
|
||||
const ownDefaultsSections = new Set(
|
||||
@@ -47,7 +71,10 @@ export function syncHostFeatureTabs(plugins: PluginSummary[]): string[] {
|
||||
const contributors = plugins.filter((plugin) => {
|
||||
if (!plugin.enabled || ownDefaultsSections.has(plugin.id)) return false;
|
||||
const host = plugin.contributes?.settings?.host;
|
||||
return !!host && (hasVisibleFields(host.fields) || !!host.enableKey);
|
||||
if (!host) return false;
|
||||
// Its own section edits it per host, so only a default is left to offer.
|
||||
if (ownSections.has(plugin.id)) return hasDefaultableFields(host);
|
||||
return hasVisibleFields(host.fields) || !!host.enableKey;
|
||||
});
|
||||
|
||||
const wanted = new Set(
|
||||
@@ -62,11 +89,12 @@ export function syncHostFeatureTabs(plugins: PluginSummary[]): string[] {
|
||||
for (const plugin of contributors) {
|
||||
const host = plugin.contributes!.settings!.host!;
|
||||
const icon = plugin.icon;
|
||||
const placement = ownPlacement.get(plugin.id);
|
||||
registerHostEditorSection({
|
||||
id: hostFeatureTabId(plugin.id),
|
||||
pluginId: plugin.id,
|
||||
group: host.editorGroup ?? "top",
|
||||
order: host.editorOrder ?? 100,
|
||||
group: placement?.group ?? host.editorGroup ?? "top",
|
||||
order: placement?.order ?? host.editorOrder ?? 100,
|
||||
labelKey: plugin.name,
|
||||
label: plugin.name,
|
||||
// Nothing but the plugin's host settings, so it works for defaults too.
|
||||
|
||||
@@ -121,6 +121,51 @@ describe("syncHostFeatureTabs", () => {
|
||||
);
|
||||
});
|
||||
|
||||
it("places the defaults tab where the plugin's own section sits", () => {
|
||||
registerHostEditorSection({
|
||||
id: "docker-own",
|
||||
pluginId: "docker",
|
||||
group: "ssh",
|
||||
order: 40,
|
||||
labelKey: "k",
|
||||
component: () => null,
|
||||
});
|
||||
syncHostFeatureTabs([plugin()]);
|
||||
const tab = getHostEditorSection(hostFeatureTabId("docker"));
|
||||
expect(tab?.group).toBe("ssh");
|
||||
expect(tab?.order).toBe(40);
|
||||
});
|
||||
|
||||
it("gives a plugin with its own section no tab when nothing can have a default", () => {
|
||||
registerHostEditorSection({
|
||||
id: "proxmox-own",
|
||||
pluginId: "proxmox",
|
||||
group: "ssh",
|
||||
labelKey: "k",
|
||||
component: () => null,
|
||||
});
|
||||
const proxmox = plugin({
|
||||
id: "proxmox",
|
||||
name: "Proxmox",
|
||||
contributes: {
|
||||
settings: {
|
||||
host: {
|
||||
fields: [
|
||||
{
|
||||
key: "enableProxmox",
|
||||
type: "custom",
|
||||
component: "proxmoxHostSettings",
|
||||
defaultable: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
} as Partial<PluginSummary>);
|
||||
expect(syncHostFeatureTabs([proxmox])).toEqual([]);
|
||||
expect(getHostEditorSection(hostFeatureTabId("proxmox"))).toBeUndefined();
|
||||
});
|
||||
|
||||
it("skips a plugin whose own section already covers the defaults editor", () => {
|
||||
registerHostEditorSection({
|
||||
id: "docker-own",
|
||||
|
||||
Reference in new issue
Block a user