mirror of
https://github.com/Termix-SSH/Termix.git
synced 2026-10-28 14:15:24 +00:00
fix: let the repair screen turn the layout plugin back on
This commit is contained in:
1 parent
28cb1bc554
commit
53c4e5fe9c
5 files changed
+59
-2
No files matched your search
@@ -1098,6 +1098,8 @@
|
||||
"resetEveryone": "Reset the default for everyone",
|
||||
"update": "Update {{name}} to {{version}}",
|
||||
"disable": "Turn off {{name}}",
|
||||
"enable": "Turn on {{name}}",
|
||||
"startAgain": "Start {{name}} again",
|
||||
"install": "Find layouts and themes",
|
||||
"installTitle": "Layouts and themes",
|
||||
"installButton": "Install",
|
||||
|
||||
@@ -81,6 +81,18 @@ function AdminTools({
|
||||
})}
|
||||
</Button>
|
||||
)}
|
||||
{entry?.installed && !entry.enabled && (
|
||||
<Button
|
||||
size="sm"
|
||||
onClick={() => void manager.toggle(entry).then(onRetry)}
|
||||
disabled={manager.busy.has(entry.id)}
|
||||
>
|
||||
<Power />
|
||||
{status.reason === "disabled"
|
||||
? t("looks.repair.enable", { name: entry.name })
|
||||
: t("looks.repair.startAgain", { name: entry.name })}
|
||||
</Button>
|
||||
)}
|
||||
{entry?.installed && entry.enabled && !entry.managedByServer && (
|
||||
<Button
|
||||
size="sm"
|
||||
|
||||
@@ -79,13 +79,15 @@ export function layoutStatus(input: LayoutStatusInput): LayoutStatus {
|
||||
const owner = input.owner;
|
||||
if (!owner) return repair("missing");
|
||||
const summary = owner.summary;
|
||||
if (!summary.enabled) return repair("disabled");
|
||||
// Before the enabled check: the server reports a plugin that failed to
|
||||
// start as not enabled, which hid the real error behind "turned off".
|
||||
if (owner.frontend === "blocked" || summary.state === "blocked") {
|
||||
return repair("blocked", { error: owner.error ?? summary.lastError });
|
||||
}
|
||||
if (owner.frontend === "failed" || summary.state === "failed") {
|
||||
return repair("failed", { error: owner.error ?? summary.lastError });
|
||||
}
|
||||
if (!summary.enabled) return repair("disabled");
|
||||
if (owner.frontend === "loading") return { kind: "loading" };
|
||||
// Just chosen: the runtime is about to load its code.
|
||||
if (
|
||||
|
||||
@@ -53,6 +53,8 @@ vi.mock("@/look/use-look-theme", () => ({
|
||||
useChooseTheme: () => look.chooseTheme,
|
||||
}));
|
||||
|
||||
const fancy = vi.hoisted(() => ({ enabled: true }));
|
||||
|
||||
const manager = vi.hoisted(() => ({
|
||||
requestUpdate: vi.fn(),
|
||||
requestInstall: vi.fn(),
|
||||
@@ -72,7 +74,7 @@ vi.mock("@/plugins/use-plugins-manager", () => ({
|
||||
id: "fancy-layout",
|
||||
name: "Fancy",
|
||||
installed: true,
|
||||
enabled: true,
|
||||
enabled: fancy.enabled,
|
||||
updateAvailable: true,
|
||||
latestVersion: "1.1.0",
|
||||
managedByServer: false,
|
||||
@@ -115,6 +117,7 @@ const onRetry = vi.fn();
|
||||
|
||||
beforeEach(() => {
|
||||
permissions.isAdmin = true;
|
||||
fancy.enabled = true;
|
||||
for (const fn of [
|
||||
...Object.values(look),
|
||||
...Object.values(manager),
|
||||
@@ -190,6 +193,31 @@ describe("RepairView", () => {
|
||||
);
|
||||
});
|
||||
|
||||
it("lets an admin turn the plugin back on and then tries again", async () => {
|
||||
fancy.enabled = false;
|
||||
manager.toggle.mockResolvedValue(undefined);
|
||||
render(
|
||||
<RepairView
|
||||
status={{ ...status, reason: "disabled", error: null }}
|
||||
onRetry={onRetry}
|
||||
/>,
|
||||
);
|
||||
expect(screen.queryByText(/looks\.repair\.disable/)).toBeNull();
|
||||
fireEvent.click(screen.getByText('looks.repair.enable:{"name":"Fancy"}'));
|
||||
expect(manager.toggle).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ id: "fancy-layout", enabled: false }),
|
||||
);
|
||||
await waitFor(() => expect(onRetry).toHaveBeenCalled());
|
||||
});
|
||||
|
||||
it("offers to start a failed plugin again", () => {
|
||||
fancy.enabled = false;
|
||||
render(<RepairView status={status} onRetry={onRetry} />);
|
||||
expect(
|
||||
screen.getByText('looks.repair.startAgain:{"name":"Fancy"}'),
|
||||
).toBeTruthy();
|
||||
});
|
||||
|
||||
it("lets an admin restore the bundled copy and then tries again", async () => {
|
||||
render(<RepairView status={status} onRetry={onRetry} />);
|
||||
fireEvent.click(screen.getByText('looks.repair.restore:{"name":"Fancy"}'));
|
||||
|
||||
@@ -120,6 +120,19 @@ describe("layoutStatus", () => {
|
||||
).toMatchObject({ reason: "failed", error: "server" });
|
||||
});
|
||||
|
||||
it("says failed, not disabled, when the server could not start it", () => {
|
||||
expect(
|
||||
layoutStatus(
|
||||
input({
|
||||
owner: owner(
|
||||
{ enabled: false, state: "failed", lastError: "bad bundle" },
|
||||
"none",
|
||||
),
|
||||
}),
|
||||
),
|
||||
).toMatchObject({ reason: "failed", error: "bad bundle" });
|
||||
});
|
||||
|
||||
it("says incompatible when the server skipped its plugin", () => {
|
||||
expect(
|
||||
layoutStatus(
|
||||
|
||||
Reference in new issue
Block a user