diff --git a/.betterer.results b/.betterer.results index 825dae54803..3afaf609106 100644 --- a/.betterer.results +++ b/.betterer.results @@ -6718,35 +6718,6 @@ exports[`no gf-form usage`] = { [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"] ], - "public/app/features/admin/ldap/LdapConnectionStatus.tsx:5381": [ - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"] - ], - "public/app/features/admin/ldap/LdapSyncInfo.tsx:5381": [ - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"] - ], - "public/app/features/admin/ldap/LdapUserGroups.tsx:5381": [ - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"] - ], - "public/app/features/admin/ldap/LdapUserInfo.tsx:5381": [ - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"] - ], - "public/app/features/admin/ldap/LdapUserMappingInfo.tsx:5381": [ - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"] - ], - "public/app/features/admin/ldap/LdapUserPermissions.tsx:5381": [ - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"] - ], - "public/app/features/admin/ldap/LdapUserTeams.tsx:5381": [ - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"] - ], "public/app/features/admin/partials/edit_org.html:5381": [ [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], diff --git a/public/app/features/admin/ldap/LdapConnectionStatus.tsx b/public/app/features/admin/ldap/LdapConnectionStatus.tsx index 2566a3ff93c..bf4fc842fc8 100644 --- a/public/app/features/admin/ldap/LdapConnectionStatus.tsx +++ b/public/app/features/admin/ldap/LdapConnectionStatus.tsx @@ -1,48 +1,65 @@ -import React from 'react'; +import React, { useMemo } from 'react'; -import { Alert, Icon } from '@grafana/ui'; +import { Alert, CellProps, Column, Icon, InteractiveTable, Stack, Text, Tooltip } from '@grafana/ui'; import { AppNotificationSeverity, LdapConnectionInfo, LdapServerInfo } from 'app/types'; interface Props { ldapConnectionInfo: LdapConnectionInfo; } +interface ServerInfo { + host: string; + port: number; + available: boolean; +} + export const LdapConnectionStatus = ({ ldapConnectionInfo }: Props) => { + const columns = useMemo>>( + () => [ + { + id: 'host', + header: 'Host', + disableGrow: true, + }, + { + id: 'port', + header: 'Port', + disableGrow: true, + }, + { + id: 'available', + cell: (serverInfo: CellProps) => { + return serverInfo.cell.value ? ( + + + + + + ) : ( + + + + + + ); + }, + }, + ], + [] + ); + + const data = useMemo(() => ldapConnectionInfo, [ldapConnectionInfo]); + return ( - <> -

LDAP Connection

-
-
- - - - - - - - - {ldapConnectionInfo && - ldapConnectionInfo.map((serverInfo, index) => ( - - - - - - ))} - -
HostPort
{serverInfo.host}{serverInfo.port} - {serverInfo.available ? ( - - ) : ( - - )} -
-
-
- -
-
- +
+ + + LDAP Connection + + serverInfo.host + serverInfo.port} /> + + +
); }; diff --git a/public/app/features/admin/ldap/LdapPage.tsx b/public/app/features/admin/ldap/LdapPage.tsx index e82df553ddc..d61c7711ca1 100644 --- a/public/app/features/admin/ldap/LdapPage.tsx +++ b/public/app/features/admin/ldap/LdapPage.tsx @@ -3,7 +3,7 @@ import { connect, ConnectedProps } from 'react-redux'; import { NavModelItem } from '@grafana/data'; import { featureEnabled } from '@grafana/runtime'; -import { Alert, Button, Field, Form, HorizontalGroup, Input } from '@grafana/ui'; +import { Alert, Button, Field, Form, Input, Stack } from '@grafana/ui'; import { Page } from 'app/core/components/Page/Page'; import { contextSrv } from 'app/core/core'; import { GrafanaRouteComponentProps } from 'app/core/navigation/types'; @@ -97,7 +97,7 @@ export class LdapPage extends PureComponent { return ( - <> + {ldapError && ldapError.title && ( {ldapError.body} @@ -109,23 +109,24 @@ export class LdapPage extends PureComponent { {featureEnabled('ldapsync') && ldapSyncInfo && } {canReadLDAPUser && ( - <> +

Test user mapping

this.search(data.username)}> {({ register }) => ( - - - - - - + + + Run + + } + /> + )}
{userError && userError.title && ( @@ -137,10 +138,10 @@ export class LdapPage extends PureComponent { {userError.body} )} - {ldapUser && } - + {ldapUser && } +
)} - +
); diff --git a/public/app/features/admin/ldap/LdapSyncInfo.tsx b/public/app/features/admin/ldap/LdapSyncInfo.tsx index aabcd79358b..6dc3dbcf56e 100644 --- a/public/app/features/admin/ldap/LdapSyncInfo.tsx +++ b/public/app/features/admin/ldap/LdapSyncInfo.tsx @@ -1,63 +1,38 @@ -import React, { PureComponent } from 'react'; +import React from 'react'; import { dateTimeFormat } from '@grafana/data'; -import { Button, Spinner } from '@grafana/ui'; +import { InteractiveTable, Text } from '@grafana/ui'; import { SyncInfo } from 'app/types'; interface Props { ldapSyncInfo: SyncInfo; } -interface State { - isSyncing: boolean; -} - const format = 'dddd YYYY-MM-DD HH:mm zz'; -export class LdapSyncInfo extends PureComponent { - state = { - isSyncing: false, - }; +export const LdapSyncInfo = ({ ldapSyncInfo }: Props) => { + const nextSyncTime = dateTimeFormat(ldapSyncInfo.nextSync, { format }); - handleSyncClick = () => { - this.setState({ isSyncing: !this.state.isSyncing }); - }; + const columns = [{ id: 'syncAttribute' }, { id: 'syncValue' }]; + const data = [ + { + syncAttribute: 'Active synchronization', + syncValue: ldapSyncInfo.enabled ? 'Enabled' : 'Disabled', + }, + { + syncAttribute: 'Scheduled', + syncValue: ldapSyncInfo.schedule, + }, + { + syncAttribute: 'Next synchronization', + syncValue: nextSyncTime, + }, + ]; - render() { - const { ldapSyncInfo } = this.props; - const { isSyncing } = this.state; - const nextSyncTime = dateTimeFormat(ldapSyncInfo.nextSync, { format }); - - return ( - <> -

- LDAP Synchronisation - -

-
-
- - - - - - - - - - - - - - - -
Active synchronisation{ldapSyncInfo.enabled ? 'Enabled' : 'Disabled'}
Scheduled{ldapSyncInfo.schedule}
Next scheduled synchronisation{nextSyncTime}
-
-
- - ); - } -} + return ( +
+ LDAP Synchronization + sync.syncAttribute} /> +
+ ); +}; diff --git a/public/app/features/admin/ldap/LdapUserGroups.tsx b/public/app/features/admin/ldap/LdapUserGroups.tsx index 0c8c1a4f83e..d8a628acf95 100644 --- a/public/app/features/admin/ldap/LdapUserGroups.tsx +++ b/public/app/features/admin/ldap/LdapUserGroups.tsx @@ -1,54 +1,52 @@ -import React from 'react'; +import React, { useMemo } from 'react'; -import { Tooltip, Icon } from '@grafana/ui'; +import { Tooltip, Icon, InteractiveTable, type CellProps, Column } from '@grafana/ui'; import { LdapRole } from 'app/types'; interface Props { groups: LdapRole[]; - showAttributeMapping?: boolean; } -export const LdapUserGroups = ({ groups, showAttributeMapping }: Props) => { - const items = showAttributeMapping ? groups : groups.filter((item) => item.orgRole); +export const LdapUserGroups = ({ groups }: Props) => { + const items = useMemo(() => groups, [groups]); + + const columns = useMemo>>( + () => [ + { + id: 'groupDN', + header: 'LDAP Group', + }, + { + id: 'orgName', + header: 'Organization', + cell: (props: CellProps) => + props.value && props.row.original.orgRole ? props.value : '', + }, + { + id: 'orgRole', + header: 'Role', + cell: (props: CellProps) => + props.value || ( + <> + No match{' '} + + + + + ), + }, + ], + [] + ); return ( -
-
- - - - {showAttributeMapping && } - - - - - - {items.map((group, index) => { - return ( - - {showAttributeMapping && } - {group.orgName && group.orgRole ? : - ) : ( - - )} - - ); - })} - -
LDAP Group - Organization - - - - Role
{group.groupDN}{group.orgName}} - {group.orgRole ? ( - {group.orgRole} - No match - - - -
-
-
+ row.orgId + row.orgRole} + /> ); }; diff --git a/public/app/features/admin/ldap/LdapUserInfo.tsx b/public/app/features/admin/ldap/LdapUserInfo.tsx index 441df16acdb..9f14a99f02f 100644 --- a/public/app/features/admin/ldap/LdapUserInfo.tsx +++ b/public/app/features/admin/ldap/LdapUserInfo.tsx @@ -1,5 +1,6 @@ import React from 'react'; +import { Box, Stack, Text } from '@grafana/ui'; import { LdapUser } from 'app/types'; import { LdapUserGroups } from './LdapUserGroups'; @@ -9,33 +10,22 @@ import { LdapUserTeams } from './LdapUserTeams'; interface Props { ldapUser: LdapUser; - showAttributeMapping?: boolean; } -export const LdapUserInfo = ({ ldapUser, showAttributeMapping }: Props) => { +export const LdapUserInfo = ({ ldapUser }: Props) => { return ( - <> - + + - {ldapUser.roles && ldapUser.roles.length > 0 && ( - - )} + {ldapUser.roles && ldapUser.roles.length > 0 && } {ldapUser.teams && ldapUser.teams.length > 0 ? ( - + ) : ( -
-
- - - - - - -
No teams found via LDAP
-
-
+ + No teams found via LDAP + )} - +
); }; diff --git a/public/app/features/admin/ldap/LdapUserMappingInfo.tsx b/public/app/features/admin/ldap/LdapUserMappingInfo.tsx index f762aefd444..c4989e4bf4d 100644 --- a/public/app/features/admin/ldap/LdapUserMappingInfo.tsx +++ b/public/app/features/admin/ldap/LdapUserMappingInfo.tsx @@ -1,47 +1,56 @@ -import React from 'react'; +import React, { useMemo } from 'react'; +import { InteractiveTable } from '@grafana/ui'; import { LdapUserInfo } from 'app/types'; interface Props { info: LdapUserInfo; - showAttributeMapping?: boolean; } -export const LdapUserMappingInfo = ({ info, showAttributeMapping }: Props) => { - return ( -
-
- - - - - {showAttributeMapping && } - - - - - - - {showAttributeMapping && } - - - - - {showAttributeMapping && } - - - - - {showAttributeMapping && } - - - - - {showAttributeMapping && } - - -
User informationLDAP attribute
First name{info.name.ldapValue}{info.name.cfgAttrValue}
Surname{info.surname.ldapValue}{info.surname.cfgAttrValue}
Username{info.login.ldapValue}{info.login.cfgAttrValue}
Email{info.email.ldapValue}{info.email.cfgAttrValue}
-
-
+export const LdapUserMappingInfo = ({ info }: Props) => { + const columns = useMemo( + () => [ + { + id: 'userInfo', + header: 'User Information', + disableGrow: true, + }, + { + id: 'ldapValue', + }, + { + id: 'cfgAttrValue', + header: 'LDAP attribute', + }, + ], + [] ); + + const rows = useMemo( + () => [ + { + userInfo: 'First name', + ldapValue: info.name.ldapValue, + cfgAttrValue: info.name.cfgAttrValue, + }, + { + userInfo: 'Surname', + ldapValue: info.surname.ldapValue, + cfgAttrValue: info.surname.cfgAttrValue, + }, + { + userInfo: 'Username', + ldapValue: info.login.ldapValue, + cfgAttrValue: info.login.cfgAttrValue, + }, + { + userInfo: 'Email', + ldapValue: info.email.ldapValue, + cfgAttrValue: info.email.cfgAttrValue, + }, + ], + [info] + ); + + return row.userInfo} />; }; diff --git a/public/app/features/admin/ldap/LdapUserPermissions.tsx b/public/app/features/admin/ldap/LdapUserPermissions.tsx index f31d0410da8..d206ce2d03c 100644 --- a/public/app/features/admin/ldap/LdapUserPermissions.tsx +++ b/public/app/features/admin/ldap/LdapUserPermissions.tsx @@ -1,52 +1,59 @@ -import React from 'react'; +import React, { useMemo } from 'react'; -import { Icon } from '@grafana/ui'; +import { Column, Icon, InteractiveTable } from '@grafana/ui'; import { LdapPermissions } from 'app/types'; interface Props { permissions: LdapPermissions; } +interface TableRow { + permission: string; + value: React.ReactNode; +} + export const LdapUserPermissions = ({ permissions }: Props) => { - return ( -
-
- - - - - - - - - - - - - - - - -
Permissions
Grafana admin - {permissions.isGrafanaAdmin ? ( - <> - Yes - - ) : ( - 'No' - )} -
Status - {permissions.isDisabled ? ( - <> - Inactive - - ) : ( - <> - Active - - )} -
-
-
+ const columns = useMemo>>( + () => [ + { + id: 'permission', + header: 'Permissions', + disableGrow: true, + }, + { + id: 'value', + }, + ], + [] ); + + const data = useMemo( + () => [ + { + permission: 'Grafana admin', + value: permissions.isGrafanaAdmin ? ( + <> + Yes + + ) : ( + 'No' + ), + }, + { + permission: 'Status', + value: permissions.isDisabled ? ( + <> + Inactive + + ) : ( + <> + Active + + ), + }, + ], + [permissions] + ); + + return row.permission} />; }; diff --git a/public/app/features/admin/ldap/LdapUserTeams.tsx b/public/app/features/admin/ldap/LdapUserTeams.tsx index b6edc7089dc..0df5926099c 100644 --- a/public/app/features/admin/ldap/LdapUserTeams.tsx +++ b/public/app/features/admin/ldap/LdapUserTeams.tsx @@ -1,59 +1,40 @@ -import React from 'react'; +import React, { useMemo } from 'react'; -import { Tooltip, Icon } from '@grafana/ui'; +import { Column, InteractiveTable, CellProps } from '@grafana/ui'; import { LdapTeam } from 'app/types'; interface Props { teams: LdapTeam[]; - showAttributeMapping?: boolean; } -export const LdapUserTeams = ({ teams, showAttributeMapping }: Props) => { - const items = showAttributeMapping ? teams : teams.filter((item) => item.teamName); - - return ( -
-
- - - - {showAttributeMapping && } - - - - - - {items.map((team, index) => { - return ( - - {showAttributeMapping && ( - <> - - {!team.orgName && ( - <> - - - )} - - )} - {team.orgName && ( - <> - - - - )} - - ); - })} - -
LDAP GroupOrganisationTeam
{team.groupDN} - - No match - - - - {team.orgName}{team.teamName}
-
-
+export const LdapUserTeams = ({ teams }: Props) => { + const columns = useMemo>>( + () => [ + { + id: 'groupDN', + header: 'LDAP Group', + }, + { + id: 'orgName', + header: 'Organization', + cell: ({ + row: { + original: { orgName }, + }, + }: CellProps) => <>{orgName || 'No matching teams found'}, + }, + { + id: 'teamName', + header: 'Team', + cell: ({ + row: { + original: { teamName, orgName }, + }, + }: CellProps) => (teamName && orgName ? teamName : ''), + }, + ], + [] ); + + return row.teamName} />; };