added filter to idp table and manage order (#32889)

* added filter to idp table and manage order

fixes: #32780
Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>

* Update js/apps/admin-ui/maven-resources/theme/keycloak.v2/admin/messages/messages_en.properties

Co-authored-by: Stefan Guilhen <sguilhen@redhat.com>
Signed-off-by: Erik Jan de Wit <edewit@redhat.com>

---------

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>
Signed-off-by: Erik Jan de Wit <edewit@redhat.com>
Co-authored-by: Stefan Guilhen <sguilhen@redhat.com>
This commit is contained in:
Erik Jan de Wit 2024-09-16 13:34:29 +02:00 committed by GitHub
parent 3fe5d4847a
commit 808883c34d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 158 additions and 81 deletions

View file

@ -1481,6 +1481,8 @@ mapperTypeMsadLdsUserAccountControlMapper=msad-user-account-control-mapper
realmSettingsExplain=Realm settings are settings that control the options for users, applications, roles, and groups in the current realm.
mappingUpdatedError=Could not update mapping\: '{{error}}'
manageDisplayOrder=Manage display order
emptyRealmBasedIdps=No realm based identity providers are configured for this realm.
hideOrganizationLinkedIdps=Hide organization linked identity providers
exactSearch=Exact search
value=Value
filenamePlaceholder=Upload a PEM file or paste key below

View file

@ -1,12 +1,20 @@
import type IdentityProviderRepresentation from "@keycloak/keycloak-admin-client/lib/defs/identityProviderRepresentation";
import type { IdentityProvidersQuery } from "@keycloak/keycloak-admin-client/lib/resources/identityProviders";
import { IconMapper, useAlerts, useFetch } from "@keycloak/keycloak-ui-shared";
import {
Action,
IconMapper,
KeycloakDataTable,
ListEmptyState,
useAlerts,
useFetch,
} from "@keycloak/keycloak-ui-shared";
import {
AlertVariant,
Badge,
Button,
ButtonVariant,
CardTitle,
Checkbox,
Dropdown,
DropdownGroup,
DropdownItem,
@ -28,7 +36,6 @@ import { Link, useNavigate } from "react-router-dom";
import { useAdminClient } from "../admin-client";
import { useConfirmDialog } from "../components/confirm-dialog/ConfirmDialog";
import { ClickableCard } from "../components/keycloak-card/ClickableCard";
import { Action, KeycloakDataTable } from "@keycloak/keycloak-ui-shared";
import { ViewHeader } from "../components/view-header/ViewHeader";
import { useRealm } from "../context/realm-context/RealmContext";
import { useServerInfo } from "../context/server-info/ServerInfoProvider";
@ -102,6 +109,7 @@ export default function IdentityProvidersSection() {
const [key, setKey] = useState(0);
const refresh = () => setKey(key + 1);
const [hide, setHide] = useState(false);
const [addProviderOpen, setAddProviderOpen] = useState(false);
const [manageDisplayDialog, setManageDisplayDialog] = useState(false);
const [hasProviders, setHasProviders] = useState(false);
@ -121,6 +129,7 @@ export default function IdentityProvidersSection() {
const params: IdentityProvidersQuery = {
first: first!,
max: max!,
realmOnly: hide,
};
if (search) {
params.search = search;
@ -184,6 +193,7 @@ export default function IdentityProvidersSection() {
<DeleteConfirm />
{manageDisplayDialog && (
<ManageOrderDialog
hideRealmBasedIdps={hide}
onClose={() => {
setManageDisplayDialog(false);
refresh();
@ -243,6 +253,18 @@ export default function IdentityProvidersSection() {
searchPlaceholderKey="searchForProvider"
toolbarItem={
<>
<ToolbarItem alignSelf="center">
<Checkbox
label={t("hideOrganizationLinkedIdps")}
id="hideOrganizationLinkedIdps"
data-testid="hideOrganizationLinkedIdps"
isChecked={hide}
onChange={(_event, check) => {
setHide(check);
refresh();
}}
/>
</ToolbarItem>
<ToolbarItem>
<Dropdown
data-testid="addProviderDropdown"
@ -299,6 +321,23 @@ export default function IdentityProvidersSection() {
cellRenderer: OrganizationLink,
},
]}
emptyState={
<ListEmptyState
message={t("identityProviders")}
instructions={t("emptyRealmBasedIdps")}
isSearchVariant
secondaryActions={[
{
text: t("clearAllFilters"),
onClick: () => {
setHide(false);
refresh();
},
type: ButtonVariant.link,
},
]}
/>
}
/>
)}
</PageSection>

View file

@ -1,5 +1,9 @@
import type IdentityProviderRepresentation from "@keycloak/keycloak-admin-client/lib/defs/identityProviderRepresentation";
import { useAlerts, useFetch } from "@keycloak/keycloak-ui-shared";
import {
KeycloakSpinner,
useAlerts,
useFetch,
} from "@keycloak/keycloak-ui-shared";
import {
Button,
ButtonVariant,
@ -23,13 +27,18 @@ import { sortBy } from "lodash-es";
import { useState } from "react";
import { useTranslation } from "react-i18next";
import { useAdminClient } from "../admin-client";
import { KeycloakSpinner } from "@keycloak/keycloak-ui-shared";
type ManageOrderDialogProps = {
orgId?: string;
hideRealmBasedIdps?: boolean;
onClose: () => void;
};
export const ManageOrderDialog = ({ onClose }: ManageOrderDialogProps) => {
export const ManageOrderDialog = ({
orgId,
hideRealmBasedIdps = false,
onClose,
}: ManageOrderDialogProps) => {
const { adminClient } = useAdminClient();
const { t } = useTranslation();
@ -67,7 +76,10 @@ export const ManageOrderDialog = ({ onClose }: ManageOrderDialogProps) => {
};
useFetch(
() => adminClient.identityProviders.find(),
() =>
orgId
? adminClient.organizations.listIdentityProviders({ orgId })
: adminClient.identityProviders.find({ realmOnly: hideRealmBasedIdps }),
(providers) => {
setProviders(providers);
setOrder(

View file

@ -1,6 +1,7 @@
import IdentityProviderRepresentation from "@keycloak/keycloak-admin-client/lib/defs/identityProviderRepresentation";
import {
KeycloakDataTable,
ListEmptyState,
useAlerts,
useFetch,
} from "@keycloak/keycloak-ui-shared";
@ -17,7 +18,7 @@ import { useTranslation } from "react-i18next";
import { useParams } from "react-router-dom";
import { useAdminClient } from "../admin-client";
import { useConfirmDialog } from "../components/confirm-dialog/ConfirmDialog";
import { ListEmptyState } from "@keycloak/keycloak-ui-shared";
import { ManageOrderDialog } from "../identity-providers/ManageOrderDialog";
import useToggle from "../utils/useToggle";
import { LinkIdentityProviderModal } from "./LinkIdentityProviderModal";
import { EditOrganizationParams } from "./routes/EditOrganization";
@ -74,6 +75,7 @@ export const IdentityProviders = () => {
const [key, setKey] = useState(0);
const refresh = () => setKey(key + 1);
const [manageDisplayDialog, setManageDisplayDialog] = useState(false);
const [hasProviders, setHasProviders] = useState(false);
const [selectedRow, setSelectedRow] =
useState<IdentityProviderRepresentation>();
@ -111,6 +113,16 @@ export const IdentityProviders = () => {
});
return (
<>
{manageDisplayDialog && (
<ManageOrderDialog
orgId={orgId!}
onClose={() => {
setManageDisplayDialog(false);
refresh();
}}
/>
)}
<PageSection variant="light">
<UnlinkConfirm />
{open && (
@ -136,6 +148,7 @@ export const IdentityProviders = () => {
ariaLabelKey="identityProviders"
searchPlaceholderKey="searchProvider"
toolbarItem={
<>
<ToolbarItem>
<Button
onClick={() => {
@ -146,6 +159,16 @@ export const IdentityProviders = () => {
{t("linkIdentityProvider")}
</Button>
</ToolbarItem>
<ToolbarItem>
<Button
data-testid="manageDisplayOrder"
variant="link"
onClick={() => setManageDisplayDialog(true)}
>
{t("manageDisplayOrder")}
</Button>
</ToolbarItem>
</>
}
actions={[
{
@ -194,5 +217,6 @@ export const IdentityProviders = () => {
/>
)}
</PageSection>
</>
);
};