Skip to content

Commit

Permalink
Unify save-buttons in admin-ui (keycloak#30119)
Browse files Browse the repository at this point in the history
* keycloak#30118 Unify save-buttons in admin-ui

Signed-off-by: Andreas Blaettlinger <bln1imb@bosch.com>

* keycloak#30118 Unify save-buttons in admin-ui

Signed-off-by: Andreas Blaettlinger <bln1imb@bosch.com>

* Introduced props for naming the buttons in FixedButtonGroup

Signed-off-by: Andreas Blaettlinger <bln1imb@bosch.com>

---------

Signed-off-by: Andreas Blaettlinger <bln1imb@bosch.com>
  • Loading branch information
andreas-blaettlinger authored Jun 18, 2024
1 parent 5ad3aba commit 2a88d01
Show file tree
Hide file tree
Showing 9 changed files with 45 additions and 85 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export default class AttributesTab {
#saveAttributeBtn = "save-attributes";
#saveAttributeBtn = "attributes-save";
#attributesTab = "attributes";
#emptyState = "attributes-empty-state";
#addAttributeBtn: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export default class KeyValueInput {
}

save() {
cy.findByTestId("save-attributes").click();
cy.findByTestId("attributes-save").click();
return this;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ enum RealmSettingsTab {

const expect = chai.expect;
export default class RealmSettingsPage extends CommonPage {
generalSaveBtn = "general-tab-save";
generalRevertBtn = "general-tab-revert";
generalSaveBtn = "realmSettingsGeneralTab-save";
generalRevertBtn = "realmSettingsGeneralTab-revert";
themesSaveBtn = "themes-tab-save";
loginTab = "rs-login-tab";
emailTab = "rs-email-tab";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ export default class CreateUserPage {
this.addUserBtn = "add-user";
this.joinGroupsBtn = "join-groups-button";
this.joinBtn = "join-button";
this.createBtn = "create-user";
this.saveBtn = "save-user";
this.cancelBtn = "cancel-create-user";
this.createBtn = "user-creation-save";
this.saveBtn = "user-creation-save";
this.cancelBtn = "user-creation-revert";
}

//#region General Settings
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export default class UserDetailsPage extends PageObject {

constructor() {
super();
this.saveBtn = "save-user";
this.saveBtn = "user-creation-save";
this.cancelBtn = "cancel-create-user";
this.emailInput = "email";
this.emailValue = () => "example" + "_" + uuid() + "@example.com";
Expand Down
8 changes: 6 additions & 2 deletions js/apps/admin-ui/src/components/form/FixedButtonGroup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,19 @@ import style from "./fixed-buttons.module.css";
type FixedButtonGroupProps = ActionGroupProps & {
name: string;
save?: () => void;
saveText?: string;
reset?: () => void;
resetText?: string;
isSubmit?: boolean;
isActive?: boolean;
};

export const FixedButtonsGroup = ({
name,
save,
saveText,
reset,
resetText,
isSubmit = false,
isActive = true,
children,
Expand All @@ -31,7 +35,7 @@ export const FixedButtonsGroup = ({
onClick={() => save?.()}
type={isSubmit ? "submit" : "button"}
>
{t("save")}
{!saveText ? t("save") : saveText}
</Button>
)}
{reset && (
Expand All @@ -41,7 +45,7 @@ export const FixedButtonsGroup = ({
variant="link"
onClick={() => reset()}
>
{t("revert")}
{!resetText ? t("revert") : resetText}
</Button>
)}
{children}
Expand Down
23 changes: 3 additions & 20 deletions js/apps/admin-ui/src/components/key-value-form/AttributeForm.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import type RoleRepresentation from "@keycloak/keycloak-admin-client/lib/defs/roleRepresentation";
import { ActionGroup, Button } from "@patternfly/react-core";
import { FormProvider, UseFormReturn } from "react-hook-form";
import { useTranslation } from "react-i18next";

import { FormAccess } from "../form/FormAccess";
import type { KeyValueType } from "./key-value-convert";
import { KeyValueInput } from "./KeyValueInput";
import { FixedButtonsGroup } from "../form/FixedButtonGroup";

export type AttributeForm = Omit<RoleRepresentation, "attributes"> & {
attributes?: KeyValueType[];
Expand All @@ -28,12 +27,8 @@ export const AttributesForm = ({
name = "attributes",
isDisabled = false,
}: AttributesFormProps) => {
const { t } = useTranslation();
const noSaveCancelButtons = !save && !reset;
const {
formState: { isDirty },
handleSubmit,
} = form;
const { handleSubmit } = form;

return (
<FormAccess
Expand All @@ -45,19 +40,7 @@ export const AttributesForm = ({
<KeyValueInput name={name} isDisabled={isDisabled} />
</FormProvider>
{!noSaveCancelButtons && (
<ActionGroup className="kc-attributes__action-group">
<Button
data-testid="save-attributes"
variant="primary"
type="submit"
isDisabled={!isDirty}
>
{t("save")}
</Button>
<Button onClick={reset} variant="link" isDisabled={!isDirty}>
{t("revert")}
</Button>
</ActionGroup>
<FixedButtonsGroup name="attributes" reset={reset} isActive isSubmit />
)}
</FormAccess>
);
Expand Down
28 changes: 8 additions & 20 deletions js/apps/admin-ui/src/realm-settings/GeneralTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ import {
UserProfileConfig,
} from "@keycloak/keycloak-admin-client/lib/defs/userProfileMetadata";
import {
ActionGroup,
Button,
ClipboardCopy,
FormGroup,
PageSection,
Expand All @@ -27,6 +25,7 @@ import { FormattedLink } from "../components/external-link/FormattedLink";
import { FormAccess } from "../components/form/FormAccess";
import { KeyValueInput } from "../components/key-value-form/KeyValueInput";
import { KeycloakSpinner } from "../components/keycloak-spinner/KeycloakSpinner";
import { FixedButtonsGroup } from "../components/form/FixedButtonGroup";
import { useRealm } from "../context/realm-context/RealmContext";
import {
addTrailingSlash,
Expand Down Expand Up @@ -105,7 +104,7 @@ function RealmSettingsGeneralTabForm({
control,
handleSubmit,
setValue,
formState: { isDirty, errors },
formState: { errors },
} = form;
const isFeatureEnabled = useIsFeatureEnabled();
const isOrganizationsEnabled = isFeatureEnabled(Feature.Organizations);
Expand Down Expand Up @@ -266,23 +265,12 @@ function RealmSettingsGeneralTabForm({
</StackItem>
</Stack>
</FormGroup>
<ActionGroup>
<Button
variant="primary"
type="submit"
data-testid="general-tab-save"
isDisabled={!isDirty}
>
{t("save")}
</Button>
<Button
data-testid="general-tab-revert"
variant="link"
onClick={setupForm}
>
{t("revert")}
</Button>
</ActionGroup>
<FixedButtonsGroup
name="realmSettingsGeneralTab"
reset={setupForm}
isActive
isSubmit
/>
</FormAccess>
</FormProvider>
</PageSection>
Expand Down
55 changes: 20 additions & 35 deletions js/apps/admin-ui/src/user/UserForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,12 @@ import { UserProfileMetadata } from "@keycloak/keycloak-admin-client/lib/defs/us
import type UserRepresentation from "@keycloak/keycloak-admin-client/lib/defs/userRepresentation";
import {
FormErrorText,
FormSubmitButton,
HelpItem,
SwitchControl,
TextControl,
UserProfileFields,
} from "@keycloak/keycloak-ui-shared";
import {
ActionGroup,
AlertVariant,
Button,
Chip,
Expand All @@ -26,7 +24,6 @@ import { TFunction } from "i18next";
import { useEffect, useState } from "react";
import { Controller, FormProvider, UseFormReturn } from "react-hook-form";
import { useTranslation } from "react-i18next";
import { Link } from "react-router-dom";
import { useAdminClient } from "../admin-client";
import { DefaultSwitchControl } from "../components/SwitchControl";
import { useAlerts } from "../components/alert/Alerts";
Expand All @@ -39,7 +36,9 @@ import useFormatDate from "../utils/useFormatDate";
import { FederatedUserLink } from "./FederatedUserLink";
import { UserFormFields, toUserFormFields } from "./form-state";
import { toUsers } from "./routes/Users";
import { FixedButtonsGroup } from "../components/form/FixedButtonGroup";
import { RequiredActionMultiSelect } from "./user-credentials/RequiredActionMultiSelect";
import { useNavigate } from "react-router-dom";

export type BruteForced = {
isBruteForceProtected?: boolean;
Expand Down Expand Up @@ -79,15 +78,15 @@ export const UserForm = ({
const { whoAmI } = useWhoAmI();
const currentLocale = whoAmI.getLocale();

const { handleSubmit, setValue, watch, control, reset, formState } = form;
const { handleSubmit, setValue, control, reset, formState } = form;
const { errors } = formState;

const watchUsernameInput = watch("username");
const [selectedGroups, setSelectedGroups] = useState<GroupRepresentation[]>(
[],
);
const [open, setOpen] = useState(false);
const [locked, setLocked] = useState(isLocked);
const navigate = useNavigate();

useEffect(() => {
setValue("requiredActions", user?.requiredActions || []);
Expand Down Expand Up @@ -132,6 +131,14 @@ export const UserForm = ({
setOpen(!open);
};

const onFormReset = () => {
if (user?.id) {
reset(toUserFormFields(user));
} else {
navigate(toUsers({ realm: realm.realm! }));
}
};

return (
<FormAccess
isHorizontal
Expand Down Expand Up @@ -327,37 +334,15 @@ export const UserForm = ({
)}
</FormGroup>
)}

<ActionGroup>
<FormSubmitButton
formState={formState}
data-testid={!user?.id ? "create-user" : "save-user"}
isDisabled={
!user?.id &&
!watchUsernameInput &&
realm.registrationEmailAsUsername === false
}
allowNonDirty
allowInvalid
>
{user?.id ? t("save") : t("create")}
</FormSubmitButton>
<Button
data-testid="cancel-create-user"
variant="link"
onClick={user?.id ? () => reset(toUserFormFields(user)) : undefined}
component={
!user?.id
? (props) => (
<Link {...props} to={toUsers({ realm: realm.realm! })} />
)
: undefined
}
>
{user?.id ? t("revert") : t("cancel")}
</Button>
</ActionGroup>
</FormProvider>
<FixedButtonsGroup
name="user-creation"
saveText={user?.id ? t("save") : t("create")}
reset={onFormReset}
resetText={user?.id ? t("revert") : t("cancel")}
isActive
isSubmit
/>
</FormAccess>
);
};

0 comments on commit 2a88d01

Please sign in to comment.