add providers and search functionality

This commit is contained in:
jenny-s51 2021-05-04 15:25:36 -04:00
parent 59f7812a24
commit 345c924e0f
4 changed files with 157 additions and 189 deletions

View file

@ -11,15 +11,7 @@ import {
TableHeader, TableHeader,
TableVariant, TableVariant,
} from "@patternfly/react-table"; } from "@patternfly/react-table";
import { import { Spinner } from "@patternfly/react-core";
DataList,
DataListAction,
DataListCell,
DataListItem,
DataListItemCells,
DataListItemRow,
Spinner,
} from "@patternfly/react-core";
import _ from "lodash"; import _ from "lodash";
import { PaginatingTableToolbar } from "./PaginatingTableToolbar"; import { PaginatingTableToolbar } from "./PaginatingTableToolbar";
@ -55,6 +47,7 @@ type DataTableProps<T> = {
onSelect?: (isSelected: boolean, rowIndex: number) => void; onSelect?: (isSelected: boolean, rowIndex: number) => void;
onCollapse?: (isOpen: boolean, rowIndex: number) => void; onCollapse?: (isOpen: boolean, rowIndex: number) => void;
canSelectAll: boolean; canSelectAll: boolean;
isNotCompact?: boolean;
}; };
function DataTable<T>({ function DataTable<T>({
@ -66,13 +59,14 @@ function DataTable<T>({
onSelect, onSelect,
onCollapse, onCollapse,
canSelectAll, canSelectAll,
isNotCompact,
...props ...props
}: DataTableProps<T>) { }: DataTableProps<T>) {
const { t } = useTranslation(); const { t } = useTranslation();
return ( return (
<Table <Table
{...props} {...props}
variant={TableVariant.compact} variant={isNotCompact ? undefined : TableVariant.compact}
onSelect={ onSelect={
onSelect onSelect
? (_, isSelected, rowIndex) => onSelect(isSelected, rowIndex) ? (_, isSelected, rowIndex) => onSelect(isSelected, rowIndex)
@ -132,6 +126,7 @@ export type DataListProps<T> = {
toolbarItem?: ReactNode; toolbarItem?: ReactNode;
emptyState?: ReactNode; emptyState?: ReactNode;
icon?: React.ComponentClass<SVGIconProps>; icon?: React.ComponentClass<SVGIconProps>;
isNotCompact?: boolean;
}; };
/** /**
@ -163,6 +158,7 @@ export function KeycloakDataTable<T>({
isPaginated = false, isPaginated = false,
onSelect, onSelect,
canSelectAll = false, canSelectAll = false,
isNotCompact,
detailColumns, detailColumns,
isRowDisabled, isRowDisabled,
loader, loader,
@ -391,47 +387,9 @@ export function KeycloakDataTable<T>({
actionResolver={actionResolver} actionResolver={actionResolver}
rows={filteredData || rows} rows={filteredData || rows}
columns={columns} columns={columns}
isNotCompact={isNotCompact}
ariaLabelKey={ariaLabelKey} ariaLabelKey={ariaLabelKey}
/> />
// <DataList
// // onSelectDataListItem={(value) => {
// // setGroupId(value);
// // }}
// aria-label={t("groups")}
// isCompact
// itemOrder={itemOrder}
// >
// {(rows!).map((component) => (
// <DataListItem draggable
// aria-labelledby={"aria"}
// key={"key"}
// id={"id"}
// // onClick={(e) => {
// // if ((e.target as HTMLInputElement).type !== "checkbox") {
// // setGroupId(group.id);
// // }
// // }}
// >
// <DataListItemRow data-testid={"group.name"}>
// <DataListItemCells
// dataListCells={[
// <DataListCell key={`name}`}>
// <>{Math.random()}</>
// </DataListCell>,
// ]}
// />
// <DataListAction
// aria-labelledby={`select`}
// id={`select`}
// aria-label={t("groupName")}
// isPlainButtonAction
// >
// </DataListAction>
// </DataListItemRow>
// </DataListItem>
// ))}
// </DataList>
)} )}
{!loading && {!loading &&
rows.length === 0 && rows.length === 0 &&

View file

@ -1,37 +1,30 @@
import React, { Component, useState, useEffect } from "react"; import React, { useState, useEffect } from "react";
import { useHistory, useRouteMatch } from "react-router-dom";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { import {
Button, Button,
ButtonVariant, ButtonVariant,
DataList, DataList,
DataListAction,
DataListCell, DataListCell,
DataListControl, DataListControl,
DataListDragButton, DataListDragButton,
DataListItem, DataListItem,
DataListItemCells, DataListItemCells,
DataListItemRow, DataListItemRow,
Dropdown,
DropdownToggle,
InputGroup,
PageSection, PageSection,
TextInput,
Toolbar,
ToolbarGroup,
ToolbarItem,
} from "@patternfly/react-core"; } from "@patternfly/react-core";
import { KeyMetadataRepresentation } from "keycloak-admin/lib/defs/keyMetadataRepresentation"; import { KeyMetadataRepresentation } from "keycloak-admin/lib/defs/keyMetadataRepresentation";
import { ListEmptyState } from "../components/list-empty-state/ListEmptyState";
import { KeycloakDataTable } from "../components/table-toolbar/KeycloakDataTable";
import { useConfirmDialog } from "../components/confirm-dialog/ConfirmDialog";
import { emptyFormatter } from "../util";
import ComponentRepresentation from "keycloak-admin/lib/defs/componentRepresentation"; import ComponentRepresentation from "keycloak-admin/lib/defs/componentRepresentation";
import "./RealmSettingsSection.css"; import "./RealmSettingsSection.css";
import {
cellWidth,
Table,
TableBody,
TableHeader,
TableVariant,
} from "@patternfly/react-table";
import ComponentTypeRepresentation from "keycloak-admin/lib/defs/componentTypeRepresentation"; import ComponentTypeRepresentation from "keycloak-admin/lib/defs/componentTypeRepresentation";
import { asyncStateFetch } from "../context/auth/AdminClient"; import { SearchIcon } from "@patternfly/react-icons";
import { useErrorHandler } from "react-error-boundary";
type ComponentData = KeyMetadataRepresentation & { type ComponentData = KeyMetadataRepresentation & {
providerDescription?: string; providerDescription?: string;
@ -44,163 +37,158 @@ type KeysTabInnerProps = {
keyProviderComponentTypes: ComponentTypeRepresentation[]; keyProviderComponentTypes: ComponentTypeRepresentation[];
}; };
export const KeysTabInner = ({ export const KeysTabInner = ({ components }: KeysTabInnerProps) => {
components,
keyProviderComponentTypes,
}: KeysTabInnerProps) => {
const { t } = useTranslation("roles"); const { t } = useTranslation("roles");
const history = useHistory();
const { url } = useRouteMatch();
const [key, setKey] = useState(0);
const refresh = () => setKey(new Date().getTime());
const errorHandler = useErrorHandler();
const [itemOrder, setItemOrder] = useState(["data1", "data2", "data3"]);
const [id, setId] = useState(""); const [id, setId] = useState("");
const [searchVal, setSearchVal] = useState("");
const [filteredComponents, setFilteredComponents] = useState<ComponentData[]>(
[]
);
const loader = async () => { const itemIds = components.map((item, idx) => "data" + idx);
return components;
};
// useEffect( const [itemOrder, setItemOrder] = useState<string[]>([]);
// () =>
// asyncStateFetch(
// async () => {
// return components;
// },
// async () => {
// setFetchedComponents(components) console.log("itemord", itemOrder);
// },
// errorHandler
// ),
// []
// );
React.useEffect(() => { const [liveText, setLiveText] = useState("");
refresh();
}, [components]);
const goToCreate = () => history.push(`${url}/add-role`); useEffect(() => {
setItemOrder(["data", ...itemIds]);
console.log("componentsss", components); }, [components, searchVal]);
const onDragStart = (id: string) => { const onDragStart = (id: string) => {
console.log(itemOrder); setLiveText(t("onDragStart", { id }));
setId(id); setId(id);
}; };
const onDragMove = (oldIndex, newIndex) => { const onDragMove = () => {
console.log(`Dragging item ${id}.`); setLiveText(t("onDragMove", { id }));
}; };
const columns = [ const onDragCancel = () => {
t("realm-settings:name"), setLiveText(t("onDragCancel"));
t("realm-settings:provider"), };
t("realm-settings:providerDescription"),
];
// const onDragCancel = () => { const onDragFinish = (itemOrder: string[]) => {
// this.setState({ setItemOrder(["data", ...itemOrder.filter((i) => i !== "data")]);
// liveText: `Dragging cancelled. List is unchanged.` setLiveText(t("onDragCancel"));
// }); };
// };
const onDragFinish = (itemOrder) => { const onSearch = () => {
setItemOrder(itemOrder); if (searchVal !== "") {
setSearchVal(searchVal);
const x = components.filter((v) => {
return v.name?.includes(searchVal) || v.providerId?.includes(searchVal);
});
setFilteredComponents(x);
} else {
setSearchVal("");
setFilteredComponents(components);
}
};
const handleKeyDown = (e: any) => {
if (e.key === "Enter") {
onSearch();
}
};
const handleInputChange = (value: string) => {
setSearchVal(value);
}; };
return ( return (
<> <>
<PageSection variant="light" padding={{ default: "noPadding" }}> <PageSection variant="light" padding={{ default: "noPadding" }}>
{/* <PublicKeyDialog /> <Toolbar>
<CertificateDialog /> */} <>
{/* <KeycloakDataTable <ToolbarGroup className="providers-toolbar">
key={key} <ToolbarItem>
loader={loader} <InputGroup>
ariaLabelKey="realm-settings:keysList" <TextInput
searchPlaceholderKey="realm-settings:searchKey" name={"inputGroupName"}
canSelectAll id={"inputGroupName"}
columns={[ type="search"
{ aria-label={t("common:search")}
name: "providerId", placeholder={t("common:search")}
displayKey: "realm-settings:name", onChange={handleInputChange}
cellFormatters: [emptyFormatter()], onKeyDown={handleKeyDown}
// cellRenderer: DataCellRendererTest,
transforms: [cellWidth(15)],
},
{
name: "name",
displayKey: "realm-settings:provider",
cellFormatters: [emptyFormatter()],
transforms: [cellWidth(10)],
},
{
name: "providerDescription",
displayKey: "realm-settings:providerDescription",
// cellRenderer: ProviderDescriptionRenderer,
cellFormatters: [emptyFormatter()],
},
]}
emptyState={
<ListEmptyState
hasIcon={true}
message={t("noRoles")}
instructions={t("noRolesInstructions")}
primaryActionText={t("createRole")}
onPrimaryAction={goToCreate}
/> />
} <Button
/> */} variant={ButtonVariant.control}
<Table aria-label={t("common:search")}
aria-label="Simple Table"
// variant={TableVariant}
// borders={choice !== 'compactBorderless'}
cells={columns}
// rows={rows}
> >
<TableHeader /> <SearchIcon />
<TableBody /> </Button>
</Table> </InputGroup>
</ToolbarItem>
<ToolbarItem>
<Dropdown
data-testid="addProviderDropdown"
className="add-provider-dropdown"
onSelect={() => {}}
toggle={
<DropdownToggle isPrimary>
{t("realm-settings:addProvider")}
</DropdownToggle>
}
/>
</ToolbarItem>
</ToolbarGroup>
</>
</Toolbar>
<DataList <DataList
// onSelectDataListItem={(value) => {
// setGroupId(value);
// }}
aria-label={t("groups")} aria-label={t("groups")}
onDragFinish={onDragFinish} onDragFinish={onDragFinish}
onDragStart={onDragStart} onDragStart={onDragStart}
onDragMove={onDragMove} onDragMove={onDragMove}
// onDragCancel={this.onDragCancel} onDragCancel={onDragCancel}
itemOrder={itemOrder} itemOrder={itemOrder}
isCompact isCompact
> >
{/* <DataListItem aria-labelledby={"aria"} id="data1" key="1"> <DataListItem aria-labelledby={"aria"} id="data" key="data">
<DataListItemRow className="test" data-testid={"group.name"}> <DataListItemRow className="test" data-testid={"data-list-row"}>
<DataListItemCells className="test2" <DataListDragButton
className="header-drag-button"
aria-label="Reorder"
aria-labelledby="simple-item"
aria-describedby="Press space or enter to begin dragging, and use the arrow keys to navigate up or down. Press enter to confirm the drag, or any other key to cancel the drag operation."
aria-pressed="false"
isDisabled
/>
<DataListItemCells
className="test2"
dataListCells={[ dataListCells={[
<DataListCell key={"1"}> <DataListCell className="name" key={"1"}>
<>{t("realm-settings:name")}</> <>{t("realm-settings:name")}</>
</DataListCell>, </DataListCell>,
<DataListCell key={"2"}> <DataListCell className="provider" key={"2"}>
<>{t("realm-settings:provider")}</> <>{t("realm-settings:provider")}</>
</DataListCell>, </DataListCell>,
<DataListCell key={"3"}> <DataListCell className="provider-description" key={"3"}>
<>{t("realm-settings:providerDescription")}</> <>{t("realm-settings:providerDescription")}</>
</DataListCell> </DataListCell>,
]} ]}
/> />
</DataListItemRow> </DataListItemRow>
</DataListItem> */} </DataListItem>
{components.map((component, idx) => ( {(filteredComponents.length === 0
? components
: filteredComponents
).map((component, idx) => (
<DataListItem <DataListItem
draggable draggable
aria-labelledby={"aria"} aria-labelledby={"aria"}
key={`key-${idx + 1}`} key={`data${idx}`}
id={`data${idx + 1}`} id={`data${idx}`}
> >
<DataListItemRow data-testid={"data-list-row"}> <DataListItemRow data-testid={"data-list-row"}>
<DataListControl> <DataListControl>
<DataListDragButton <DataListDragButton
className="row-drag-button"
aria-label="Reorder" aria-label="Reorder"
aria-labelledby="simple-item2" aria-labelledby="simple-item2"
aria-describedby="Press space or enter to begin dragging, and use the arrow keys to navigate up or down. Press enter to confirm the drag, or any other key to cancel the drag operation." aria-describedby="Press space or enter to begin dragging, and use the arrow keys to navigate up or down. Press enter to confirm the drag, or any other key to cancel the drag operation."
@ -226,6 +214,9 @@ export const KeysTabInner = ({
</DataListItem> </DataListItem>
))} ))}
</DataList> </DataList>
<div className="pf-screen-reader" aria-live="assertive">
{liveText}
</div>
</PageSection> </PageSection>
</> </>
); );
@ -242,10 +233,6 @@ export const KeysProviderTab = ({
keyProviderComponentTypes, keyProviderComponentTypes,
...props ...props
}: KeysProps) => { }: KeysProps) => {
// console.log("components", components)
// console.log("keyz", keys)
// console.log("keyz", keyProviderComponentTypes)
return ( return (
<KeysTabInner <KeysTabInner
components={components?.map((component) => { components={components?.map((component) => {
@ -256,13 +243,6 @@ export const KeysProviderTab = ({
return { ...component, providerDescription: provider?.helpText }; return { ...component, providerDescription: provider?.helpText };
})} })}
keyProviderComponentTypes={keyProviderComponentTypes} keyProviderComponentTypes={keyProviderComponentTypes}
// keyProviderComponentTypes={keyProviderComponentTypes?.map((key) => {
// const provider = keyProviderComponentTypes.find(
// (key: key) =>
// component.id === key.providerId
// );
// return { ...key, provider: provider?.providerId };
// })}
{...props} {...props}
/> />
); );

View file

@ -24,3 +24,28 @@ button#kc-certificate.pf-c-button.pf-m-secondary {
.pf-c-data-list__item-row.test { .pf-c-data-list__item-row.test {
font-weight: bold; font-weight: bold;
} }
.pf-c-data-list__item-content.test2 {
margin-left: var(--pf-global--spacer--xl);
}
button.pf-c-data-list__item-draggable-button.pf-m-disabled.header-drag-button {
/* --pf-c-data-list__item-draggable-button-icon--Color: white; */
display: none;
}
button.pf-c-data-list__item-draggable-button.row-drag-button {
padding-top: var(--pf-global--spacer--md);
}
.pf-c-data-list__item-control {
margin-right: 0px;
}
button.pf-c-button.pf-m-link.add-provider {
padding: 0px;
}
.pf-c-toolbar__group.providers-toolbar {
padding-left: var(--pf-c-toolbar__content--PaddingLeft);
}

View file

@ -40,6 +40,7 @@
"kid": "Kid", "kid": "Kid",
"provider": "Provider", "provider": "Provider",
"providerDescription": "Provider description", "providerDescription": "Provider description",
"addProvider": "Add provider",
"publicKeys": "Public keys", "publicKeys": "Public keys",
"certificate": "Certificate", "certificate": "Certificate",
"userRegistration": "User registration", "userRegistration": "User registration",
@ -104,5 +105,9 @@
"partial-import": { "partial-import": {
"partialImportHeaderText": "Partial import allows you to import users, clients, and resources from a previously exported json file.", "partialImportHeaderText": "Partial import allows you to import users, clients, and resources from a previously exported json file.",
"import": "Import" "import": "Import"
} },
"onDragStart": "Dragging started for item {{id}}",
"onDragMove": "Dragging item {{id}}",
"onDragCancel": "Dragging cancelled. List is unchanged.",
"onDragFinish": "Dragging finished {{list}}"
} }