mirror of
https://github.com/Termix-SSH/Termix.git
synced 2026-10-28 06:05:24 +00:00
fix: open settings goes to the plugin's page and hides when it has none
This commit is contained in:
1 parent
d1ddcd3ff9
commit
60024bdd4e
6 files changed
+96
-5
No files matched your search
@@ -1686,6 +1686,10 @@ export function AppShell({
|
|||||||
tabLabel,
|
tabLabel,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
// Asking for a page again still goes there after the user moved away
|
||||||
|
if (type === "settings" && data?.section && data.revealAt === undefined) {
|
||||||
|
data = { ...data, revealAt: Date.now() };
|
||||||
|
}
|
||||||
const id = type;
|
const id = type;
|
||||||
const singletonLabels: Partial<Record<TabType, string>> = {
|
const singletonLabels: Partial<Record<TabType, string>> = {
|
||||||
"host-manager": t("nav.manage"),
|
"host-manager": t("nav.manage"),
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ import {
|
|||||||
type PluginEntry,
|
type PluginEntry,
|
||||||
} from "./plugin-model";
|
} from "./plugin-model";
|
||||||
import { openPluginSettings } from "./open-plugins";
|
import { openPluginSettings } from "./open-plugins";
|
||||||
|
import { hasSettingsPage } from "@/settings/settings-fields-util";
|
||||||
import { PluginReleaseNotes, PluginVideo } from "./PluginReleaseNotes";
|
import { PluginReleaseNotes, PluginVideo } from "./PluginReleaseNotes";
|
||||||
import type { PluginsManager } from "./use-plugins-manager";
|
import type { PluginsManager } from "./use-plugins-manager";
|
||||||
|
|
||||||
@@ -67,11 +68,10 @@ export function PluginDetail({
|
|||||||
}, [plugin.version, plugin.latestVersion]);
|
}, [plugin.version, plugin.latestVersion]);
|
||||||
|
|
||||||
const contributions = describeContributions(plugin.contributes);
|
const contributions = describeContributions(plugin.contributes);
|
||||||
const settings = plugin.contributes?.settings as
|
// Only people who can manage plugins get here, and they see admin settings
|
||||||
{ admin?: unknown[]; user?: unknown[] } | undefined;
|
|
||||||
const hasSettings =
|
const hasSettings =
|
||||||
plugin.installed &&
|
plugin.installed &&
|
||||||
((settings?.admin?.length ?? 0) > 0 || (settings?.user?.length ?? 0) > 0);
|
hasSettingsPage(plugin as Parameters<typeof hasSettingsPage>[0], true);
|
||||||
const issueUrl = reportIssueUrl(
|
const issueUrl = reportIssueUrl(
|
||||||
plugin,
|
plugin,
|
||||||
import.meta.env.VITE_APP_VERSION || undefined,
|
import.meta.env.VITE_APP_VERSION || undefined,
|
||||||
|
|||||||
@@ -43,6 +43,8 @@ import {
|
|||||||
export interface SettingsTabProps {
|
export interface SettingsTabProps {
|
||||||
/** The page to open, from the tab's data. */
|
/** The page to open, from the tab's data. */
|
||||||
section?: string;
|
section?: string;
|
||||||
|
/** Changes on every open request, so asking for the same page again still goes there. */
|
||||||
|
sectionAt?: string | number;
|
||||||
/** An element id on that page to scroll to, as "id@nonce". */
|
/** An element id on that page to scroll to, as "id@nonce". */
|
||||||
reveal?: string;
|
reveal?: string;
|
||||||
username: string;
|
username: string;
|
||||||
@@ -86,6 +88,7 @@ function revealText(container: HTMLElement, needle: string): boolean {
|
|||||||
/** Everything that configures the app, one page at a time. */
|
/** Everything that configures the app, one page at a time. */
|
||||||
export function SettingsTab({
|
export function SettingsTab({
|
||||||
section,
|
section,
|
||||||
|
sectionAt,
|
||||||
reveal,
|
reveal,
|
||||||
username,
|
username,
|
||||||
isAdmin,
|
isAdmin,
|
||||||
@@ -141,7 +144,7 @@ export function SettingsTab({
|
|||||||
const [current, setCurrent] = useState(section ?? "account");
|
const [current, setCurrent] = useState(section ?? "account");
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (section) setCurrent(section);
|
if (section) setCurrent(section);
|
||||||
}, [section]);
|
}, [section, sectionAt]);
|
||||||
|
|
||||||
// The page renders lazily, so the target may take a moment to appear.
|
// The page renders lazily, so the target may take a moment to appear.
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
@@ -19,3 +19,24 @@ export function isFieldShown(
|
|||||||
export function hasVisibleFields(fields: PluginSettingsField[]): boolean {
|
export function hasVisibleFields(fields: PluginSettingsField[]): boolean {
|
||||||
return fields.some((field) => !field.hidden);
|
return fields.some((field) => !field.hidden);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Whether Settings lists a page for this plugin, by the same rule it uses. */
|
||||||
|
export function hasSettingsPage(
|
||||||
|
plugin: {
|
||||||
|
enabled: boolean;
|
||||||
|
contributes?: {
|
||||||
|
settings?: {
|
||||||
|
user?: PluginSettingsField[];
|
||||||
|
admin?: PluginSettingsField[];
|
||||||
|
};
|
||||||
|
} | null;
|
||||||
|
},
|
||||||
|
isAdmin: boolean,
|
||||||
|
): boolean {
|
||||||
|
const settings = plugin.contributes?.settings;
|
||||||
|
return (
|
||||||
|
plugin.enabled &&
|
||||||
|
(hasVisibleFields(settings?.user ?? []) ||
|
||||||
|
(isAdmin && hasVisibleFields(settings?.admin ?? [])))
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -227,7 +227,7 @@ function noop() {}
|
|||||||
export interface TabRenderContext {
|
export interface TabRenderContext {
|
||||||
shell: TabShellCallbacks;
|
shell: TabShellCallbacks;
|
||||||
/** What the Settings tab needs from the shell. */
|
/** What the Settings tab needs from the shell. */
|
||||||
settings?: Omit<SettingsTabProps, "section">;
|
settings?: Omit<SettingsTabProps, "section" | "sectionAt">;
|
||||||
/** The terminal a panel shown as a tab sends commands to. */
|
/** The terminal a panel shown as a tab sends commands to. */
|
||||||
panelTargetTab?: Tab;
|
panelTargetTab?: Tab;
|
||||||
isVisible?: boolean;
|
isVisible?: boolean;
|
||||||
@@ -266,6 +266,12 @@ export function renderTabContent(tab: Tab, context: TabRenderContext) {
|
|||||||
? tab.data.section
|
? tab.data.section
|
||||||
: undefined
|
: undefined
|
||||||
}
|
}
|
||||||
|
sectionAt={
|
||||||
|
typeof tab.data?.revealAt === "number" ||
|
||||||
|
typeof tab.data?.revealAt === "string"
|
||||||
|
? tab.data.revealAt
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
reveal={
|
reveal={
|
||||||
typeof tab.data?.reveal === "string"
|
typeof tab.data?.reveal === "string"
|
||||||
? `${tab.data.reveal}@${String(tab.data.revealAt ?? "")}`
|
? `${tab.data.reveal}@${String(tab.data.revealAt ?? "")}`
|
||||||
|
|||||||
@@ -0,0 +1,57 @@
|
|||||||
|
import { describe, expect, it } from "vitest";
|
||||||
|
import {
|
||||||
|
hasSettingsPage,
|
||||||
|
hasVisibleFields,
|
||||||
|
} from "@/settings/settings-fields-util";
|
||||||
|
import type { PluginSettingsField } from "@/api/plugins-api";
|
||||||
|
|
||||||
|
const field = (hidden = false) =>
|
||||||
|
({ key: "a", type: "string", hidden }) as unknown as PluginSettingsField;
|
||||||
|
|
||||||
|
describe("hasVisibleFields", () => {
|
||||||
|
it("ignores hidden fields", () => {
|
||||||
|
expect(hasVisibleFields([field(true)])).toBe(false);
|
||||||
|
expect(hasVisibleFields([field(true), field()])).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("hasSettingsPage", () => {
|
||||||
|
it("needs an enabled plugin", () => {
|
||||||
|
expect(
|
||||||
|
hasSettingsPage(
|
||||||
|
{ enabled: false, contributes: { settings: { user: [field()] } } },
|
||||||
|
true,
|
||||||
|
),
|
||||||
|
).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("is false with no settings or only hidden ones", () => {
|
||||||
|
expect(hasSettingsPage({ enabled: true, contributes: null }, true)).toBe(
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
hasSettingsPage(
|
||||||
|
{ enabled: true, contributes: { settings: { user: [field(true)] } } },
|
||||||
|
true,
|
||||||
|
),
|
||||||
|
).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("counts admin settings only for admins", () => {
|
||||||
|
const plugin = {
|
||||||
|
enabled: true,
|
||||||
|
contributes: { settings: { admin: [field()] } },
|
||||||
|
};
|
||||||
|
expect(hasSettingsPage(plugin, true)).toBe(true);
|
||||||
|
expect(hasSettingsPage(plugin, false)).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("counts user settings for anyone", () => {
|
||||||
|
expect(
|
||||||
|
hasSettingsPage(
|
||||||
|
{ enabled: true, contributes: { settings: { user: [field()] } } },
|
||||||
|
false,
|
||||||
|
),
|
||||||
|
).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in new issue
Block a user