fixed messages and replaced KeyckloakTextInput (#27591)

Signed-off-by: Agnieszka Gancarczyk <agancarc@redhat.com>
Co-authored-by: Agnieszka Gancarczyk <agancarc@redhat.com>
This commit is contained in:
agagancarczyk 2024-03-06 10:25:57 +00:00 committed by GitHub
parent 3e46810b37
commit 8689208e3a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 200 additions and 211 deletions

View file

@ -3098,4 +3098,8 @@ noLanguagesSearchResultsInstructions=Click on the search bar above to search for
addTranslationDialogOkBtn=Ok
translationError=Please add translations before saving
fetchRoles=Fetch Roles
fetchRolesHelp=By default, only the roles available from the token sent with the authorization requests are used to check if the user is granted with a role. If this setting is enabled, the policy will ignore roles from the token and check any role associated with the user instead.
fetchRolesHelp=By default, only the roles available from the token sent with the authorization requests are used to check if the user is granted with a role. If this setting is enabled, the policy will ignore roles from the token and check any role associated with the user instead.
emptyAdminEvents=No admin events
emptyAdminEventsInstructions=There are no admin events in this realm.
emptyUserEvents=No user events
emptyUserEventsInstructions=There are no user events in this realm.

View file

@ -528,8 +528,8 @@ export const AdminEvents = () => {
]}
emptyState={
<ListEmptyState
message={t("emptyEvents")}
instructions={t("emptyEventsInstructions")}
message={t("emptyAdminEvents")}
instructions={t("emptyAdminEventsInstructions")}
/>
}
isSearching={Object.keys(activeFilters).length > 0}

View file

@ -27,12 +27,11 @@ import { CheckCircleIcon, WarningTriangleIcon } from "@patternfly/react-icons";
import { cellWidth, expandable } from "@patternfly/react-table";
import { pickBy } from "lodash-es";
import { useState } from "react";
import { Controller, useForm } from "react-hook-form";
import { Controller, FormProvider, useForm } from "react-hook-form";
import { Trans, useTranslation } from "react-i18next";
import { Link } from "react-router-dom";
import { adminClient } from "../admin-client";
import { KeycloakTextInput } from "../components/keycloak-text-input/KeycloakTextInput";
import { ListEmptyState } from "../components/list-empty-state/ListEmptyState";
import {
RoutableTabs,
@ -49,6 +48,7 @@ import { useFetch } from "../utils/useFetch";
import useFormatDate, { FORMAT_DATE_AND_TIME } from "../utils/useFormatDate";
import { AdminEvents } from "./AdminEvents";
import { EventsTab, toEvents } from "./routes/Events";
import { TextControl } from "ui-shared";
import "./events.css";
@ -145,17 +145,18 @@ export default function EventsSection() {
ipAddress: t("ipAddress"),
};
const form = useForm<UserEventSearchForm>({
mode: "onChange",
defaultValues,
});
const {
getValues,
register,
reset,
formState: { isDirty },
control,
handleSubmit,
} = useForm<UserEventSearchForm>({
mode: "onChange",
defaultValues,
});
} = form;
useFetch(
() => adminClient.realms.getConfigEvents({ realm }),
@ -222,212 +223,196 @@ export default function EventsSection() {
const userEventSearchFormDisplay = () => {
return (
<Flex
direction={{ default: "column" }}
spaceItems={{ default: "spaceItemsNone" }}
>
<FlexItem>
<DropdownPanel
buttonText={t("searchForUserEvent")}
setSearchDropdownOpen={setSearchDropdownOpen}
searchDropdownOpen={searchDropdownOpen}
marginRight="2.5rem"
width="15vw"
>
<Form
data-testid="searchForm"
className="keycloak__events_search__form"
onSubmit={handleSubmit(onSubmit)}
isHorizontal
<FormProvider {...form}>
<Flex
direction={{ default: "column" }}
spaceItems={{ default: "spaceItemsNone" }}
>
<FlexItem>
<DropdownPanel
buttonText={t("searchForUserEvent")}
setSearchDropdownOpen={setSearchDropdownOpen}
searchDropdownOpen={searchDropdownOpen}
marginRight="2.5rem"
width="15vw"
>
<FormGroup
label={t("userId")}
fieldId="kc-userId"
className="keycloak__events_search__form_label"
<Form
data-testid="searchForm"
className="keycloak__events_search__form"
onSubmit={handleSubmit(onSubmit)}
isHorizontal
>
<KeycloakTextInput
id="kc-userId"
<TextControl
name="user"
label={t("userId")}
data-testid="userId-searchField"
{...register("user")}
/>
</FormGroup>
<FormGroup
label={t("eventType")}
fieldId="kc-eventType"
className="keycloak__events_search__form_label"
>
<Controller
name="type"
control={control}
render={({ field }) => (
<Select
className="keycloak__events_search__type_select"
name="eventType"
data-testid="event-type-searchField"
chipGroupProps={{
numChips: 1,
expandedText: t("hide"),
collapsedText: t("showRemaining"),
}}
variant={SelectVariant.typeaheadMulti}
typeAheadAriaLabel="Select"
onToggle={(isOpen) => setSelectOpen(isOpen)}
selections={field.value}
onSelect={(_, selectedValue) => {
const option = selectedValue.toString() as EventType;
const changedValue = field.value.includes(option)
? field.value.filter((item) => item !== option)
: [...field.value, option];
field.onChange(changedValue);
}}
onClear={(event) => {
event.stopPropagation();
field.onChange([]);
}}
isOpen={selectOpen}
aria-labelledby={"eventType"}
chipGroupComponent={
<ChipGroup>
{field.value.map((chip) => (
<Chip
key={chip}
onClick={(event) => {
event.stopPropagation();
field.onChange(
field.value.filter((val) => val !== chip),
);
}}
>
{t(`eventTypes.${chip}.name`)}
</Chip>
))}
</ChipGroup>
}
>
{events?.enabledEventTypes?.map((option) => (
<SelectOption key={option} value={option}>
{t(`eventTypes.${option}.name`)}
</SelectOption>
))}
</Select>
)}
/>
</FormGroup>
<FormGroup
label={t("client")}
fieldId="kc-client"
className="keycloak__events_search__form_label"
>
<KeycloakTextInput
id="kc-client"
data-testid="client-searchField"
{...register("client")}
/>
</FormGroup>
<FormGroup
label={t("dateFrom")}
fieldId="kc-dateFrom"
className="keycloak__events_search__form_label"
>
<Controller
name="dateFrom"
control={control}
render={({ field }) => (
<DatePicker
className="pf-u-w-100"
value={field.value}
onChange={(_, value) => field.onChange(value)}
inputProps={{ id: "kc-dateFrom" }}
/>
)}
/>
</FormGroup>
<FormGroup
label={t("dateTo")}
fieldId="kc-dateTo"
className="keycloak__events_search__form_label"
>
<Controller
name="dateTo"
control={control}
render={({ field }) => (
<DatePicker
className="pf-u-w-100"
value={field.value}
onChange={(_, value) => field.onChange(value)}
inputProps={{ id: "kc-dateTo" }}
/>
)}
/>
</FormGroup>
<FormGroup
label={t("ipAddress")}
fieldId="kc-ipAddress"
className="keycloak__events_search__form_label"
>
<KeycloakTextInput
id="kc-ipAddress"
data-testid="ipAddress-searchField"
{...register("ipAddress")}
/>
</FormGroup>
<ActionGroup>
<Button
data-testid="search-events-btn"
variant="primary"
type="submit"
isDisabled={!isDirty}
<FormGroup
label={t("eventType")}
fieldId="kc-eventType"
className="keycloak__events_search__form_label"
>
{t("searchUserEventsBtn")}
</Button>
<Button
variant="secondary"
onClick={resetSearch}
isDisabled={!isDirty}
>
{t("resetBtn")}
</Button>
</ActionGroup>
</Form>
</DropdownPanel>
</FlexItem>
<FlexItem>
{Object.entries(activeFilters).length > 0 && (
<div className="keycloak__searchChips pf-u-ml-md">
{Object.entries(activeFilters).map((filter) => {
const [key, value] = filter as [
keyof UserEventSearchForm,
string | EventType[],
];
<Controller
name="type"
control={control}
render={({ field }) => (
<Select
className="keycloak__events_search__type_select"
name="eventType"
data-testid="event-type-searchField"
chipGroupProps={{
numChips: 1,
expandedText: t("hide"),
collapsedText: t("showRemaining"),
}}
variant={SelectVariant.typeaheadMulti}
typeAheadAriaLabel="Select"
onToggle={(isOpen) => setSelectOpen(isOpen)}
selections={field.value}
onSelect={(_, selectedValue) => {
const option = selectedValue.toString() as EventType;
const changedValue = field.value.includes(option)
? field.value.filter((item) => item !== option)
: [...field.value, option];
return (
<ChipGroup
className="pf-u-mt-md pf-u-mr-md"
key={key}
categoryName={filterLabels[key]}
isClosable
onClick={() => removeFilter(key)}
>
{typeof value === "string" ? (
<Chip isReadOnly>{value}</Chip>
) : (
value.map((entry) => (
<Chip
key={entry}
onClick={() => removeFilterValue(key, entry)}
>
{t(`eventTypes.${entry}.name`)}
</Chip>
))
field.onChange(changedValue);
}}
onClear={(event) => {
event.stopPropagation();
field.onChange([]);
}}
isOpen={selectOpen}
aria-labelledby={"eventType"}
chipGroupComponent={
<ChipGroup>
{field.value.map((chip) => (
<Chip
key={chip}
onClick={(event) => {
event.stopPropagation();
field.onChange(
field.value.filter((val) => val !== chip),
);
}}
>
{t(`eventTypes.${chip}.name`)}
</Chip>
))}
</ChipGroup>
}
>
{events?.enabledEventTypes?.map((option) => (
<SelectOption key={option} value={option}>
{t(`eventTypes.${option}.name`)}
</SelectOption>
))}
</Select>
)}
</ChipGroup>
);
})}
</div>
)}
</FlexItem>
</Flex>
/>
</FormGroup>
<TextControl
name="client"
label={t("client")}
data-testid="client-searchField"
/>
<FormGroup
label={t("dateFrom")}
fieldId="kc-dateFrom"
className="keycloak__events_search__form_label"
>
<Controller
name="dateFrom"
control={control}
render={({ field }) => (
<DatePicker
className="pf-u-w-100"
value={field.value}
onChange={(_, value) => field.onChange(value)}
inputProps={{ id: "kc-dateFrom" }}
/>
)}
/>
</FormGroup>
<FormGroup
label={t("dateTo")}
fieldId="kc-dateTo"
className="keycloak__events_search__form_label"
>
<Controller
name="dateTo"
control={control}
render={({ field }) => (
<DatePicker
className="pf-u-w-100"
value={field.value}
onChange={(_, value) => field.onChange(value)}
inputProps={{ id: "kc-dateTo" }}
/>
)}
/>
</FormGroup>
<TextControl
name="ipAddress"
label={t("ipAddress")}
data-testid="ipAddress-searchField"
/>
<ActionGroup>
<Button
data-testid="search-events-btn"
variant="primary"
type="submit"
isDisabled={!isDirty}
>
{t("searchUserEventsBtn")}
</Button>
<Button
variant="secondary"
onClick={resetSearch}
isDisabled={!isDirty}
>
{t("resetBtn")}
</Button>
</ActionGroup>
</Form>
</DropdownPanel>
</FlexItem>
<FlexItem>
{Object.entries(activeFilters).length > 0 && (
<div className="keycloak__searchChips pf-u-ml-md">
{Object.entries(activeFilters).map((filter) => {
const [key, value] = filter as [
keyof UserEventSearchForm,
string | EventType[],
];
return (
<ChipGroup
className="pf-u-mt-md pf-u-mr-md"
key={key}
categoryName={filterLabels[key]}
isClosable
onClick={() => removeFilter(key)}
>
{typeof value === "string" ? (
<Chip isReadOnly>{value}</Chip>
) : (
value.map((entry) => (
<Chip
key={entry}
onClick={() => removeFilterValue(key, entry)}
>
{t(`eventTypes.${entry}.name`)}
</Chip>
))
)}
</ChipGroup>
);
})}
</div>
)}
</FlexItem>
</Flex>
</FormProvider>
);
};
@ -501,8 +486,8 @@ export default function EventsSection() {
]}
emptyState={
<ListEmptyState
message={t("emptyEvents")}
instructions={t("emptyEventsInstructions")}
message={t("emptyUserEvents")}
instructions={t("emptyUserEventsInstructions")}
/>
}
isSearching={Object.keys(activeFilters).length > 0}