mirror of
https://github.com/Termix-SSH/Termix.git
synced 2026-10-30 15:15:24 +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,
|
registerHostEditorSection,
|
||||||
unregisterHostEditorSection,
|
unregisterHostEditorSection,
|
||||||
} from "@/sidebar/HostManagerTabs";
|
} from "@/sidebar/HostManagerTabs";
|
||||||
import type { PluginSummary } from "@/api/plugins-api";
|
import type { PluginSettingsField, PluginSummary } from "@/api/plugins-api";
|
||||||
import {
|
import {
|
||||||
HostPluginSections,
|
HostPluginSections,
|
||||||
type HostPluginSettings,
|
type HostPluginSettings,
|
||||||
} from "./HostPluginSections";
|
} from "./HostPluginSections";
|
||||||
import { hasVisibleFields } from "./settings-fields-util";
|
import { hasVisibleFields } from "./settings-fields-util";
|
||||||
|
import { isDefaultableField } from "@/sidebar/host-defaults/catalog";
|
||||||
|
|
||||||
const TAB_PREFIX = "feature:";
|
const TAB_PREFIX = "feature:";
|
||||||
|
|
||||||
@@ -29,6 +30,16 @@ interface HostFormLike {
|
|||||||
pluginSettings?: HostPluginSettings;
|
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. */
|
/** Adds, updates and removes generated tabs to match the plugin list. */
|
||||||
export function syncHostFeatureTabs(plugins: PluginSummary[]): string[] {
|
export function syncHostFeatureTabs(plugins: PluginSummary[]): string[] {
|
||||||
const existing = hostEditorSectionList();
|
const existing = hostEditorSectionList();
|
||||||
@@ -36,6 +47,19 @@ export function syncHostFeatureTabs(plugins: PluginSummary[]): string[] {
|
|||||||
(section) => section.pluginId && !section.id.startsWith(TAB_PREFIX),
|
(section) => section.pluginId && !section.id.startsWith(TAB_PREFIX),
|
||||||
);
|
);
|
||||||
const ownSections = new Set(own.map((section) => section.pluginId));
|
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
|
// 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.
|
// switches in the defaults editor, through a generated tab shown only there.
|
||||||
const ownDefaultsSections = new Set(
|
const ownDefaultsSections = new Set(
|
||||||
@@ -47,7 +71,10 @@ export function syncHostFeatureTabs(plugins: PluginSummary[]): string[] {
|
|||||||
const contributors = plugins.filter((plugin) => {
|
const contributors = plugins.filter((plugin) => {
|
||||||
if (!plugin.enabled || ownDefaultsSections.has(plugin.id)) return false;
|
if (!plugin.enabled || ownDefaultsSections.has(plugin.id)) return false;
|
||||||
const host = plugin.contributes?.settings?.host;
|
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(
|
const wanted = new Set(
|
||||||
@@ -62,11 +89,12 @@ export function syncHostFeatureTabs(plugins: PluginSummary[]): string[] {
|
|||||||
for (const plugin of contributors) {
|
for (const plugin of contributors) {
|
||||||
const host = plugin.contributes!.settings!.host!;
|
const host = plugin.contributes!.settings!.host!;
|
||||||
const icon = plugin.icon;
|
const icon = plugin.icon;
|
||||||
|
const placement = ownPlacement.get(plugin.id);
|
||||||
registerHostEditorSection({
|
registerHostEditorSection({
|
||||||
id: hostFeatureTabId(plugin.id),
|
id: hostFeatureTabId(plugin.id),
|
||||||
pluginId: plugin.id,
|
pluginId: plugin.id,
|
||||||
group: host.editorGroup ?? "top",
|
group: placement?.group ?? host.editorGroup ?? "top",
|
||||||
order: host.editorOrder ?? 100,
|
order: placement?.order ?? host.editorOrder ?? 100,
|
||||||
labelKey: plugin.name,
|
labelKey: plugin.name,
|
||||||
label: plugin.name,
|
label: plugin.name,
|
||||||
// Nothing but the plugin's host settings, so it works for defaults too.
|
// 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", () => {
|
it("skips a plugin whose own section already covers the defaults editor", () => {
|
||||||
registerHostEditorSection({
|
registerHostEditorSection({
|
||||||
id: "docker-own",
|
id: "docker-own",
|
||||||
|
|||||||
Reference in new issue
Block a user