diff --git a/web/src/components/users/FirstUser.jsx b/web/src/components/users/FirstUser.jsx
index 8f661d279e..4d16709c20 100644
--- a/web/src/components/users/FirstUser.jsx
+++ b/web/src/components/users/FirstUser.jsx
@@ -19,34 +19,30 @@
* find current contact information at www.suse.com.
*/
-import React, { useState, useEffect, useRef } from "react";
-import {
- Alert,
- Checkbox,
- Form, FormGroup, TextInput,
- Menu, MenuContent, MenuList, MenuItem,
- Skeleton,
- Stack
-} from "@patternfly/react-core";
+import React, { useState, useEffect } from "react";
+import { Skeleton, Split, Stack } from "@patternfly/react-core";
import { Table, Thead, Tr, Th, Tbody, Td } from '@patternfly/react-table';
import { useNavigate } from "react-router-dom";
-import { RowActions, PasswordAndConfirmationInput, Popup, ButtonLink } from '~/components/core';
+import { RowActions, ButtonLink } from '~/components/core';
import { _ } from "~/i18n";
import { useCancellablePromise } from "~/utils";
import { useInstallerClient } from "~/context/installer";
-import { suggestUsernames } from '~/components/users/utils';
const UserNotDefined = ({ actionCb }) => {
return (
-
- {_("No user defined yet.")}
-
-
- {_("Please, be aware that a user must be defined before installing the system to be able to log into it.")}
-
-
- {_("Define a user now")}
-
+ <>
+
+ {_("No user defined yet.")}
+
+
+ {_("Please, be aware that a user must be defined before installing the system to be able to log into it.")}
+
+
+
+ {_("Define a user now")}
+
+
+ >
);
};
@@ -73,38 +69,6 @@ const UserData = ({ user, actions }) => {
);
};
-const UsernameSuggestions = ({ isOpen = false, entries, onSelect, setInsideDropDown, focusedIndex = -1 }) => {
- if (!isOpen) return;
-
- return (
-
- );
-};
-
-const CREATE_MODE = 'create';
-const EDIT_MODE = 'edit';
-
const initialUser = {
userName: "",
fullName: "",
@@ -116,23 +80,11 @@ export default function FirstUser() {
const client = useInstallerClient();
const { cancellablePromise } = useCancellablePromise();
const [user, setUser] = useState({});
- const [errors, setErrors] = useState([]);
- const [formValues, setFormValues] = useState(initialUser);
const [isLoading, setIsLoading] = useState(true);
- const [isEditing, setIsEditing] = useState(false);
- const [isFormOpen, setIsFormOpen] = useState(false);
- const [isValidPassword, setIsValidPassword] = useState(true);
- const [isSettingPassword, setIsSettingPassword] = useState(false);
- const [showSuggestions, setShowSuggestions] = useState(false);
- const [insideDropDown, setInsideDropDown] = useState(false);
- const [focusedIndex, setFocusedIndex] = useState(-1);
- const [suggestions, setSuggestions] = useState([]);
- const usernameInputRef = useRef();
useEffect(() => {
cancellablePromise(client.users.getUser()).then(userValues => {
setUser(userValues);
- setFormValues({ ...initialUser, ...userValues });
setIsLoading(false);
});
}, [client.users, cancellablePromise]);
@@ -145,41 +97,6 @@ export default function FirstUser() {
});
}, [client.users]);
- const openForm = (e, mode = CREATE_MODE) => {
- setIsEditing(mode === EDIT_MODE);
- // Password will be always set when creating the user. In the edit mode it
- // depends on the user choice
- setIsSettingPassword(mode === CREATE_MODE);
- // To avoid confusion, do not expose the current password
- setFormValues({ ...initialUser, ...user, password: "" });
- setIsFormOpen(true);
- };
-
- const closeForm = () => {
- setErrors([]);
- setIsEditing(false);
- setIsFormOpen(false);
- };
-
- const accept = async (formName, e) => {
- e.preventDefault();
- setErrors([]);
- setIsLoading(true);
-
- // Preserve current password value if the user was not editing it.
- const newUser = { ...formValues };
- if (!isSettingPassword) newUser.password = user.password;
-
- const { result, issues = [] } = await client.users.setUser(newUser);
- setErrors(issues);
- setIsLoading(false);
- if (result) {
- setUser(newUser);
-
- closeForm();
- }
- };
-
const remove = async () => {
setIsLoading(true);
@@ -187,18 +104,11 @@ export default function FirstUser() {
if (result) {
setUser(initialUser);
- setFormValues(initialUser);
setIsLoading(false);
}
};
- const handleInputChange = ({ target }, value) => {
- const { name } = target;
- setFormValues({ ...formValues, [name]: value });
- };
-
const isUserDefined = user?.userName && user?.userName !== "";
- const showErrors = () => ((errors || []).length > 0);
const navigate = useNavigate();
const actions = [
@@ -213,145 +123,11 @@ export default function FirstUser() {
}
];
- const toggleShowPasswordField = () => setIsSettingPassword(!isSettingPassword);
- const usingValidPassword = formValues.password && formValues.password !== "" && isValidPassword;
- const submitDisable = formValues.userName === "" || (isSettingPassword && !usingValidPassword);
-
- const displaySuggestions = !formValues.userName && formValues.fullName && showSuggestions;
- useEffect(() => {
- if (displaySuggestions) {
- setFocusedIndex(-1);
- setSuggestions(suggestUsernames(formValues.fullName));
- }
- }, [displaySuggestions, formValues.fullName]);
-
- const onSuggestionSelected = (suggestion) => {
- setInsideDropDown(false);
- setFormValues({ ...formValues, userName: suggestion });
- usernameInputRef.current?.focus();
- };
-
- const handleKeyDown = (event) => {
- switch (event.key) {
- case 'ArrowDown':
- event.preventDefault(); // Prevent page scrolling
- if (suggestions.length > 0) setShowSuggestions(true);
- setFocusedIndex((prevIndex) => (prevIndex + 1) % suggestions.length);
- break;
- case 'ArrowUp':
- event.preventDefault(); // Prevent page scrolling
- if (suggestions.length > 0) setShowSuggestions(true);
- setFocusedIndex((prevIndex) => (prevIndex - (prevIndex === -1 ? 0 : 1) + suggestions.length) % suggestions.length);
- break;
- case 'Enter':
- if (focusedIndex >= 0) {
- onSuggestionSelected(suggestions[focusedIndex]);
- }
- break;
- case 'Escape':
- case 'Tab':
- setShowSuggestions(false);
- break;
- default:
- break;
- }
- };
-
- if (isLoading) return ;
-
- return (
- <>
- {isUserDefined ? : }
- { /* TODO: Extract this form to a component, if possible */}
- {isFormOpen &&
-
-
-
-
-
-
-
- }
- >
- );
+ if (isLoading) {
+ return ;
+ } else if (isUserDefined) {
+ return ;
+ } else {
+ return ;
+ }
}
diff --git a/web/src/components/users/FirstUser.test.jsx b/web/src/components/users/FirstUser.test.jsx
deleted file mode 100644
index 4dae092eb6..0000000000
--- a/web/src/components/users/FirstUser.test.jsx
+++ /dev/null
@@ -1,389 +0,0 @@
-/*
- * Copyright (c) [2022] SUSE LLC
- *
- * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as published
- * by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, contact SUSE LLC.
- *
- * To contact SUSE LLC about this file by physical or electronic mail, you may
- * find current contact information at www.suse.com.
- */
-
-import React from "react";
-
-import { act, screen, waitFor, within } from "@testing-library/react";
-import { installerRender, createCallbackMock } from "~/test-utils";
-import { createClient } from "~/client";
-import { FirstUser } from "~/components/users";
-
-jest.mock("~/client");
-
-let user;
-const emptyUser = {
- fullName: "",
- userName: "",
- autologin: false
-};
-
-let setUserResult = { result: true, issues: [] };
-
-let setUserFn = jest.fn().mockResolvedValue(setUserResult);
-const removeUserFn = jest.fn();
-let onUsersChangeFn = jest.fn();
-
-const openUserForm = async () => {
- const { user } = installerRender();
- await screen.findByText("No user defined yet.");
- const button = await screen.findByText("Define a user now");
- await user.click(button);
- const dialog = await screen.findByLabelText("Username");
-
- return { user, dialog };
-};
-
-beforeEach(() => {
- user = emptyUser;
- createClient.mockImplementation(() => {
- return {
- users: {
- setUser: setUserFn,
- getUser: jest.fn().mockResolvedValue(user),
- removeUser: removeUserFn,
- onUsersChange: onUsersChangeFn
- }
- };
- });
-});
-
-it.skip("allows defining a new user", async () => {
- const { user } = installerRender();
- await screen.findByText("No user defined yet.");
- const button = await screen.findByText("Define a user now");
- await user.click(button);
-
- const dialog = await screen.findByRole("form");
-
- const fullNameInput = within(dialog).getByLabelText("Full name");
- await user.type(fullNameInput, "Jane Doe");
-
- const usernameInput = within(dialog).getByLabelText(/Username/);
- await user.type(usernameInput, "jane");
-
- const passwordInput = within(dialog).getByLabelText("Password");
- await user.type(passwordInput, "12345");
-
- const passwordConfirmationInput = within(dialog).getByLabelText("Password confirmation");
- await user.type(passwordConfirmationInput, "12345");
-
- const confirmButton = screen.getByRole("button", { name: /Confirm/i });
- expect(confirmButton).toBeEnabled();
- await user.click(confirmButton);
-
- expect(setUserFn).toHaveBeenCalledWith({
- fullName: "Jane Doe",
- userName: "jane",
- password: "12345",
- autologin: false
- });
-
- await waitFor(() => {
- expect(screen.queryByRole("dialog")).not.toBeInTheDocument();
- });
-});
-
-it.skip("doest not allow to confirm the settings if the user name and the password are not provided", async () => {
- const { user } = installerRender();
- const button = await screen.findByText("Define a user now");
- await user.click(button);
-
- const dialog = await screen.findByRole("dialog");
-
- const usernameInput = within(dialog).getByLabelText(/Username/);
- await user.type(usernameInput, "jane");
- const confirmButton = within(dialog).getByRole("button", { name: /Confirm/i });
- expect(confirmButton).toBeDisabled();
-});
-
-it.skip("does not change anything if the user cancels", async () => {
- const { user } = installerRender();
- const button = await screen.findByRole("button", { name: "Define a user now" });
- await user.click(button);
-
- const dialog = await screen.findByRole("dialog");
-
- const cancelButton = within(dialog).getByRole("button", { name: /Cancel/i });
- await user.click(cancelButton);
-
- expect(setUserFn).not.toHaveBeenCalled();
- await waitFor(() => {
- expect(screen.queryByRole("dialog")).not.toBeInTheDocument();
- });
-});
-
-describe.skip("when there is some issue with the user config provided", () => {
- beforeEach(() => {
- setUserResult = { result: false, issues: ["There is an error"] };
- setUserFn = jest.fn().mockResolvedValue(setUserResult);
- });
-
- it("shows the issues found", async () => {
- const { user } = installerRender();
- const button = await screen.findByRole("button", { name: "Define a user now" });
- await user.click(button);
-
- const dialog = await screen.findByRole("dialog");
-
- const usernameInput = within(dialog).getByLabelText("Username");
- await user.type(usernameInput, "root");
-
- const passwordInput = within(dialog).getByLabelText("Password");
- await user.type(passwordInput, "12345");
-
- const passwordConfirmationInput = within(dialog).getByLabelText("Password confirmation");
- await user.type(passwordConfirmationInput, "12345");
-
- const confirmButton = within(dialog).getByRole("button", { name: /Confirm/i });
- expect(confirmButton).toBeEnabled();
- await user.click(confirmButton);
-
- expect(setUserFn).toHaveBeenCalledWith({
- fullName: "",
- userName: "root",
- password: "12345",
- autologin: false
- });
-
- await waitFor(() => {
- expect(screen.queryByText(/Something went wrong/i)).toBeInTheDocument();
- expect(screen.queryByText(/There is an error/i)).toBeInTheDocument();
- expect(screen.queryByText("No user defined yet.")).toBeInTheDocument();
- });
- });
-});
-
-describe.skip("when the user is already defined", () => {
- beforeEach(() => {
- user = {
- fullName: "John Doe",
- userName: "jdoe",
- password: "sup3rSecret",
- autologin: false
- };
- });
-
- it("renders the name and username", async () => {
- installerRender();
- await screen.findByText("John Doe");
- await screen.findByText("jdoe");
- });
-
- it("allows editing the user without changing the password", async () => {
- const { user } = installerRender();
-
- await screen.findByText("John Doe");
-
- const userActionsToggler = screen.getByRole("button", { name: "Actions" });
- await user.click(userActionsToggler);
- const editAction = screen.getByRole("menuitem", { name: "Edit" });
- await user.click(editAction);
- const dialog = await screen.findByRole("dialog");
-
- const fullNameInput = within(dialog).getByLabelText("Full name");
- await user.clear(fullNameInput);
- await user.type(fullNameInput, "Jane");
-
- const usernameInput = within(dialog).getByLabelText(/Username/);
- await user.clear(usernameInput);
- await user.type(usernameInput, "jane");
-
- const autologinCheckbox = within(dialog).getByLabelText(/Auto-login/);
- await user.click(autologinCheckbox);
-
- const confirmButton = screen.getByRole("button", { name: /Confirm/i });
- expect(confirmButton).toBeEnabled();
- await user.click(confirmButton);
-
- expect(setUserFn).toHaveBeenCalledWith({
- fullName: "Jane",
- userName: "jane",
- password: "sup3rSecret",
- autologin: true
- });
- });
-
- it("allows changing the password", async () => {
- const { user } = installerRender();
-
- await screen.findByText("John Doe");
-
- const userActionsToggler = screen.getByRole("button", { name: "Actions" });
- await user.click(userActionsToggler);
- const editAction = screen.getByRole("menuitem", { name: "Edit" });
- await user.click(editAction);
- const dialog = await screen.findByRole("dialog");
-
- const confirmButton = screen.getByRole("button", { name: /Confirm/i });
- const changePasswordCheckbox = within(dialog).getByLabelText("Edit password too");
- await user.click(changePasswordCheckbox);
-
- expect(confirmButton).toBeDisabled();
-
- const passwordInput = within(dialog).getByLabelText("Password");
- await user.type(passwordInput, "n0tSecret");
- const passwordConfirmationInput = within(dialog).getByLabelText("Password confirmation");
- await user.type(passwordConfirmationInput, "n0tSecret");
-
- expect(confirmButton).toBeEnabled();
-
- await user.click(confirmButton);
-
- expect(setUserFn).toHaveBeenCalledWith({
- fullName: "John Doe",
- userName: "jdoe",
- password: "n0tSecret",
- autologin: false
- });
- });
-
- it("allows removing the user", async () => {
- const { user } = installerRender();
- const table = await screen.findByRole("grid");
- const row = within(table).getByText("John Doe")
- .closest("tr");
- const actionsToggler = within(row).getByRole("button", { name: "Actions" });
- await user.click(actionsToggler);
- const discardAction = screen.getByRole("menuitem", { name: "Discard" });
- await user.click(discardAction);
- expect(removeUserFn).toHaveBeenCalled();
- });
-});
-
-describe.skip("when the user has been modified", () => {
- it("updates the UI for rendering its main info", async () => {
- const [mockFunction, callbacks] = createCallbackMock();
- onUsersChangeFn = mockFunction;
- installerRender();
- await screen.findByText("No user defined yet.");
-
- const [cb] = callbacks;
- act(() => {
- cb({ firstUser: { userName: "ytm", fullName: "YaST Team Member", autologin: false } });
- });
-
- const noUserInfo = await screen.queryByText("No user defined yet.");
- expect(noUserInfo).toBeNull();
- screen.getByText("YaST Team Member");
- screen.getByText("ytm");
- });
-});
-
-describe.skip("username suggestions", () => {
- it("shows suggestions when full name is given and username gets focus", async () => {
- const { user, dialog } = await openUserForm();
-
- const fullNameInput = within(dialog).getByLabelText("Full name");
- await user.type(fullNameInput, "Jane Doe");
-
- await user.tab();
-
- const menuItems = screen.getAllByText("Use suggested username");
- expect(menuItems.length).toBe(4);
- });
-
- it("hides suggestions when username loses focus", async () => {
- const { user, dialog } = await openUserForm();
-
- const fullNameInput = within(dialog).getByLabelText("Full name");
- await user.type(fullNameInput, "Jane Doe");
-
- await user.tab();
-
- let menuItems = screen.getAllByText("Use suggested username");
- expect(menuItems.length).toBe(4);
-
- await user.tab();
-
- menuItems = screen.queryAllByText("Use suggested username");
- expect(menuItems.length).toBe(0);
- });
-
- it("does not show suggestions when full name is not given", async () => {
- const { user, dialog } = await openUserForm();
-
- const fullNameInput = within(dialog).getByLabelText("Full name");
- fullNameInput.focus();
-
- await user.tab();
-
- const menuItems = screen.queryAllByText("Use suggested username");
- expect(menuItems.length).toBe(0);
- });
-
- it("hides suggestions if user types something", async () => {
- const { user, dialog } = await openUserForm();
-
- const fullNameInput = within(dialog).getByLabelText("Full name");
- await user.type(fullNameInput, "Jane Doe");
-
- await user.tab();
-
- // confirming that we have suggestions
- let menuItems = screen.queryAllByText("Use suggested username");
- expect(menuItems.length).toBe(4);
-
- const usernameInput = within(dialog).getByLabelText("Username");
- // the user now types something
- await user.type(usernameInput, "John Smith");
-
- // checking if suggestions are gone
- menuItems = screen.queryAllByText("Use suggested username");
- expect(menuItems.length).toBe(0);
- });
-
- it("fills username input with chosen suggestion", async () => {
- const { user, dialog } = await openUserForm();
-
- const fullNameInput = within(dialog).getByLabelText("Full name");
- await user.type(fullNameInput, "Will Power");
-
- await user.tab();
-
- const menuItem = screen.getByText('willpower');
- const usernameInput = within(dialog).getByLabelText("Username");
-
- await user.click(menuItem);
-
- expect(usernameInput).toHaveFocus();
- expect(usernameInput.value).toBe("willpower");
- });
-
- it("fills username input with chosen suggestion using keyboard for selection", async () => {
- const { user, dialog } = await openUserForm();
-
- const fullNameInput = within(dialog).getByLabelText("Full name");
- await user.type(fullNameInput, "Jane Doe");
-
- await user.tab();
-
- const menuItems = screen.getAllByRole("menuitem");
- const menuItemTwo = menuItems[1].textContent.replace("Use suggested username ", "");
-
- await user.keyboard("{ArrowDown}");
- await user.keyboard("{ArrowDown}");
- await user.keyboard("{Enter}");
-
- const usernameInput = within(dialog).getByLabelText("Username");
- expect(usernameInput).toHaveFocus();
- expect(usernameInput.value).toBe(menuItemTwo);
- });
-});
diff --git a/web/src/components/users/FirstUserForm.jsx b/web/src/components/users/FirstUserForm.jsx
index c148737805..7640be4ac6 100644
--- a/web/src/components/users/FirstUserForm.jsx
+++ b/web/src/components/users/FirstUserForm.jsx
@@ -254,7 +254,7 @@ export default function FirstUserForm() {
{state.isEditing &&
setChangePassword(!changePassword)}
/>}
diff --git a/web/src/components/users/UsersPage.jsx b/web/src/components/users/UsersPage.jsx
index 1fffd6f0b3..56bef68a8e 100644
--- a/web/src/components/users/UsersPage.jsx
+++ b/web/src/components/users/UsersPage.jsx
@@ -24,7 +24,7 @@ import React from "react";
import { _ } from "~/i18n";
import { CardField, IssuesHint, Page } from "~/components/core";
import { FirstUser, RootAuthMethods } from "~/components/users";
-import { CardBody, Grid, GridItem, Stack } from "@patternfly/react-core";
+import { CardBody, Grid, GridItem } from "@patternfly/react-core";
import { useIssues } from "~/context/issues";
export default function UsersPage() {
@@ -44,18 +44,14 @@ export default function UsersPage() {
-
-
-
+
-
-
-
+