Skip to content

Commit

Permalink
feat: warn self change on roles settings
Browse files Browse the repository at this point in the history
  • Loading branch information
marc.sirisak committed Jan 8, 2025
1 parent 5caad70 commit 492152e
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 2 deletions.
30 changes: 29 additions & 1 deletion src/components/views/settings/PowerLevelSelector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import { useMatrixClientContext } from "../../../contexts/MatrixClientContext";
import PowerSelector from "../elements/PowerSelector";
import { _t } from "../../../languageHandler";
import SettingsFieldset from "./SettingsFieldset";
import Modal from "../../../Modal";
import QuestionDialog from "../dialogs/QuestionDialog";

/**
* Display in a fieldset, the power level of the users and allow to change them.
Expand Down Expand Up @@ -77,6 +79,13 @@ export function PowerLevelSelector({
// No user to display, we return the children into fragment to convert it to JSX.Element type
if (!users.length) return <>{children}</>;

// check at least one admin in the list
const roomHasAtLeastOneAdmin = (usersLevels: Record<string, number>) : boolean => {
const userLevelValues = Object.values(usersLevels);
// At least one user as the pL 100 which means he is admin
return userLevelValues.some((uL) => uL === 100);
}

return (
<SettingsFieldset legend={title}>
{users.map((userId) => {
Expand All @@ -96,7 +105,26 @@ export function PowerLevelSelector({
disabled={!canChange}
label={userId}
key={userId}
onChange={(value) => setCurrentPowerLevel({ value, userId })}
onChange={async (value) => {
const userLevelsTmp = Object.assign({}, userLevels);
userLevelsTmp[userId] = value;

if (!roomHasAtLeastOneAdmin(userLevelsTmp)) {
const { finished } = Modal.createDialog(QuestionDialog, {
title: _t("common|warning"),
description: (
<div>
{_t("user_info|demote_self_confirm_room")}
</div>
),
button: _t("action|continue"),
});
const [confirmed] = await finished;
if (!confirmed) return;
}
setCurrentPowerLevel({ value, userId });
}
}
/>
);
})}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,12 @@ describe("PowerLevelSelector", () => {

it("should be able to change the power level of the current user", async () => {
const onClick = jest.fn();
renderPLS({ onClick });
const userLevels = {
[currentUser]: 100,
"@alice:server.org": 100,
"@bob:server.org": 0,
};
renderPLS({ userLevels, onClick });

// Until the power level is changed, the apply button should be disabled
// compound button is using aria-disabled instead of the disabled attribute, we can't toBeDisabled on it
Expand Down Expand Up @@ -107,4 +112,34 @@ describe("PowerLevelSelector", () => {

expect(screen.getByText("empty label")).toBeInTheDocument();
});

it("should display modal warning if user is last admin", async () => {
const onClick = jest.fn();

renderPLS({ onClick });

// Until the power level is changed, the apply button should be disabled
// compound button is using aria-disabled instead of the disabled attribute, we can't toBeDisabled on it
expect(screen.getByRole("button", { name: "Apply" })).toHaveAttribute("aria-disabled", "true");

const select = screen.getByRole("combobox", { name: currentUser });
// Sanity check
expect(select).toHaveValue("100");

// Change current user power level to 50
await userEvent.selectOptions(select, "50");

// modal should appear because only admin in the room
expect(screen.findByText("WARNING")).toBeTruthy();

await userEvent.click(screen.getByRole("button", { name: "Continue" }));

expect(select).toHaveValue("50");
// After the user level changes, the apply button should be enabled
expect(screen.getByRole("button", { name: "Apply" })).toHaveAttribute("aria-disabled", "false");

// Click on Apply should call onClick with the new power level
await userEvent.click(screen.getByRole("button", { name: "Apply" }));
expect(onClick).toHaveBeenCalledWith(50, currentUser);
});
});

0 comments on commit 492152e

Please sign in to comment.