Changed clients/authorization to use ui-shared (#27826)

* migrated Switch and KeycloakTextInput to ui-shared

Signed-off-by: Agnieszka Gancarczyk <agancarc@redhat.com>

* migrated AuthorizationExport to use TextAreaControl

Signed-off-by: Agnieszka Gancarczyk <agancarc@redhat.com>

* migrated ImportDialog to use use-shared

Signed-off-by: Agnieszka Gancarczyk <agancarc@redhat.com>

* migrated PermissionDetails to use use-shared

Signed-off-by: Agnieszka Gancarczyk <agancarc@redhat.com>

* migrated ResourceDetails to use use-shared

Signed-off-by: Agnieszka Gancarczyk <agancarc@redhat.com>

* migrated ScopeDetails to use use-shared

Signed-off-by: Agnieszka Gancarczyk <agancarc@redhat.com>

* migrated PermissionDetails to ui-shared

Signed-off-by: Agnieszka Gancarczyk <agancarc@redhat.com>

---------

Signed-off-by: Agnieszka Gancarczyk <agancarc@redhat.com>
Co-authored-by: Agnieszka Gancarczyk <agancarc@redhat.com>
This commit is contained in:
agagancarczyk 2024-03-19 13:22:10 +00:00 committed by GitHub
parent b77e228be4
commit e501cfcfb3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 140 additions and 317 deletions

View file

@ -3112,3 +3112,4 @@ replyToDisplayPlaceholder=Display name for "reply to" email address
senderEnvelopePlaceholder=Sender envelope email address
smtpPortPlaceholder=SMTP port (defaults to 25)
loginUsernamePlaceholder=Login username
ownerHelp=Owner for this resource.

View file

@ -23,8 +23,7 @@ import {
import { useState } from "react";
import { Controller, FormProvider, useForm, useWatch } from "react-hook-form";
import { useTranslation } from "react-i18next";
import { HelpItem } from "ui-shared";
import { HelpItem, TextControl } from "ui-shared";
import { ForbiddenSection } from "../../ForbiddenSection";
import { adminClient } from "../../admin-client";
import { useAlerts } from "../../components/alert/Alerts";
@ -34,7 +33,6 @@ import {
KeyValueType,
keyValueToArray,
} from "../../components/key-value-form/key-value-convert";
import { KeycloakTextInput } from "../../components/keycloak-text-input/KeycloakTextInput";
import { UserSelect } from "../../components/users/UserSelect";
import { useAccess } from "../../context/access/Access";
import { useRealm } from "../../context/realm-context/RealmContext";
@ -96,7 +94,6 @@ const AuthorizationEvaluateContent = ({ client }: Props) => {
const form = useForm<EvaluateFormInputs>({ mode: "onChange" });
const {
control,
register,
reset,
trigger,
formState: { isValid, errors },
@ -104,9 +101,7 @@ const AuthorizationEvaluateContent = ({ client }: Props) => {
const { t } = useTranslation();
const { addError } = useAlerts();
const realm = useRealm();
const [scopesDropdownOpen, setScopesDropdownOpen] = useState(false);
const [roleDropdownOpen, setRoleDropdownOpen] = useState(false);
const [isExpanded, setIsExpanded] = useState(false);
const [applyToResourceType, setApplyToResourceType] = useState(false);
@ -114,7 +109,6 @@ const AuthorizationEvaluateContent = ({ client }: Props) => {
const [scopes, setScopes] = useState<ScopeRepresentation[]>([]);
const [evaluateResult, setEvaluateResult] =
useState<PolicyEvaluationResponse>();
const [clientRoles, setClientRoles] = useState<RoleRepresentation[]>([]);
useFetch(
@ -304,7 +298,6 @@ const AuthorizationEvaluateContent = ({ client }: Props) => {
aria-label={t("applyToResourceType")}
/>
</FormGroup>
{!applyToResourceType ? (
<FormGroup
label={t("resourcesAndScopes")}
@ -328,26 +321,12 @@ const AuthorizationEvaluateContent = ({ client }: Props) => {
</FormGroup>
) : (
<>
<FormGroup
<TextControl
name="alias"
label={t("resourceType")}
isRequired
labelIcon={
<HelpItem
helpText={t("resourceTypeHelp")}
fieldLabelId="resourceType"
/>
}
fieldId="client"
validated={errors.alias ? "error" : "default"}
helperTextInvalid={t("required")}
>
<KeycloakTextInput
id="alias"
aria-label="resource-type"
data-testid="alias"
{...register("alias", { required: true })}
/>
</FormGroup>
labelIcon={t("resourceTypeHelp")}
rules={{ required: t("required") }}
/>
<FormGroup
label={t("authScopes")}
labelIcon={

View file

@ -3,19 +3,16 @@ import {
ActionGroup,
AlertVariant,
Button,
FormGroup,
PageSection,
} from "@patternfly/react-core";
import { saveAs } from "file-saver";
import { useState } from "react";
import { useTranslation } from "react-i18next";
import { HelpItem } from "ui-shared";
import { TextAreaControl } from "ui-shared";
import { adminClient } from "../../admin-client";
import { useAlerts } from "../../components/alert/Alerts";
import { FormAccess } from "../../components/form/FormAccess";
import { KeycloakSpinner } from "../../components/keycloak-spinner/KeycloakSpinner";
import { KeycloakTextArea } from "../../components/keycloak-text-area/KeycloakTextArea";
import { useFetch } from "../../utils/useFetch";
import { prettyPrintJSON } from "../../util";
import { useParams } from "../../utils/useParams";
@ -68,25 +65,14 @@ export const AuthorizationExport = () => {
role="manage-authorization"
className="pf-u-mt-lg"
>
<FormGroup
<TextAreaControl
name="authDetails"
label={t("authDetails")}
labelIcon={
<HelpItem
helpText={t("authDetailsHelp")}
fieldLabelId="authDetails"
/>
}
fieldId="client"
>
<KeycloakTextArea
id="authorizationDetails"
readOnly
resizeOrientation="vertical"
value={code}
aria-label={t("authDetails")}
rows={10}
/>
</FormGroup>
labelIcon={t("authDetailsHelp")}
defaultValue={code!}
readOnly
rows={10}
/>
<ActionGroup>
<Button
data-testid="authorization-export-download"

View file

@ -16,15 +16,12 @@ import { useState } from "react";
import { Controller, FormProvider, useForm, useWatch } from "react-hook-form";
import { useTranslation } from "react-i18next";
import { Link, useNavigate } from "react-router-dom";
import { HelpItem } from "ui-shared";
import { HelpItem, TextAreaControl, TextControl } from "ui-shared";
import { adminClient } from "../../admin-client";
import { useAlerts } from "../../components/alert/Alerts";
import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog";
import { FormAccess } from "../../components/form/FormAccess";
import { KeycloakSpinner } from "../../components/keycloak-spinner/KeycloakSpinner";
import { KeycloakTextArea } from "../../components/keycloak-text-area/KeycloakTextArea";
import { KeycloakTextInput } from "../../components/keycloak-text-input/KeycloakTextInput";
import { ViewHeader } from "../../components/view-header/ViewHeader";
import { useFetch } from "../../utils/useFetch";
import { toUpperCase } from "../../util";
@ -50,7 +47,6 @@ export default function PermissionDetails() {
mode: "onChange",
});
const {
register,
control,
reset,
formState: { errors },
@ -213,45 +209,25 @@ export default function PermissionDetails() {
onSubmit={handleSubmit(save)}
>
<FormProvider {...form}>
<FormGroup
<TextControl
name="name"
label={t("name")}
isRequired
helperTextInvalid={t("required")}
validated={errors.name ? "error" : "default"}
fieldId="name"
labelIcon={
<HelpItem helpText={t("permissionName")} fieldLabelId="name" />
}
>
<KeycloakTextInput
id="name"
validated={errors.name ? "error" : "default"}
{...register("name", { required: true })}
/>
</FormGroup>
<FormGroup
labelIcon={t("permissionName")}
rules={{
required: t("required"),
}}
/>
<TextAreaControl
name="description"
label={t("description")}
fieldId="description"
labelIcon={
<HelpItem
helpText={t("permissionDescription")}
fieldLabelId="description"
/>
}
validated={errors.description ? "error" : "default"}
helperTextInvalid={errors.description?.message}
>
<KeycloakTextArea
id="description"
validated={errors.description ? "error" : "default"}
{...register("description", {
maxLength: {
value: 255,
message: t("maxLength", { length: 255 }),
},
})}
/>
</FormGroup>
labelIcon={t("permissionDescription")}
rules={{
maxLength: {
value: 255,
message: t("maxLength", { length: 255 }),
},
}}
/>
<FormGroup
label={t("applyToResourceTypeFlag")}
fieldId="applyToResourceTypeFlag"
@ -273,24 +249,17 @@ export default function PermissionDetails() {
/>
</FormGroup>
{applyToResourceTypeFlag ? (
<FormGroup
<TextControl
name="resourceType"
label={t("resourceType")}
fieldId="resourceType"
labelIcon={
<HelpItem
helpText={t("resourceTypeHelp")}
fieldLabelId="resourceType"
/>
}
isRequired={permissionType === "scope"}
>
<KeycloakTextInput
id="resourceType"
{...register("resourceType", {
required: permissionType === "scope",
})}
/>
</FormGroup>
labelIcon={t("resourceTypeHelp")}
rules={{
required: {
value: permissionType === "scope" ? true : false,
message: t("required"),
},
}}
/>
) : (
<FormGroup
label={t("resource")}

View file

@ -10,15 +10,12 @@ import {
DropdownItem,
FormGroup,
PageSection,
Switch,
ValidatedOptions,
} from "@patternfly/react-core";
import { useState } from "react";
import { Controller, FormProvider, useForm } from "react-hook-form";
import { FormProvider, useForm } from "react-hook-form";
import { useTranslation } from "react-i18next";
import { Link, useNavigate } from "react-router-dom";
import { HelpItem } from "ui-shared";
import { HelpItem, TextControl } from "ui-shared";
import { adminClient } from "../../admin-client";
import { useAlerts } from "../../components/alert/Alerts";
import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog";
@ -26,7 +23,6 @@ import { FormAccess } from "../../components/form/FormAccess";
import type { KeyValueType } from "../../components/key-value-form/key-value-convert";
import { KeyValueInput } from "../../components/key-value-form/KeyValueInput";
import { KeycloakSpinner } from "../../components/keycloak-spinner/KeycloakSpinner";
import { KeycloakTextInput } from "../../components/keycloak-text-input/KeycloakTextInput";
import { MultiLineInput } from "../../components/multi-line-input/MultiLineInput";
import { ViewHeader } from "../../components/view-header/ViewHeader";
import { convertFormValuesToObject, convertToFormValues } from "../../util";
@ -35,9 +31,9 @@ import { useParams } from "../../utils/useParams";
import { toAuthorizationTab } from "../routes/AuthenticationTab";
import { ResourceDetailsParams, toResourceDetails } from "../routes/Resource";
import { ScopePicker } from "./ScopePicker";
import "./resource-details.css";
import { DefaultSwitchControl } from "../../components/SwitchControl";
import { useAccess } from "../../context/access/Access";
import "./resource-details.css";
type SubmittedResource = Omit<
ResourceRepresentation,
@ -58,13 +54,7 @@ export default function ResourceDetails() {
const form = useForm<SubmittedResource>({
mode: "onChange",
});
const {
register,
formState: { errors },
control,
setValue,
handleSubmit,
} = form;
const { setValue, handleSubmit } = form;
const { id, resourceId, realm } = useParams<ResourceDetailsParams>();
const navigate = useNavigate();
@ -197,68 +187,30 @@ export default function ResourceDetails() {
className="keycloak__resource-details__form"
onSubmit={handleSubmit(submit)}
>
<FormGroup
<TextControl
name={resourceId ? "owner.name" : ""}
label={t("owner")}
fieldId="owner"
labelIcon={
<HelpItem helpText={t("ownerHelp")} fieldLabelId="owner" />
}
>
<KeycloakTextInput
id="owner"
value={client.clientId}
isReadOnly
/>
</FormGroup>
<FormGroup
labelIcon={t("ownerHelp")}
defaultValue={client.clientId}
readOnly
/>
<TextControl
name={"name"}
label={t("name")}
fieldId="name"
labelIcon={
<HelpItem
helpText={t("resourceNameHelp")}
fieldLabelId="name"
/>
}
helperTextInvalid={t("required")}
validated={
errors.name ? ValidatedOptions.error : ValidatedOptions.default
}
isRequired
>
<KeycloakTextInput
id="name"
validated={
errors.name
? ValidatedOptions.error
: ValidatedOptions.default
}
{...register("name", { required: true })}
/>
</FormGroup>
<FormGroup
labelIcon={t("resourceNameHelp")}
rules={{ required: t("required") }}
/>
<TextControl
name="displayName"
label={t("displayName")}
fieldId="displayName"
labelIcon={
<HelpItem helpText={t("displayNameHelp")} fieldLabelId="name" />
}
>
<KeycloakTextInput
id="displayName"
{...register("displayName")}
/>
</FormGroup>
<FormGroup
labelIcon={t("displayNameHelp")}
rules={{ required: t("required") }}
/>
<TextControl
name="type"
label={t("type")}
fieldId="type"
labelIcon={
<HelpItem
helpText={t("resourceDetailsTypeHelp")}
fieldLabelId="type"
/>
}
>
<KeycloakTextInput id="type" {...register("type")} />
</FormGroup>
labelIcon={t("resourceDetailsTypeHelp")}
/>
<FormGroup
label={t("uris")}
fieldId="uris"
@ -274,47 +226,17 @@ export default function ResourceDetails() {
/>
</FormGroup>
<ScopePicker clientId={id} />
<FormGroup
<TextControl
name="icon_uri"
label={t("iconUri")}
fieldId="iconUri"
labelIcon={
<HelpItem helpText={t("iconUriHelp")} fieldLabelId="iconUri" />
}
>
<KeycloakTextInput
id="iconUri"
type="url"
{...register("icon_uri")}
/>
</FormGroup>
<FormGroup
hasNoPaddingTop
labelIcon={t("iconUriHelp")}
type="url"
/>
<DefaultSwitchControl
name="ownerManagedAccess"
label={t("ownerManagedAccess")}
labelIcon={
<HelpItem
helpText={t("ownerManagedAccessHelp")}
fieldLabelId="ownerManagedAccess"
/>
}
fieldId="ownerManagedAccess"
>
<Controller
name="ownerManagedAccess"
control={control}
defaultValue={false}
render={({ field }) => (
<Switch
id="ownerManagedAccess"
label={t("on")}
labelOff={t("off")}
isChecked={field.value}
onChange={field.onChange}
aria-label={t("ownerManagedAccess")}
/>
)}
/>
</FormGroup>
labelIcon={t("ownerManagedAccessHelp")}
/>
<FormGroup
hasNoPaddingTop
label={t("resourceAttribute")}

View file

@ -5,20 +5,16 @@ import {
Button,
ButtonVariant,
DropdownItem,
FormGroup,
PageSection,
ValidatedOptions,
} from "@patternfly/react-core";
import { useState } from "react";
import { useForm } from "react-hook-form";
import { FormProvider, useForm } from "react-hook-form";
import { useTranslation } from "react-i18next";
import { Link, useNavigate } from "react-router-dom";
import { HelpItem } from "ui-shared";
import { TextControl } from "ui-shared";
import { adminClient } from "../../admin-client";
import { useAlerts } from "../../components/alert/Alerts";
import { FormAccess } from "../../components/form/FormAccess";
import { KeycloakTextInput } from "../../components/keycloak-text-input/KeycloakTextInput";
import { ViewHeader } from "../../components/view-header/ViewHeader";
import { useFetch } from "../../utils/useFetch";
import { useParams } from "../../utils/useParams";
@ -33,19 +29,13 @@ export default function ScopeDetails() {
const { t } = useTranslation();
const { id, scopeId, realm } = useParams<ScopeDetailsParams>();
const navigate = useNavigate();
const { addAlert, addError } = useAlerts();
const [deleteDialog, toggleDeleteDialog] = useToggle();
const [scope, setScope] = useState<ScopeRepresentation>();
const {
register,
reset,
handleSubmit,
formState: { errors },
} = useForm<FormFields>({
const form = useForm<FormFields>({
mode: "onChange",
});
const { reset, handleSubmit } = form;
useFetch(
async () => {
@ -123,92 +113,68 @@ export default function ScopeDetails() {
}
/>
<PageSection variant="light">
<FormAccess
isHorizontal
role="manage-authorization"
onSubmit={handleSubmit(onSubmit)}
>
<FormGroup
label={t("name")}
fieldId="name"
labelIcon={
<HelpItem helpText={t("scopeNameHelp")} fieldLabelId="name" />
}
helperTextInvalid={t("required")}
validated={
errors.name ? ValidatedOptions.error : ValidatedOptions.default
}
isRequired
<FormProvider {...form}>
<FormAccess
isHorizontal
role="manage-authorization"
onSubmit={handleSubmit(onSubmit)}
>
<KeycloakTextInput
id="name"
validated={
errors.name ? ValidatedOptions.error : ValidatedOptions.default
}
isRequired
{...register("name", { required: true })}
<TextControl
name="name"
label={t("name")}
labelIcon={t("scopeNameHelp")}
rules={{ required: t("required") }}
/>
</FormGroup>
<FormGroup
label={t("displayName")}
fieldId="displayName"
labelIcon={
<HelpItem
helpText={t("scopeDisplayNameHelp")}
fieldLabelId="displayName"
/>
}
>
<KeycloakTextInput id="displayName" {...register("displayName")} />
</FormGroup>
<FormGroup
label={t("iconUri")}
fieldId="iconUri"
labelIcon={
<HelpItem helpText={t("iconUriHelp")} fieldLabelId="iconUri" />
}
>
<KeycloakTextInput id="iconUri" {...register("iconUri")} />
</FormGroup>
<ActionGroup>
<div className="pf-u-mt-md">
<Button
variant={ButtonVariant.primary}
type="submit"
data-testid="save"
>
{t("save")}
</Button>
<TextControl
name="displayName"
label={t("displayName")}
labelIcon={t("scopeDisplayNameHelp")}
/>
<TextControl
name="iconUri"
label={t("iconUri")}
labelIcon={t("iconUriHelp")}
/>
<ActionGroup>
<div className="pf-u-mt-md">
<Button
variant={ButtonVariant.primary}
type="submit"
data-testid="save"
>
{t("save")}
</Button>
{!scope ? (
<Button
variant="link"
data-testid="cancel"
component={(props) => (
<Link
{...props}
to={toAuthorizationTab({
realm,
clientId: id,
tab: "scopes",
})}
></Link>
)}
>
{t("cancel")}
</Button>
) : (
<Button
variant="link"
data-testid="revert"
onClick={() => reset({ ...scope })}
>
{t("revert")}
</Button>
)}
</div>
</ActionGroup>
</FormAccess>
{!scope ? (
<Button
variant="link"
data-testid="cancel"
component={(props) => (
<Link
{...props}
to={toAuthorizationTab({
realm,
clientId: id,
tab: "scopes",
})}
></Link>
)}
>
{t("cancel")}
</Button>
) : (
<Button
variant="link"
data-testid="revert"
onClick={() => reset({ ...scope })}
>
{t("revert")}
</Button>
)}
</div>
</ActionGroup>
</FormAccess>
</FormProvider>
</PageSection>
</>
);