events: reverted to Flex (#1076)

Co-authored-by: Agnieszka Gancarczyk <agancarc@redhat.com>
This commit is contained in:
agagancarczyk 2021-08-26 11:37:56 +01:00 committed by GitHub
parent 2657eaf1d8
commit 764421033f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 392 additions and 378 deletions

View file

@ -3,6 +3,8 @@ import {
Button, Button,
Dropdown, Dropdown,
DropdownToggle, DropdownToggle,
Flex,
FlexItem,
Form, Form,
FormGroup, FormGroup,
Modal, Modal,
@ -11,7 +13,6 @@ import {
SelectVariant, SelectVariant,
TextInput, TextInput,
Tooltip, Tooltip,
ToolbarItem,
} from "@patternfly/react-core"; } from "@patternfly/react-core";
import { import {
cellWidth, cellWidth,
@ -159,136 +160,141 @@ export const AdminEvents = () => {
const adminEventSearchFormDisplay = () => { const adminEventSearchFormDisplay = () => {
return ( return (
<> <>
<ToolbarItem> <Flex
<Dropdown direction={{ default: "column" }}
id="admin-events-search-select" spaceItems={{ default: "spaceItemsNone" }}
data-testid="AdminEventsSearchSelector" >
className="pf-u-ml-md" <FlexItem>
toggle={ <Dropdown
<DropdownToggle id="admin-events-search-select"
data-testid="adminEventsSearchSelectorToggle" data-testid="AdminEventsSearchSelector"
onToggle={(isOpen) => setSearchDropdownOpen(isOpen)} className="pf-u-ml-md"
className="keycloak__events_search_selector_dropdown__toggle" toggle={
> <DropdownToggle
{t("searchForAdminEvent")} data-testid="adminEventsSearchSelectorToggle"
</DropdownToggle> onToggle={(isOpen) => setSearchDropdownOpen(isOpen)}
} className="keycloak__events_search_selector_dropdown__toggle"
isOpen={searchDropdownOpen}
>
<Form
isHorizontal
className="keycloak__admin_events_search__form"
data-testid="searchForm"
>
<FormGroup
label={t("resourceType")}
fieldId="kc-resourceType"
className="keycloak__events_search__form_multiline_label"
>
<Select
variant={SelectVariant.single}
onToggle={(isOpen) => setSelectOpen(isOpen)}
isOpen={selectOpen}
></Select>
</FormGroup>
<FormGroup
label={t("operationType")}
fieldId="kc-operationType"
className="keycloak__events_search__form_multiline_label"
>
<Select
variant={SelectVariant.single}
onToggle={(isOpen) => setSelectOpen(isOpen)}
isOpen={selectOpen}
></Select>
</FormGroup>
<FormGroup
label={t("user")}
fieldId="kc-user"
className="keycloak__events_search__form_label"
>
<TextInput
ref={register()}
type="text"
id="kc-user"
name="user"
data-testid="user-searchField"
/>
</FormGroup>
<FormGroup
label={t("realm")}
fieldId="kc-realm"
className="keycloak__events_search__form_label"
>
<Select
variant={SelectVariant.single}
onToggle={(isOpen) => setSelectOpen(isOpen)}
isOpen={selectOpen}
></Select>
</FormGroup>
<FormGroup
label={t("ipAddress")}
fieldId="kc-ipAddress"
className="keycloak__events_search__form_label"
>
<TextInput
ref={register()}
type="text"
id="kc-ipAddress"
name="ipAddress"
data-testid="ipAddress-searchField"
/>
</FormGroup>
<FormGroup
label={t("dateFrom")}
fieldId="kc-dateFrom"
className="keycloak__events_search__form_label"
>
<TextInput
ref={register()}
type="text"
id="kc-dateFrom"
name="dateFrom"
className="pf-c-form-control pf-m-icon pf-m-calendar"
placeholder="yyyy-MM-dd"
data-testid="dateFrom-searchField"
/>
</FormGroup>
<FormGroup
label={t("dateTo")}
fieldId="kc-dateTo"
className="keycloak__events_search__form_label"
>
<TextInput
ref={register()}
type="text"
id="kc-dateTo"
name="dateTo"
className="pf-c-form-control pf-m-icon pf-m-calendar"
placeholder="yyyy-MM-dd"
data-testid="dateTo-searchField"
/>
</FormGroup>
<ActionGroup>
<Button
className="keycloak__admin_events_search__form_btn"
variant={"primary"}
data-testid="search-events-btn"
isDisabled={!isDirty}
> >
{t("searchAdminEventsBtn")} {t("searchForAdminEvent")}
</Button> </DropdownToggle>
</ActionGroup> }
</Form> isOpen={searchDropdownOpen}
</Dropdown> >
<Button <Form
className="pf-u-ml-md" isHorizontal
onClick={refresh} className="keycloak__admin_events_search__form"
data-testid="refresh-btn" data-testid="searchForm"
> >
{t("refresh")} <FormGroup
</Button> label={t("resourceType")}
</ToolbarItem> fieldId="kc-resourceType"
className="keycloak__events_search__form_multiline_label"
>
<Select
variant={SelectVariant.single}
onToggle={(isOpen) => setSelectOpen(isOpen)}
isOpen={selectOpen}
></Select>
</FormGroup>
<FormGroup
label={t("operationType")}
fieldId="kc-operationType"
className="keycloak__events_search__form_multiline_label"
>
<Select
variant={SelectVariant.single}
onToggle={(isOpen) => setSelectOpen(isOpen)}
isOpen={selectOpen}
></Select>
</FormGroup>
<FormGroup
label={t("user")}
fieldId="kc-user"
className="keycloak__events_search__form_label"
>
<TextInput
ref={register()}
type="text"
id="kc-user"
name="user"
data-testid="user-searchField"
/>
</FormGroup>
<FormGroup
label={t("realm")}
fieldId="kc-realm"
className="keycloak__events_search__form_label"
>
<Select
variant={SelectVariant.single}
onToggle={(isOpen) => setSelectOpen(isOpen)}
isOpen={selectOpen}
></Select>
</FormGroup>
<FormGroup
label={t("ipAddress")}
fieldId="kc-ipAddress"
className="keycloak__events_search__form_label"
>
<TextInput
ref={register()}
type="text"
id="kc-ipAddress"
name="ipAddress"
data-testid="ipAddress-searchField"
/>
</FormGroup>
<FormGroup
label={t("dateFrom")}
fieldId="kc-dateFrom"
className="keycloak__events_search__form_label"
>
<TextInput
ref={register()}
type="text"
id="kc-dateFrom"
name="dateFrom"
className="pf-c-form-control pf-m-icon pf-m-calendar"
placeholder="yyyy-MM-dd"
data-testid="dateFrom-searchField"
/>
</FormGroup>
<FormGroup
label={t("dateTo")}
fieldId="kc-dateTo"
className="keycloak__events_search__form_label"
>
<TextInput
ref={register()}
type="text"
id="kc-dateTo"
name="dateTo"
className="pf-c-form-control pf-m-icon pf-m-calendar"
placeholder="yyyy-MM-dd"
data-testid="dateTo-searchField"
/>
</FormGroup>
<ActionGroup>
<Button
className="keycloak__admin_events_search__form_btn"
variant={"primary"}
data-testid="search-events-btn"
isDisabled={!isDirty}
>
{t("searchAdminEventsBtn")}
</Button>
</ActionGroup>
</Form>
</Dropdown>
<Button
className="pf-u-ml-md"
onClick={refresh}
data-testid="refresh-btn"
>
{t("refresh")}
</Button>
</FlexItem>
</Flex>
</> </>
); );
}; };

View file

@ -9,6 +9,8 @@ import {
DescriptionListTerm, DescriptionListTerm,
Dropdown, Dropdown,
DropdownToggle, DropdownToggle,
Flex,
FlexItem,
Form, Form,
FormGroup, FormGroup,
PageSection, PageSection,
@ -19,13 +21,12 @@ import {
TabTitleText, TabTitleText,
TextInput, TextInput,
Tooltip, Tooltip,
ToolbarItem,
} from "@patternfly/react-core"; } from "@patternfly/react-core";
import { CheckCircleIcon, WarningTriangleIcon } from "@patternfly/react-icons"; import { CheckCircleIcon, WarningTriangleIcon } from "@patternfly/react-icons";
import { cellWidth, expandable } from "@patternfly/react-table"; import { cellWidth, expandable } from "@patternfly/react-table";
import type EventRepresentation from "@keycloak/keycloak-admin-client/lib/defs/eventRepresentation"; import type EventRepresentation from "keycloak-admin/lib/defs/eventRepresentation";
import type EventType from "@keycloak/keycloak-admin-client/lib/defs/eventTypes"; import type EventType from "keycloak-admin/lib/defs/eventTypes";
import type { RealmEventsConfigRepresentation } from "@keycloak/keycloak-admin-client/lib/defs/realmEventsConfigRepresentation"; import type { RealmEventsConfigRepresentation } from "keycloak-admin/lib/defs/realmEventsConfigRepresentation";
import { pickBy } from "lodash"; import { pickBy } from "lodash";
import moment from "moment"; import moment from "moment";
import React, { useState } from "react"; import React, { useState } from "react";
@ -184,204 +185,209 @@ export const EventsSection = () => {
const userEventSearchFormDisplay = () => { const userEventSearchFormDisplay = () => {
return ( return (
<> <>
<ToolbarItem> <Flex
<Dropdown direction={{ default: "column" }}
id="user-events-search-select" spaceItems={{ default: "spaceItemsNone" }}
data-testid="UserEventsSearchSelector" >
className="pf-u-ml-md" <FlexItem>
toggle={ <Dropdown
<DropdownToggle id="user-events-search-select"
data-testid="userEventsSearchSelectorToggle" data-testid="UserEventsSearchSelector"
onToggle={(isOpen) => setSearchDropdownOpen(isOpen)} className="pf-u-ml-md"
className="keycloak__events_search_selector_dropdown__toggle" toggle={
> <DropdownToggle
{t("searchForUserEvent")} data-testid="userEventsSearchSelectorToggle"
</DropdownToggle> onToggle={(isOpen) => setSearchDropdownOpen(isOpen)}
} className="keycloak__events_search_selector_dropdown__toggle"
isOpen={searchDropdownOpen}
>
<Form
isHorizontal
className="keycloak__user_events_search__form"
data-testid="searchForm"
>
<FormGroup
label={t("userId")}
fieldId="kc-userId"
className="keycloak__events_search__form_label"
>
<TextInput
ref={register()}
type="text"
id="kc-userId"
name="user"
data-testid="userId-searchField"
/>
</FormGroup>
<FormGroup
label={t("eventType")}
fieldId="kc-eventType"
className="keycloak__events_search__form_label"
>
<Controller
name="type"
control={control}
render={({
onChange,
value,
}: {
onChange: (newValue: EventType[]) => void;
value: EventType[];
}) => (
<Select
className="keycloak__events_search__event_type_select"
name="eventType"
data-testid="event-type-searchField"
chipGroupProps={{
numChips: 1,
expandedText: "Hide",
collapsedText: "Show ${remaining}",
}}
variant={SelectVariant.typeaheadMulti}
typeAheadAriaLabel="Select"
onToggle={(isOpen) => setSelectOpen(isOpen)}
selections={value}
onSelect={(_, selectedValue) => {
const option = selectedValue.toString() as EventType;
const changedValue = value.includes(option)
? value.filter((item) => item !== option)
: [...value, option];
onChange(changedValue);
}}
onClear={(event) => {
event.stopPropagation();
onChange([]);
}}
isOpen={selectOpen}
aria-labelledby={"eventType"}
chipGroupComponent={
<ChipGroup>
{value.map((chip) => (
<Chip
key={chip}
onClick={(event) => {
event.stopPropagation();
onChange(value.filter((val) => val !== chip));
}}
>
{chip}
</Chip>
))}
</ChipGroup>
}
>
{events?.enabledEventTypes?.map((option) => (
<SelectOption key={option} value={option} />
))}
</Select>
)}
/>
</FormGroup>
<FormGroup
label={t("client")}
fieldId="kc-client"
className="keycloak__events_search__form_label"
>
<TextInput
ref={register()}
type="text"
id="kc-client"
name="client"
data-testid="client-searchField"
/>
</FormGroup>
<FormGroup
label={t("dateFrom")}
fieldId="kc-dateFrom"
className="keycloak__events_search__form_label"
>
<TextInput
ref={register()}
type="text"
id="kc-dateFrom"
name="dateFrom"
className="pf-c-form-control pf-m-icon pf-m-calendar"
placeholder="yyyy-MM-dd"
data-testid="dateFrom-searchField"
/>
</FormGroup>
<FormGroup
label={t("dateTo")}
fieldId="kc-dateTo"
className="keycloak__events_search__form_label"
>
<TextInput
ref={register()}
type="text"
id="kc-dateTo"
name="dateTo"
className="pf-c-form-control pf-m-icon pf-m-calendar"
placeholder="yyyy-MM-dd"
data-testid="dateTo-searchField"
/>
</FormGroup>
<ActionGroup>
<Button
className="keycloak__user_events_search__form_btn"
variant={"primary"}
onClick={submitSearch}
data-testid="search-events-btn"
isDisabled={!isDirty}
> >
{t("searchUserEventsBtn")} {t("searchForUserEvent")}
</Button> </DropdownToggle>
</ActionGroup> }
</Form> isOpen={searchDropdownOpen}
</Dropdown> >
<Button <Form
className="pf-u-ml-md" isHorizontal
onClick={refresh} className="keycloak__user_events_search__form"
data-testid="refresh-btn" data-testid="searchForm"
> >
{t("refresh")} <FormGroup
</Button> label={t("userId")}
</ToolbarItem> fieldId="kc-userId"
<ToolbarItem> className="keycloak__events_search__form_label"
{Object.entries(activeFilters).length > 0 && ( >
<div className="keycloak__searchChips pf-u-ml-md"> <TextInput
{Object.entries(activeFilters).map((filter) => { ref={register()}
const [key, value] = filter as [ type="text"
keyof UserEventSearchForm, id="kc-userId"
string | EventType[] name="user"
]; data-testid="userId-searchField"
/>
</FormGroup>
<FormGroup
label={t("eventType")}
fieldId="kc-eventType"
className="keycloak__events_search__form_label"
>
<Controller
name="type"
control={control}
render={({
onChange,
value,
}: {
onChange: (newValue: EventType[]) => void;
value: EventType[];
}) => (
<Select
className="keycloak__events_search__event_type_select"
name="eventType"
data-testid="event-type-searchField"
chipGroupProps={{
numChips: 1,
expandedText: "Hide",
collapsedText: "Show ${remaining}",
}}
variant={SelectVariant.typeaheadMulti}
typeAheadAriaLabel="Select"
onToggle={(isOpen) => setSelectOpen(isOpen)}
selections={value}
onSelect={(_, selectedValue) => {
const option = selectedValue.toString() as EventType;
const changedValue = value.includes(option)
? value.filter((item) => item !== option)
: [...value, option];
return ( onChange(changedValue);
<ChipGroup }}
className="pf-u-mr-md pf-u-mb-md" onClear={(event) => {
key={key} event.stopPropagation();
categoryName={filterLabels[key]} onChange([]);
isClosable }}
onClick={() => removeFilter(key)} isOpen={selectOpen}
> aria-labelledby={"eventType"}
{typeof value === "string" ? ( chipGroupComponent={
<Chip isReadOnly>{value}</Chip> <ChipGroup>
) : ( {value.map((chip) => (
value.map((entry) => ( <Chip
<Chip key={chip}
key={entry} onClick={(event) => {
onClick={() => removeFilterValue(key, entry)} event.stopPropagation();
> onChange(value.filter((val) => val !== chip));
{entry} }}
</Chip> >
)) {chip}
</Chip>
))}
</ChipGroup>
}
>
{events?.enabledEventTypes?.map((option) => (
<SelectOption key={option} value={option} />
))}
</Select>
)} )}
</ChipGroup> />
); </FormGroup>
})} <FormGroup
</div> label={t("client")}
)} fieldId="kc-client"
</ToolbarItem> className="keycloak__events_search__form_label"
>
<TextInput
ref={register()}
type="text"
id="kc-client"
name="client"
data-testid="client-searchField"
/>
</FormGroup>
<FormGroup
label={t("dateFrom")}
fieldId="kc-dateFrom"
className="keycloak__events_search__form_label"
>
<TextInput
ref={register()}
type="text"
id="kc-dateFrom"
name="dateFrom"
className="pf-c-form-control pf-m-icon pf-m-calendar"
placeholder="yyyy-MM-dd"
data-testid="dateFrom-searchField"
/>
</FormGroup>
<FormGroup
label={t("dateTo")}
fieldId="kc-dateTo"
className="keycloak__events_search__form_label"
>
<TextInput
ref={register()}
type="text"
id="kc-dateTo"
name="dateTo"
className="pf-c-form-control pf-m-icon pf-m-calendar"
placeholder="yyyy-MM-dd"
data-testid="dateTo-searchField"
/>
</FormGroup>
<ActionGroup>
<Button
className="keycloak__user_events_search__form_btn"
variant={"primary"}
onClick={submitSearch}
data-testid="search-events-btn"
isDisabled={!isDirty}
>
{t("searchUserEventsBtn")}
</Button>
</ActionGroup>
</Form>
</Dropdown>
<Button
className="pf-u-ml-md"
onClick={refresh}
data-testid="refresh-btn"
>
{t("refresh")}
</Button>
</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)}
>
{entry}
</Chip>
))
)}
</ChipGroup>
);
})}
</div>
)}
</FlexItem>
</Flex>
</> </>
); );
}; };
@ -408,55 +414,57 @@ export const EventsSection = () => {
eventKey="userEvents" eventKey="userEvents"
title={<TabTitleText>{t("userEvents")}</TabTitleText>} title={<TabTitleText>{t("userEvents")}</TabTitleText>}
> >
<KeycloakDataTable <div className="keycloak__events_table">
key={key} <KeycloakDataTable
loader={loader} key={key}
detailColumns={[ loader={loader}
{ detailColumns={[
name: "details", {
enabled: (event) => event.details !== undefined, name: "details",
cellRenderer: DetailCell, enabled: (event) => event.details !== undefined,
}, cellRenderer: DetailCell,
]} },
isPaginated ]}
ariaLabelKey="events:title" isPaginated
toolbarItem={userEventSearchFormDisplay()} ariaLabelKey="events:title"
columns={[ toolbarItem={userEventSearchFormDisplay()}
{ columns={[
name: "time", {
displayKey: "events:time", name: "time",
cellRenderer: (row) => moment(row.time).format("LLL"), displayKey: "events:time",
cellFormatters: [expandable], cellRenderer: (row) => moment(row.time).format("LLL"),
}, cellFormatters: [expandable],
{ },
name: "userId", {
displayKey: "events:user", name: "userId",
cellRenderer: UserDetailLink, displayKey: "events:user",
}, cellRenderer: UserDetailLink,
{ },
name: "type", {
displayKey: "events:eventType", name: "type",
cellRenderer: StatusRow, displayKey: "events:eventType",
}, cellRenderer: StatusRow,
{ },
name: "ipAddress", {
displayKey: "events:ipAddress", name: "ipAddress",
transforms: [cellWidth(10)], displayKey: "events:ipAddress",
}, transforms: [cellWidth(10)],
{ },
name: "clientId", {
displayKey: "events:client", name: "clientId",
}, displayKey: "events:client",
]} },
emptyState={ ]}
<div className="pf-u-mt-md"> emptyState={
<ListEmptyState <div className="pf-u-mt-md">
message={t("emptyEvents")} <ListEmptyState
instructions={t("emptyEventsInstructions")} message={t("emptyEvents")}
/> instructions={t("emptyEventsInstructions")}
</div> />
} </div>
/> }
/>
</div>
</Tab> </Tab>
<Tab <Tab
eventKey="adminEvents" eventKey="adminEvents"