Replace Lodash with it's ESM variant (#1990)

This commit is contained in:
Jon Koops 2022-02-02 11:33:57 +01:00 committed by GitHub
parent aa19af62e2
commit b9224862de
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
36 changed files with 139 additions and 86 deletions

View file

@ -9,6 +9,7 @@ module.exports = {
env: { env: {
node: true, node: true,
}, },
plugins: ["lodash"],
extends: [ extends: [
"eslint:recommended", "eslint:recommended",
"plugin:react/recommended", "plugin:react/recommended",
@ -30,6 +31,7 @@ module.exports = {
"@typescript-eslint/no-empty-function": "error", "@typescript-eslint/no-empty-function": "error",
"@typescript-eslint/no-unnecessary-condition": "warn", "@typescript-eslint/no-unnecessary-condition": "warn",
"@typescript-eslint/no-unused-vars": "error", "@typescript-eslint/no-unused-vars": "error",
"lodash/import-scope": ["error", "member"],
// react/prop-types cannot handle generic props, so we need to disable it. // react/prop-types cannot handle generic props, so we need to disable it.
// https://github.com/yannickcr/eslint-plugin-react/issues/2777#issuecomment-814968432 // https://github.com/yannickcr/eslint-plugin-react/issues/2777#issuecomment-814968432
"react/prop-types": "off", "react/prop-types": "off",

View file

@ -1,4 +1,4 @@
import { capitalize } from "lodash"; import { capitalize } from "lodash-es";
export default class SidebarPage { export default class SidebarPage {
private realmsDrpDwn = "realmSelectorToggle"; private realmsDrpDwn = "realmSelectorToggle";

View file

@ -4,7 +4,7 @@ import type ClientRepresentation from "@keycloak/keycloak-admin-client/lib/defs/
import type ClientScopeRepresentation from "@keycloak/keycloak-admin-client/lib/defs/clientScopeRepresentation"; import type ClientScopeRepresentation from "@keycloak/keycloak-admin-client/lib/defs/clientScopeRepresentation";
import type RealmRepresentation from "@keycloak/keycloak-admin-client/lib/defs/realmRepresentation"; import type RealmRepresentation from "@keycloak/keycloak-admin-client/lib/defs/realmRepresentation";
import type UserProfileConfig from "@keycloak/keycloak-admin-client/lib/defs/userProfileConfig"; import type UserProfileConfig from "@keycloak/keycloak-admin-client/lib/defs/userProfileConfig";
import { merge } from "lodash"; import { merge } from "lodash-es";
export default class AdminClient { export default class AdminClient {
private client: KeycloakAdminClient; private client: KeycloakAdminClient;

View file

@ -1,4 +1,4 @@
import type { InitialOptionsTsJest } from "ts-jest/dist/types"; import type { InitialOptionsTsJest } from "ts-jest";
const config: InitialOptionsTsJest = { const config: InitialOptionsTsJest = {
preset: "ts-jest", preset: "ts-jest",
@ -11,6 +11,7 @@ const config: InitialOptionsTsJest = {
setupFilesAfterEnv: ["<rootDir>/jest.setup.ts"], setupFilesAfterEnv: ["<rootDir>/jest.setup.ts"],
moduleNameMapper: { moduleNameMapper: {
"\\.css$": "<rootDir>/mocks/fileMock.ts", "\\.css$": "<rootDir>/mocks/fileMock.ts",
"lodash-es": "lodash",
}, },
}; };

57
package-lock.json generated
View file

@ -17,7 +17,7 @@
"file-saver": "^2.0.5", "file-saver": "^2.0.5",
"flat": "^5.0.2", "flat": "^5.0.2",
"i18next": "^21.6.10", "i18next": "^21.6.10",
"lodash": "^4.17.20", "lodash-es": "^4.17.21",
"moment": "^2.29.1", "moment": "^2.29.1",
"react": "^17.0.2", "react": "^17.0.2",
"react-dom": "^17.0.2", "react-dom": "^17.0.2",
@ -43,7 +43,7 @@
"@types/dagre": "^0.7.47", "@types/dagre": "^0.7.47",
"@types/file-saver": "^2.0.5", "@types/file-saver": "^2.0.5",
"@types/flat": "^5.0.2", "@types/flat": "^5.0.2",
"@types/lodash": "^4.14.178", "@types/lodash-es": "^4.17.5",
"@types/node": "^17.0.13", "@types/node": "^17.0.13",
"@types/react": "^17.0.38", "@types/react": "^17.0.38",
"@types/react-dom": "^17.0.11", "@types/react-dom": "^17.0.11",
@ -57,6 +57,7 @@
"eslint": "^8.8.0", "eslint": "^8.8.0",
"eslint-config-prettier": "^8.3.0", "eslint-config-prettier": "^8.3.0",
"eslint-plugin-cypress": "^2.12.1", "eslint-plugin-cypress": "^2.12.1",
"eslint-plugin-lodash": "^7.3.0",
"eslint-plugin-prettier": "^4.0.0", "eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-react": "^7.28.0", "eslint-plugin-react": "^7.28.0",
"fork-ts-checker-webpack-plugin": "^7.0.0", "fork-ts-checker-webpack-plugin": "^7.0.0",
@ -4755,6 +4756,15 @@
"integrity": "sha512-0d5Wd09ItQWH1qFbEyQ7oTQ3GZrMfth5JkbN3EvTKLXcHLRDSXeLnlvlOn0wvxVIwK5o2M8JzP/OWz7T3NRsbw==", "integrity": "sha512-0d5Wd09ItQWH1qFbEyQ7oTQ3GZrMfth5JkbN3EvTKLXcHLRDSXeLnlvlOn0wvxVIwK5o2M8JzP/OWz7T3NRsbw==",
"dev": true "dev": true
}, },
"node_modules/@types/lodash-es": {
"version": "4.17.5",
"resolved": "https://registry.npmjs.org/@types/lodash-es/-/lodash-es-4.17.5.tgz",
"integrity": "sha512-SHBoI8/0aoMQWAgUHMQ599VM6ZiSKg8sh/0cFqqlQQMyY9uEplc0ULU5yQNzcvdR4ZKa0ey8+vFmahuRbOCT1A==",
"dev": true,
"dependencies": {
"@types/lodash": "*"
}
},
"node_modules/@types/node": { "node_modules/@types/node": {
"version": "17.0.13", "version": "17.0.13",
"resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.13.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.13.tgz",
@ -9318,6 +9328,21 @@
"eslint": ">= 3.2.1" "eslint": ">= 3.2.1"
} }
}, },
"node_modules/eslint-plugin-lodash": {
"version": "7.3.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-lodash/-/eslint-plugin-lodash-7.3.0.tgz",
"integrity": "sha512-FQM8HklruJzulPawX3uZqWbeyN3bQT4hjVCpFYMrWo0Hdz1qDCwp1v3JS4zjhdssAXdwCxdnyrNMCZJK70GeUQ==",
"dev": true,
"dependencies": {
"lodash": "^4.17.21"
},
"engines": {
"node": ">=10"
},
"peerDependencies": {
"eslint": ">=2"
}
},
"node_modules/eslint-plugin-prettier": { "node_modules/eslint-plugin-prettier": {
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.0.0.tgz", "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.0.0.tgz",
@ -14604,6 +14629,11 @@
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
}, },
"node_modules/lodash-es": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz",
"integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="
},
"node_modules/lodash.camelcase": { "node_modules/lodash.camelcase": {
"version": "4.3.0", "version": "4.3.0",
"resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz",
@ -25042,6 +25072,15 @@
"integrity": "sha512-0d5Wd09ItQWH1qFbEyQ7oTQ3GZrMfth5JkbN3EvTKLXcHLRDSXeLnlvlOn0wvxVIwK5o2M8JzP/OWz7T3NRsbw==", "integrity": "sha512-0d5Wd09ItQWH1qFbEyQ7oTQ3GZrMfth5JkbN3EvTKLXcHLRDSXeLnlvlOn0wvxVIwK5o2M8JzP/OWz7T3NRsbw==",
"dev": true "dev": true
}, },
"@types/lodash-es": {
"version": "4.17.5",
"resolved": "https://registry.npmjs.org/@types/lodash-es/-/lodash-es-4.17.5.tgz",
"integrity": "sha512-SHBoI8/0aoMQWAgUHMQ599VM6ZiSKg8sh/0cFqqlQQMyY9uEplc0ULU5yQNzcvdR4ZKa0ey8+vFmahuRbOCT1A==",
"dev": true,
"requires": {
"@types/lodash": "*"
}
},
"@types/node": { "@types/node": {
"version": "17.0.13", "version": "17.0.13",
"resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.13.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.13.tgz",
@ -28805,6 +28844,15 @@
"globals": "^11.12.0" "globals": "^11.12.0"
} }
}, },
"eslint-plugin-lodash": {
"version": "7.3.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-lodash/-/eslint-plugin-lodash-7.3.0.tgz",
"integrity": "sha512-FQM8HklruJzulPawX3uZqWbeyN3bQT4hjVCpFYMrWo0Hdz1qDCwp1v3JS4zjhdssAXdwCxdnyrNMCZJK70GeUQ==",
"dev": true,
"requires": {
"lodash": "^4.17.21"
}
},
"eslint-plugin-prettier": { "eslint-plugin-prettier": {
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.0.0.tgz", "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.0.0.tgz",
@ -32647,6 +32695,11 @@
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
}, },
"lodash-es": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz",
"integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="
},
"lodash.camelcase": { "lodash.camelcase": {
"version": "4.3.0", "version": "4.3.0",
"resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz",

View file

@ -33,7 +33,7 @@
"file-saver": "^2.0.5", "file-saver": "^2.0.5",
"flat": "^5.0.2", "flat": "^5.0.2",
"i18next": "^21.6.10", "i18next": "^21.6.10",
"lodash": "^4.17.20", "lodash-es": "^4.17.21",
"moment": "^2.29.1", "moment": "^2.29.1",
"react": "^17.0.2", "react": "^17.0.2",
"react-dom": "^17.0.2", "react-dom": "^17.0.2",
@ -59,7 +59,7 @@
"@types/dagre": "^0.7.47", "@types/dagre": "^0.7.47",
"@types/file-saver": "^2.0.5", "@types/file-saver": "^2.0.5",
"@types/flat": "^5.0.2", "@types/flat": "^5.0.2",
"@types/lodash": "^4.14.178", "@types/lodash-es": "^4.17.5",
"@types/node": "^17.0.13", "@types/node": "^17.0.13",
"@types/react": "^17.0.38", "@types/react": "^17.0.38",
"@types/react-dom": "^17.0.11", "@types/react-dom": "^17.0.11",
@ -73,6 +73,7 @@
"eslint": "^8.8.0", "eslint": "^8.8.0",
"eslint-config-prettier": "^8.3.0", "eslint-config-prettier": "^8.3.0",
"eslint-plugin-cypress": "^2.12.1", "eslint-plugin-cypress": "^2.12.1",
"eslint-plugin-lodash": "^7.3.0",
"eslint-plugin-prettier": "^4.0.0", "eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-react": "^7.28.0", "eslint-plugin-react": "^7.28.0",
"fork-ts-checker-webpack-plugin": "^7.0.0", "fork-ts-checker-webpack-plugin": "^7.0.0",

View file

@ -1,6 +1,6 @@
import React, { ReactNode, useMemo, useRef, useState } from "react"; import React, { ReactNode, useMemo, useRef, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { get } from "lodash"; import { get } from "lodash-es";
import { import {
TableComposable, TableComposable,
Tbody, Tbody,

View file

@ -12,7 +12,7 @@ import {
} from "@patternfly/react-core"; } from "@patternfly/react-core";
import { InfoCircleIcon } from "@patternfly/react-icons"; import { InfoCircleIcon } from "@patternfly/react-icons";
import type ClientRepresentation from "@keycloak/keycloak-admin-client/lib/defs/clientRepresentation"; import type ClientRepresentation from "@keycloak/keycloak-admin-client/lib/defs/clientRepresentation";
import _, { cloneDeep } from "lodash"; import { cloneDeep, sortBy } from "lodash-es";
import React, { useMemo, useState } from "react"; import React, { useMemo, useState } from "react";
import { Controller, FormProvider, useForm, useWatch } from "react-hook-form"; import { Controller, FormProvider, useForm, useWatch } from "react-hook-form";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
@ -224,7 +224,7 @@ export default function ClientDetails() {
const loader = async () => { const loader = async () => {
const roles = await adminClient.clients.listRoles({ id: clientId }); const roles = await adminClient.clients.listRoles({ id: clientId });
return _.sortBy(roles, (role) => role.name?.toUpperCase()); return sortBy(roles, (role) => role.name?.toUpperCase());
}; };
const [toggleDeleteDialog, DeleteConfirm] = useConfirmDialog({ const [toggleDeleteDialog, DeleteConfirm] = useConfirmDialog({

View file

@ -1,7 +1,7 @@
import React, { useState } from "react"; import React, { useState } from "react";
import { Control, Controller } from "react-hook-form"; import { Control, Controller } from "react-hook-form";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import _ from "lodash"; import { sortBy } from "lodash-es";
import { import {
ActionGroup, ActionGroup,
Button, Button,
@ -40,7 +40,7 @@ export const AuthenticationOverrides = ({
let filteredFlows = [ let filteredFlows = [
...flows.filter((flow) => flow.providerId !== "client-flow"), ...flows.filter((flow) => flow.providerId !== "client-flow"),
]; ];
filteredFlows = _.sortBy(filteredFlows, [(f) => f.alias]); filteredFlows = sortBy(filteredFlows, [(f) => f.alias]);
setFlows([ setFlows([
<SelectOption key="empty" value=""> <SelectOption key="empty" value="">
{t("common:choose")} {t("common:choose")}

View file

@ -20,7 +20,7 @@ import { MinusCircleIcon, PlusCircleIcon } from "@patternfly/react-icons";
import "../attribute-form/attribute-form.css"; import "../attribute-form/attribute-form.css";
import { defaultContextAttributes } from "../../clients/utils"; import { defaultContextAttributes } from "../../clients/utils";
import { camelCase } from "lodash"; import { camelCase } from "lodash-es";
import type ResourceRepresentation from "@keycloak/keycloak-admin-client/lib/defs/resourceRepresentation"; import type ResourceRepresentation from "@keycloak/keycloak-admin-client/lib/defs/resourceRepresentation";
export type AttributeType = { export type AttributeType = {

View file

@ -5,7 +5,7 @@ import useBreadcrumbs, {
BreadcrumbsRoute, BreadcrumbsRoute,
} from "use-react-router-breadcrumbs"; } from "use-react-router-breadcrumbs";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import _ from "lodash"; import { uniqBy } from "lodash-es";
import { Breadcrumb, BreadcrumbItem } from "@patternfly/react-core"; import { Breadcrumb, BreadcrumbItem } from "@patternfly/react-core";
import { useRealm } from "../../context/realm-context/RealmContext"; import { useRealm } from "../../context/realm-context/RealmContext";
@ -23,7 +23,7 @@ export const PageBreadCrumbs = () => {
breadcrumb: route.breadcrumb?.(t), breadcrumb: route.breadcrumb?.(t),
})); }));
const crumbs = _.uniqBy( const crumbs = uniqBy(
useBreadcrumbs(routesWithCrumbs, { useBreadcrumbs(routesWithCrumbs, {
disableDefaults: true, disableDefaults: true,
excludePaths: ["/", `/${realm}`], excludePaths: ["/", `/${realm}`],

View file

@ -1,7 +1,7 @@
import React, { useState } from "react"; import React, { useState } from "react";
import { Controller, useFormContext } from "react-hook-form"; import { Controller, useFormContext } from "react-hook-form";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { sortedUniq } from "lodash"; import { sortedUniq } from "lodash-es";
import { import {
FormGroup, FormGroup,
Select, Select,

View file

@ -1,6 +1,6 @@
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import _ from "lodash"; import { findIndex } from "lodash-es";
import { import {
Badge, Badge,
Button, Button,
@ -127,7 +127,7 @@ export const AddRoleMappingModal = ({
}; };
const loader = async () => { const loader = async () => {
const realmRolesSelected = _.findIndex( const realmRolesSelected = findIndex(
selectedClients, selectedClients,
(client) => client.name === "realmRoles" (client) => client.name === "realmRoles"
); );

View file

@ -18,7 +18,7 @@ import {
TableProps, TableProps,
TableVariant, TableVariant,
} from "@patternfly/react-table"; } from "@patternfly/react-table";
import _ from "lodash"; import { get, cloneDeep, differenceBy } from "lodash-es";
import { PaginatingTableToolbar } from "./PaginatingTableToolbar"; import { PaginatingTableToolbar } from "./PaginatingTableToolbar";
import { ListEmptyState } from "../list-empty-state/ListEmptyState"; import { ListEmptyState } from "../list-empty-state/ListEmptyState";
@ -208,7 +208,7 @@ export function KeycloakDataTable<T>({
if (col.cellRenderer) { if (col.cellRenderer) {
return { title: col.cellRenderer(value) }; return { title: col.cellRenderer(value) };
} }
return _.get(value, col.name); return get(value, col.name);
}); });
}; };
@ -223,9 +223,7 @@ export function KeycloakDataTable<T>({
data: value, data: value,
disableSelection: disabledRow, disableSelection: disabledRow,
disableActions: disabledRow, disableActions: disabledRow,
selected: !!selected.find( selected: !!selected.find((v) => get(v, "id") === get(value, "id")),
(v) => _.get(v, "id") === _.get(value, "id")
),
isOpen: isDetailColumnsEnabled(value) ? false : undefined, isOpen: isDetailColumnsEnabled(value) ? false : undefined,
cells: renderCell(columns, value), cells: renderCell(columns, value),
}, },
@ -308,7 +306,7 @@ export function KeycloakDataTable<T>({
const convertAction = () => const convertAction = () =>
actions && actions &&
_.cloneDeep(actions).map((action: Action<T>, index: number) => { cloneDeep(actions).map((action: Action<T>, index: number) => {
delete action.onRowClick; delete action.onRowClick;
action.onClick = async (_, rowIndex) => { action.onClick = async (_, rowIndex) => {
const result = await actions[index].onRowClick!( const result = await actions[index].onRowClick!(
@ -342,7 +340,7 @@ export function KeycloakDataTable<T>({
} }
// Keeps selected items when paginating // Keeps selected items when paginating
const difference = _.differenceBy( const difference = differenceBy(
selected, selected,
data!.map((row) => row.data), data!.map((row) => row.data),
"id" "id"

View file

@ -1,5 +1,5 @@
import type RealmRepresentation from "@keycloak/keycloak-admin-client/lib/defs/realmRepresentation"; import type RealmRepresentation from "@keycloak/keycloak-admin-client/lib/defs/realmRepresentation";
import { sortBy } from "lodash"; import { sortBy } from "lodash-es";
import React, { import React, {
createContext, createContext,
FunctionComponent, FunctionComponent,

View file

@ -22,7 +22,7 @@ import {
} from "@patternfly/react-core"; } from "@patternfly/react-core";
import React from "react"; import React from "react";
import { Trans, useTranslation } from "react-i18next"; import { Trans, useTranslation } from "react-i18next";
import { xor } from "lodash"; import { xor } from "lodash-es";
import { useRealm } from "../context/realm-context/RealmContext"; import { useRealm } from "../context/realm-context/RealmContext";
import { useServerInfo } from "../context/server-info/ServerInfoProvider"; import { useServerInfo } from "../context/server-info/ServerInfoProvider";

View file

@ -31,7 +31,7 @@ import React, { FunctionComponent, useMemo, useState } from "react";
import { Controller, useForm } from "react-hook-form"; import { Controller, useForm } from "react-hook-form";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import { pickBy } from "lodash"; import { pickBy } from "lodash-es";
import { ListEmptyState } from "../components/list-empty-state/ListEmptyState"; import { ListEmptyState } from "../components/list-empty-state/ListEmptyState";
import { KeycloakDataTable } from "../components/table-toolbar/KeycloakDataTable"; import { KeycloakDataTable } from "../components/table-toolbar/KeycloakDataTable";
import { useAdminClient } from "../context/auth/AdminClient"; import { useAdminClient } from "../context/auth/AdminClient";

View file

@ -27,7 +27,7 @@ import { cellWidth, expandable } from "@patternfly/react-table";
import type EventRepresentation from "@keycloak/keycloak-admin-client/lib/defs/eventRepresentation"; import type EventRepresentation from "@keycloak/keycloak-admin-client/lib/defs/eventRepresentation";
import type EventType from "@keycloak/keycloak-admin-client/lib/defs/eventTypes"; import type EventType from "@keycloak/keycloak-admin-client/lib/defs/eventTypes";
import type { RealmEventsConfigRepresentation } from "@keycloak/keycloak-admin-client/lib/defs/realmEventsConfigRepresentation"; import type { RealmEventsConfigRepresentation } from "@keycloak/keycloak-admin-client/lib/defs/realmEventsConfigRepresentation";
import { pickBy } from "lodash"; import { pickBy } from "lodash-es";
import moment from "moment"; import moment from "moment";
import React, { useState } from "react"; import React, { useState } from "react";
import { Controller, useForm } from "react-hook-form"; import { Controller, useForm } from "react-hook-form";

View file

@ -1,7 +1,7 @@
import React, { useState } from "react"; import React, { useState } from "react";
import { Link, useLocation } from "react-router-dom"; import { Link, useLocation } from "react-router-dom";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import _ from "lodash"; import { uniqBy } from "lodash-es";
import { import {
AlertVariant, AlertVariant,
Button, Button,
@ -74,7 +74,7 @@ export const Members = () => {
await adminClient.groups.listMembers({ id: group.id! }) await adminClient.groups.listMembers({ id: group.id! })
); );
} }
members = _.uniqBy(members, (member) => member.username); members = uniqBy(members, (member) => member.username);
} }
const memberOfPromises = await Promise.all( const memberOfPromises = await Promise.all(

View file

@ -16,7 +16,7 @@ import { KeycloakDataTable } from "../components/table-toolbar/KeycloakDataTable
import { ListEmptyState } from "../components/list-empty-state/ListEmptyState"; import { ListEmptyState } from "../components/list-empty-state/ListEmptyState";
import { emptyFormatter } from "../util"; import { emptyFormatter } from "../util";
import { toAddUser } from "../user/routes/AddUser"; import { toAddUser } from "../user/routes/AddUser";
import _ from "lodash"; import { differenceBy } from "lodash-es";
type MemberModalProps = { type MemberModalProps = {
groupId: string; groupId: string;
@ -43,7 +43,7 @@ export const MemberModal = ({ groupId, onClose }: MemberModalProps) => {
try { try {
const users = await adminClient.users.find({ ...params }); const users = await adminClient.users.find({ ...params });
return _.differenceBy(users, members, "id").slice(0, max); return differenceBy(users, members, "id").slice(0, max);
} catch (error) { } catch (error) {
addError("groups:noUsersFoundError", error); addError("groups:noUsersFoundError", error);
return []; return [];

View file

@ -1,7 +1,7 @@
import React, { Fragment, useState } from "react"; import React, { Fragment, useState } from "react";
import { Link, useHistory } from "react-router-dom"; import { Link, useHistory } from "react-router-dom";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import _ from "lodash"; import { sortBy, groupBy } from "lodash-es";
import { import {
AlertVariant, AlertVariant,
Badge, Badge,
@ -41,7 +41,7 @@ import helpUrls from "../help-urls";
export default function IdentityProvidersSection() { export default function IdentityProvidersSection() {
const { t } = useTranslation("identity-providers"); const { t } = useTranslation("identity-providers");
const identityProviders = _.groupBy( const identityProviders = groupBy(
useServerInfo().identityProviders, useServerInfo().identityProviders,
"groupName" "groupName"
); );
@ -74,7 +74,7 @@ export default function IdentityProvidersSection() {
[] []
); );
const loader = () => Promise.resolve(_.sortBy(providers, "alias")); const loader = () => Promise.resolve(sortBy(providers, "alias"));
const DetailLink = (identityProvider: IdentityProviderRepresentation) => ( const DetailLink = (identityProvider: IdentityProviderRepresentation) => (
<Link <Link
@ -112,7 +112,7 @@ export default function IdentityProvidersSection() {
const identityProviderOptions = () => const identityProviderOptions = () =>
Object.keys(identityProviders).map((group) => ( Object.keys(identityProviders).map((group) => (
<DropdownGroup key={group} label={group}> <DropdownGroup key={group} label={group}>
{_.sortBy(identityProviders[group], "name").map((provider) => ( {sortBy(identityProviders[group], "name").map((provider) => (
<DropdownItem <DropdownItem
key={provider.id} key={provider.id}
value={provider.id} value={provider.id}
@ -189,8 +189,7 @@ export default function IdentityProvidersSection() {
</TextContent> </TextContent>
<hr className="pf-u-mb-lg" /> <hr className="pf-u-mb-lg" />
<Gallery hasGutter> <Gallery hasGutter>
{_.sortBy(identityProviders[group], "name").map( {sortBy(identityProviders[group], "name").map((provider) => (
(provider) => (
<Card <Card
className="keycloak-empty-state-card" className="keycloak-empty-state-card"
key={provider.id} key={provider.id}
@ -207,8 +206,7 @@ export default function IdentityProvidersSection() {
</Split> </Split>
</CardTitle> </CardTitle>
</Card> </Card>
) ))}
)}
</Gallery> </Gallery>
</Fragment> </Fragment>
))} ))}

View file

@ -1,6 +1,6 @@
import React, { useState } from "react"; import React, { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import _ from "lodash"; import { sortBy } from "lodash-es";
import { import {
AlertVariant, AlertVariant,
Button, Button,
@ -109,7 +109,7 @@ export const ManageOderDialog = ({
onDragCancel={onDragCancel} onDragCancel={onDragCancel}
itemOrder={order} itemOrder={order}
> >
{_.sortBy(providers, "config.guiOrder").map((provider) => ( {sortBy(providers, "config.guiOrder").map((provider) => (
<DataListItem <DataListItem
aria-labelledby={provider.alias} aria-labelledby={provider.alias}
id={provider.alias} id={provider.alias}

View file

@ -1,6 +1,6 @@
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { omit, sortBy } from "lodash"; import { omit, sortBy } from "lodash-es";
import { import {
Button, Button,
Dropdown, Dropdown,

View file

@ -10,7 +10,7 @@ import {
} from "@patternfly/react-core"; } from "@patternfly/react-core";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { useForm } from "react-hook-form"; import { useForm } from "react-hook-form";
import { omit } from "lodash"; import { omit } from "lodash-es";
import { useAlerts } from "../components/alert/Alerts"; import { useAlerts } from "../components/alert/Alerts";
import { useAdminClient, useFetch } from "../context/auth/AdminClient"; import { useAdminClient, useFetch } from "../context/auth/AdminClient";

View file

@ -1,6 +1,6 @@
import React, { useState } from "react"; import React, { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { cloneDeep, isEqual, uniqWith } from "lodash"; import { cloneDeep, isEqual, uniqWith } from "lodash-es";
import { Controller, useForm, useFormContext, useWatch } from "react-hook-form"; import { Controller, useForm, useFormContext, useWatch } from "react-hook-form";
import { import {
ActionGroup, ActionGroup,

View file

@ -17,7 +17,7 @@ import { FormPanel } from "../components/scroll-form/FormPanel";
import { HelpItem } from "../components/help-enabler/HelpItem"; import { HelpItem } from "../components/help-enabler/HelpItem";
import { useServerInfo } from "../context/server-info/ServerInfoProvider"; import { useServerInfo } from "../context/server-info/ServerInfoProvider";
import type ClientPolicyRepresentation from "@keycloak/keycloak-admin-client/lib/defs/clientPolicyRepresentation"; import type ClientPolicyRepresentation from "@keycloak/keycloak-admin-client/lib/defs/clientPolicyRepresentation";
import { camelCase } from "lodash"; import { camelCase } from "lodash-es";
import { useAdminClient, useFetch } from "../context/auth/AdminClient"; import { useAdminClient, useFetch } from "../context/auth/AdminClient";
import { useAlerts } from "../components/alert/Alerts"; import { useAlerts } from "../components/alert/Alerts";
import { useHistory, useParams } from "react-router"; import { useHistory, useParams } from "react-router";

View file

@ -1,5 +1,5 @@
import React, { useState } from "react"; import React, { useState } from "react";
import { omit } from "lodash"; import { omit } from "lodash-es";
import { import {
ActionGroup, ActionGroup,
AlertVariant, AlertVariant,

View file

@ -14,7 +14,7 @@ import { FormAccess } from "../../components/form-access/FormAccess";
import { useRealm } from "../../context/realm-context/RealmContext"; import { useRealm } from "../../context/realm-context/RealmContext";
import { HelpItem } from "../../components/help-enabler/HelpItem"; import { HelpItem } from "../../components/help-enabler/HelpItem";
import _ from "lodash"; import { isEqual } from "lodash-es";
import { WizardSectionHeader } from "../../components/wizard-section-header/WizardSectionHeader"; import { WizardSectionHeader } from "../../components/wizard-section-header/WizardSectionHeader";
import { useAdminClient, useFetch } from "../../context/auth/AdminClient"; import { useAdminClient, useFetch } from "../../context/auth/AdminClient";
@ -261,7 +261,7 @@ export const KerberosSettingsRequired = ({
/> />
</FormGroup> </FormGroup>
{_.isEqual(allowPassAuth, ["true"]) ? ( {isEqual(allowPassAuth, ["true"]) ? (
<FormGroup <FormGroup
label={t("editMode")} label={t("editMode")}
labelIcon={ labelIcon={

View file

@ -11,7 +11,7 @@ import {
} from "@patternfly/react-core"; } from "@patternfly/react-core";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import React, { useState } from "react"; import React, { useState } from "react";
import _ from "lodash"; import { get, isEqual } from "lodash-es";
import type TestLdapConnectionRepresentation from "@keycloak/keycloak-admin-client/lib/defs/testLdapConnection"; import type TestLdapConnectionRepresentation from "@keycloak/keycloak-admin-client/lib/defs/testLdapConnection";
import { HelpItem } from "../../components/help-enabler/HelpItem"; import { HelpItem } from "../../components/help-enabler/HelpItem";
@ -46,7 +46,7 @@ const convertFormToSettings = (form: UseFormMethods) => {
const settings: TestLdapConnectionRepresentation = {}; const settings: TestLdapConnectionRepresentation = {};
testLdapProperties.forEach((key) => { testLdapProperties.forEach((key) => {
const value = _.get(form.getValues(), `config.${key}`); const value = get(form.getValues(), `config.${key}`);
settings[key] = Array.isArray(value) ? value[0] : ""; settings[key] = Array.isArray(value) ? value[0] : "";
}); });
@ -285,7 +285,7 @@ export const LdapSettingsConnection = ({
></Controller> ></Controller>
</FormGroup> </FormGroup>
{_.isEqual(ldapBindType, ["simple"]) && ( {isEqual(ldapBindType, ["simple"]) && (
<> <>
<FormGroup <FormGroup
label={t("bindDn")} label={t("bindDn")}

View file

@ -10,7 +10,7 @@ import React from "react";
import { HelpItem } from "../../components/help-enabler/HelpItem"; import { HelpItem } from "../../components/help-enabler/HelpItem";
import { UseFormMethods, useWatch, Controller } from "react-hook-form"; import { UseFormMethods, useWatch, Controller } from "react-hook-form";
import { FormAccess } from "../../components/form-access/FormAccess"; import { FormAccess } from "../../components/form-access/FormAccess";
import _ from "lodash"; import { isEqual } from "lodash-es";
import { WizardSectionHeader } from "../../components/wizard-section-header/WizardSectionHeader"; import { WizardSectionHeader } from "../../components/wizard-section-header/WizardSectionHeader";
import useToggle from "../../utils/useToggle"; import useToggle from "../../utils/useToggle";
@ -112,7 +112,7 @@ const CacheFields = ({ form }: { form: UseFormMethods }) => {
)} )}
/> />
</FormGroup> </FormGroup>
{_.isEqual(cachePolicyType, ["EVICT_WEEKLY"]) ? ( {isEqual(cachePolicyType, ["EVICT_WEEKLY"]) ? (
<FormGroup <FormGroup
label={t("evictionDay")} label={t("evictionDay")}
labelIcon={ labelIcon={
@ -168,8 +168,8 @@ const CacheFields = ({ form }: { form: UseFormMethods }) => {
/> />
</FormGroup> </FormGroup>
) : null} ) : null}
{_.isEqual(cachePolicyType, ["EVICT_DAILY"]) || {isEqual(cachePolicyType, ["EVICT_DAILY"]) ||
_.isEqual(cachePolicyType, ["EVICT_WEEKLY"]) ? ( isEqual(cachePolicyType, ["EVICT_WEEKLY"]) ? (
<> <>
<FormGroup <FormGroup
label={t("evictionHour")} label={t("evictionHour")}
@ -237,7 +237,7 @@ const CacheFields = ({ form }: { form: UseFormMethods }) => {
</FormGroup> </FormGroup>
</> </>
) : null} ) : null}
{_.isEqual(cachePolicyType, ["MAX_LIFESPAN"]) ? ( {isEqual(cachePolicyType, ["MAX_LIFESPAN"]) ? (
<FormGroup <FormGroup
label={t("maxLifespan")} label={t("maxLifespan")}
labelIcon={ labelIcon={

View file

@ -12,7 +12,7 @@ import { KeycloakDataTable } from "../components/table-toolbar/KeycloakDataTable
import { emptyFormatter } from "../util"; import { emptyFormatter } from "../util";
import { useAdminClient } from "../context/auth/AdminClient"; import { useAdminClient } from "../context/auth/AdminClient";
import { cellWidth } from "@patternfly/react-table"; import { cellWidth } from "@patternfly/react-table";
import _ from "lodash"; import { sortBy } from "lodash-es";
import type UserConsentRepresentation from "@keycloak/keycloak-admin-client/lib/defs/userConsentRepresentation"; import type UserConsentRepresentation from "@keycloak/keycloak-admin-client/lib/defs/userConsentRepresentation";
import { CubesIcon } from "@patternfly/react-icons"; import { CubesIcon } from "@patternfly/react-icons";
import moment from "moment"; import moment from "moment";
@ -29,7 +29,7 @@ export const UserConsents = () => {
const adminClient = useAdminClient(); const adminClient = useAdminClient();
const { id } = useParams<{ id: string }>(); const { id } = useParams<{ id: string }>();
const alphabetize = (consentsList: UserConsentRepresentation[]) => { const alphabetize = (consentsList: UserConsentRepresentation[]) => {
return _.sortBy(consentsList, (client) => client.clientId?.toUpperCase()); return sortBy(consentsList, (client) => client.clientId?.toUpperCase());
}; };
const refresh = () => setKey(new Date().getTime()); const refresh = () => setKey(new Date().getTime());

View file

@ -9,7 +9,7 @@ import { QuestionCircleIcon } from "@patternfly/react-icons";
import { cellWidth } from "@patternfly/react-table"; import { cellWidth } from "@patternfly/react-table";
import type GroupRepresentation from "@keycloak/keycloak-admin-client/lib/defs/groupRepresentation"; import type GroupRepresentation from "@keycloak/keycloak-admin-client/lib/defs/groupRepresentation";
import type UserRepresentation from "@keycloak/keycloak-admin-client/lib/defs/userRepresentation"; import type UserRepresentation from "@keycloak/keycloak-admin-client/lib/defs/userRepresentation";
import { intersectionBy, sortBy } from "lodash"; import { intersectionBy, sortBy } from "lodash-es";
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { useAlerts } from "../components/alert/Alerts"; import { useAlerts } from "../components/alert/Alerts";

View file

@ -16,7 +16,7 @@ import { useForm } from "react-hook-form";
import type GroupRepresentation from "@keycloak/keycloak-admin-client/lib/defs/groupRepresentation"; import type GroupRepresentation from "@keycloak/keycloak-admin-client/lib/defs/groupRepresentation";
import { useAdminClient } from "../context/auth/AdminClient"; import { useAdminClient } from "../context/auth/AdminClient";
import { useAlerts } from "../components/alert/Alerts"; import { useAlerts } from "../components/alert/Alerts";
import _ from "lodash"; import { capitalize } from "lodash-es";
import { useParams } from "react-router-dom"; import { useParams } from "react-router-dom";
import type FederatedIdentityRepresentation from "@keycloak/keycloak-admin-client/lib/defs/federatedIdentityRepresentation"; import type FederatedIdentityRepresentation from "@keycloak/keycloak-admin-client/lib/defs/federatedIdentityRepresentation";
import type { UserParams } from "./routes/User"; import type { UserParams } from "./routes/User";
@ -60,7 +60,7 @@ export const UserIdpModal = ({
<Modal <Modal
variant={ModalVariant.small} variant={ModalVariant.small}
title={t("users:linkAccountTitle", { title={t("users:linkAccountTitle", {
provider: _.capitalize(federatedId), provider: capitalize(federatedId),
})} })}
isOpen={true} isOpen={true}
onClose={handleModalToggle} onClose={handleModalToggle}
@ -108,7 +108,7 @@ export const UserIdpModal = ({
type="text" type="text"
id="link-idp-name" id="link-idp-name"
name="identityProvider" name="identityProvider"
value={_.capitalize(federatedId)} value={capitalize(federatedId)}
validated={ validated={
errors.identityProvider errors.identityProvider
? ValidatedOptions.error ? ValidatedOptions.error

View file

@ -19,7 +19,7 @@ import type IdentityProviderRepresentation from "@keycloak/keycloak-admin-client
import type FederatedIdentityRepresentation from "@keycloak/keycloak-admin-client/lib/defs/federatedIdentityRepresentation"; import type FederatedIdentityRepresentation from "@keycloak/keycloak-admin-client/lib/defs/federatedIdentityRepresentation";
import { useRealm } from "../context/realm-context/RealmContext"; import { useRealm } from "../context/realm-context/RealmContext";
import { useServerInfo } from "../context/server-info/ServerInfoProvider"; import { useServerInfo } from "../context/server-info/ServerInfoProvider";
import _ from "lodash"; import { capitalize } from "lodash-es";
import { useConfirmDialog } from "../components/confirm-dialog/ConfirmDialog"; import { useConfirmDialog } from "../components/confirm-dialog/ConfirmDialog";
import { useAlerts } from "../components/alert/Alerts"; import { useAlerts } from "../components/alert/Alerts";
import { UserIdpModal } from "./UserIdPModal"; import { UserIdpModal } from "./UserIdPModal";
@ -83,10 +83,10 @@ export const UserIdentityProviderLinks = () => {
const [toggleUnlinkDialog, UnlinkConfirm] = useConfirmDialog({ const [toggleUnlinkDialog, UnlinkConfirm] = useConfirmDialog({
titleKey: t("users:unlinkAccountTitle", { titleKey: t("users:unlinkAccountTitle", {
provider: _.capitalize(federatedId), provider: capitalize(federatedId),
}), }),
messageKey: t("users:unlinkAccountConfirm", { messageKey: t("users:unlinkAccountConfirm", {
provider: _.capitalize(federatedId), provider: capitalize(federatedId),
}), }),
continueButtonLabel: "users:unlink", continueButtonLabel: "users:unlink",
continueButtonVariant: ButtonVariant.primary, continueButtonVariant: ButtonVariant.primary,
@ -114,7 +114,7 @@ export const UserIdentityProviderLinks = () => {
tab: "settings", tab: "settings",
})} })}
> >
{_.capitalize(idp.identityProvider)} {capitalize(idp.identityProvider)}
</Link> </Link>
); );
}; };

View file

@ -1,4 +1,4 @@
import { cloneDeep } from "lodash"; import { cloneDeep } from "lodash-es";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import FileSaver from "file-saver"; import FileSaver from "file-saver";
import type { IFormatter, IFormatterValueType } from "@patternfly/react-table"; import type { IFormatter, IFormatterValueType } from "@patternfly/react-table";

View file

@ -1,6 +1,6 @@
import type { Context } from "react"; import type { Context } from "react";
import { useContext } from "react"; import { useContext } from "react";
import { mocked } from "ts-jest/utils"; import { mocked } from "jest-mock";
import useRequiredContext from "./useRequiredContext"; import useRequiredContext from "./useRequiredContext";
jest.mock("react"); jest.mock("react");