fix(panel): 可认领的服务器行去掉点不了的控制台按钮,管理员在认领旁保留唤醒和控制台

This commit is contained in:
Lemon-miaow committed 2026-09-27 15:23:48 +08:00
1 parent 50ec181177
commit b6357ad68b
2 files changed
+55 -24

No files matched your search

@@ -111,6 +111,36 @@ describe("ServersPage fleet ownership", () => {
expect(skyblock.getByRole("button", { name: /Claim/ })).toBeTruthy();
});
it("offers a player only the claim on a server nobody owns, and an admin its wake and console too", async () => {
tier.isAdmin = false;
calls.myServers.mockResolvedValue([
{ name: "skyblock", subdomain: "skyblock", owned: false, claimable: true, phase: "Stopped", playersOnline: 0, playersMax: 20 },
] satisfies MyServerView[]);
const { unmount } = render(
<MemoryRouter>
<ServersPage />
</MemoryRouter>,
);
let skyblock = await tableRow("skyblock");
const names = skyblock.getAllByRole("button").map((b) => b.getAttribute("aria-label") ?? b.textContent?.trim());
expect(names).toEqual(["Copy address skyblock.example.test:25570", "Claim"]);
expect(skyblock.queryByRole("link")).toBeNull();
unmount();
tier.isAdmin = true;
calls.fleet.mockResolvedValue([row("skyblock", { claimable: true })]);
render(
<MemoryRouter>
<ServersPage />
</MemoryRouter>,
);
skyblock = await tableRow("skyblock");
expect(skyblock.getByRole("button", { name: /Claim/ })).toBeTruthy();
expect(skyblock.getByRole("button", { name: /Wake/ })).toHaveProperty("disabled", false);
expect(skyblock.getByRole("link").getAttribute("href")).toBe("/servers/skyblock");
expect(within(skyblock.getByRole("link")).getByRole("button", { name: /Console/ })).toHaveProperty("disabled", false);
});
it("says the owner is unknown and offers no claim when the lookup failed", async () => {
calls.fleet.mockResolvedValue([row("survival", { ownerUnknown: true })]);
render(
+25 -24
View File
@@ -525,10 +525,15 @@ function ServerActions({
);
}
// An unclaimed server is the player's to claim and nothing more: waking it and
// its console belong to its owner, and it has none yet. An admin runs any server
// (the wake and console routes admit them), so theirs keep both beside the claim.
const claimable = server.claimable && !server.owned;
return (
<div className={cn("flex flex-col items-end gap-1", className)}>
<div className="flex flex-wrap items-start justify-end gap-2 xl:flex-nowrap">
{server.claimable && !server.owned ? (
{claimable && (
<>
<Button
size="sm"
@@ -539,9 +544,6 @@ function ServerActions({
>
<Hand /> {ts("claim")}
</Button>
<Button size="sm" variant="outline" disabled>
<Terminal /> {ts("console")}
</Button>
<Dialog open={confirmOpen} onOpenChange={setConfirmOpen}>
<DialogContent className="sm:max-w-md">
@@ -566,26 +568,25 @@ function ServerActions({
</DialogContent>
</Dialog>
</>
) : (
<>
<PowerButton
name={server.name}
phase={server.phase}
desiredState={server.desiredState}
failed={startFailure(server) !== null}
playersOnline={server.playersOnline}
playerCountUnknown={server.playerCountUnknown}
retiring={server.retiring}
onChanged={onChanged}
/>
{(server.owned || isAdmin) && (
<Link to={`/servers/${server.name}`}>
<Button size="sm" variant="outline">
<Terminal /> {ts("console")}
</Button>
</Link>
)}
</>
)}
{(!claimable || isAdmin) && (
<PowerButton
name={server.name}
phase={server.phase}
desiredState={server.desiredState}
failed={startFailure(server) !== null}
playersOnline={server.playersOnline}
playerCountUnknown={server.playerCountUnknown}
retiring={server.retiring}
onChanged={onChanged}
/>
)}
{(server.owned || isAdmin) && (
<Link to={`/servers/${server.name}`}>
<Button size="sm" variant="outline">
<Terminal /> {ts("console")}
</Button>
</Link>
)}
</div>
{error && (