Chore: Remove Form usage from admin components (#81618)
* Chore: Remove Form usage from AdminEditOrgPage * Chore: Remove Form usage from UserCreatePage.tsx * Chore: Transform LdapPage to FC * Chore: Remove Form usage from LdapPage.tsx
This commit is contained in:
@@ -1,8 +1,9 @@
|
|||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
|
import { useForm } from 'react-hook-form';
|
||||||
import { useAsyncFn } from 'react-use';
|
import { useAsyncFn } from 'react-use';
|
||||||
|
|
||||||
import { NavModelItem } from '@grafana/data';
|
import { NavModelItem } from '@grafana/data';
|
||||||
import { Form, Field, Input, Button, Legend, Alert } from '@grafana/ui';
|
import { Field, Input, Button, Legend, Alert } from '@grafana/ui';
|
||||||
import { Page } from 'app/core/components/Page/Page';
|
import { Page } from 'app/core/components/Page/Page';
|
||||||
import { contextSrv } from 'app/core/core';
|
import { contextSrv } from 'app/core/core';
|
||||||
import { GrafanaRouteComponentProps } from 'app/core/navigation/types';
|
import { GrafanaRouteComponentProps } from 'app/core/navigation/types';
|
||||||
@@ -27,6 +28,11 @@ const AdminEditOrgPage = ({ match }: Props) => {
|
|||||||
const [totalPages, setTotalPages] = useState(1);
|
const [totalPages, setTotalPages] = useState(1);
|
||||||
|
|
||||||
const [orgState, fetchOrg] = useAsyncFn(() => getOrg(orgId), []);
|
const [orgState, fetchOrg] = useAsyncFn(() => getOrg(orgId), []);
|
||||||
|
const {
|
||||||
|
handleSubmit,
|
||||||
|
register,
|
||||||
|
formState: { errors },
|
||||||
|
} = useForm<OrgNameDTO>();
|
||||||
const [, fetchOrgUsers] = useAsyncFn(async (page) => {
|
const [, fetchOrgUsers] = useAsyncFn(async (page) => {
|
||||||
const result = await getOrgUsers(orgId, page);
|
const result = await getOrgUsers(orgId, page);
|
||||||
|
|
||||||
@@ -45,8 +51,8 @@ const AdminEditOrgPage = ({ match }: Props) => {
|
|||||||
fetchOrgUsers(page);
|
fetchOrgUsers(page);
|
||||||
}, [fetchOrg, fetchOrgUsers, page]);
|
}, [fetchOrg, fetchOrgUsers, page]);
|
||||||
|
|
||||||
const onUpdateOrgName = async (name: string) => {
|
const onUpdateOrgName = async ({ orgName }: OrgNameDTO) => {
|
||||||
await updateOrgName(name, orgId);
|
await updateOrgName(orgName, orgId);
|
||||||
};
|
};
|
||||||
|
|
||||||
const renderMissingPermissionMessage = () => (
|
const renderMissingPermissionMessage = () => (
|
||||||
@@ -82,21 +88,18 @@ const AdminEditOrgPage = ({ match }: Props) => {
|
|||||||
<>
|
<>
|
||||||
<Legend>Edit organization</Legend>
|
<Legend>Edit organization</Legend>
|
||||||
{orgState.value && (
|
{orgState.value && (
|
||||||
<Form
|
<form onSubmit={handleSubmit(onUpdateOrgName)} style={{ maxWidth: '600px' }}>
|
||||||
defaultValues={{ orgName: orgState.value.name }}
|
<Field label="Name" invalid={!!errors.orgName} error="Name is required" disabled={!canWriteOrg}>
|
||||||
onSubmit={(values: OrgNameDTO) => onUpdateOrgName(values.orgName)}
|
<Input
|
||||||
>
|
{...register('orgName', { required: true })}
|
||||||
{({ register, errors }) => (
|
id="org-name-input"
|
||||||
<>
|
defaultValue={orgState.value.name}
|
||||||
<Field label="Name" invalid={!!errors.orgName} error="Name is required" disabled={!canWriteOrg}>
|
/>
|
||||||
<Input {...register('orgName', { required: true })} id="org-name-input" />
|
</Field>
|
||||||
</Field>
|
<Button type="submit" disabled={!canWriteOrg}>
|
||||||
<Button type="submit" disabled={!canWriteOrg}>
|
Update
|
||||||
Update
|
</Button>
|
||||||
</Button>
|
</form>
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</Form>
|
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div style={{ marginTop: '20px' }}>
|
<div style={{ marginTop: '20px' }}>
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
import React, { useCallback } from 'react';
|
import React, { useCallback } from 'react';
|
||||||
|
import { useForm } from 'react-hook-form';
|
||||||
import { useHistory } from 'react-router-dom';
|
import { useHistory } from 'react-router-dom';
|
||||||
|
|
||||||
import { NavModelItem } from '@grafana/data';
|
import { NavModelItem } from '@grafana/data';
|
||||||
import { getBackendSrv } from '@grafana/runtime';
|
import { getBackendSrv } from '@grafana/runtime';
|
||||||
import { Form, Button, Input, Field } from '@grafana/ui';
|
import { Button, Input, Field } from '@grafana/ui';
|
||||||
import { Page } from 'app/core/components/Page/Page';
|
import { Page } from 'app/core/components/Page/Page';
|
||||||
|
|
||||||
interface UserDTO {
|
interface UserDTO {
|
||||||
@@ -24,6 +25,11 @@ const pageNav: NavModelItem = {
|
|||||||
|
|
||||||
const UserCreatePage = () => {
|
const UserCreatePage = () => {
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
|
const {
|
||||||
|
handleSubmit,
|
||||||
|
register,
|
||||||
|
formState: { errors },
|
||||||
|
} = useForm<UserDTO>({ mode: 'onBlur' });
|
||||||
|
|
||||||
const onSubmit = useCallback(
|
const onSubmit = useCallback(
|
||||||
async (data: UserDTO) => {
|
async (data: UserDTO) => {
|
||||||
@@ -37,45 +43,34 @@ const UserCreatePage = () => {
|
|||||||
return (
|
return (
|
||||||
<Page navId="global-users" pageNav={pageNav}>
|
<Page navId="global-users" pageNav={pageNav}>
|
||||||
<Page.Contents>
|
<Page.Contents>
|
||||||
<Form onSubmit={onSubmit} validateOn="onBlur">
|
<form onSubmit={handleSubmit(onSubmit)} style={{ maxWidth: '600px' }}>
|
||||||
{({ register, errors }) => {
|
<Field label="Name" required invalid={!!errors.name} error={errors.name ? 'Name is required' : undefined}>
|
||||||
return (
|
<Input id="name-input" {...register('name', { required: true })} />
|
||||||
<>
|
</Field>
|
||||||
<Field
|
|
||||||
label="Name"
|
|
||||||
required
|
|
||||||
invalid={!!errors.name}
|
|
||||||
error={errors.name ? 'Name is required' : undefined}
|
|
||||||
>
|
|
||||||
<Input id="name-input" {...register('name', { required: true })} />
|
|
||||||
</Field>
|
|
||||||
|
|
||||||
<Field label="Email">
|
<Field label="Email">
|
||||||
<Input id="email-input" {...register('email')} />
|
<Input id="email-input" {...register('email')} />
|
||||||
</Field>
|
</Field>
|
||||||
|
|
||||||
<Field label="Username">
|
<Field label="Username">
|
||||||
<Input id="username-input" {...register('login')} />
|
<Input id="username-input" {...register('login')} />
|
||||||
</Field>
|
</Field>
|
||||||
<Field
|
<Field
|
||||||
label="Password"
|
label="Password"
|
||||||
required
|
required
|
||||||
invalid={!!errors.password}
|
invalid={!!errors.password}
|
||||||
error={errors.password ? 'Password is required and must contain at least 4 characters' : undefined}
|
error={errors.password ? 'Password is required and must contain at least 4 characters' : undefined}
|
||||||
>
|
>
|
||||||
<Input
|
<Input
|
||||||
id="password-input"
|
id="password-input"
|
||||||
{...register('password', {
|
{...register('password', {
|
||||||
validate: (value) => value.trim() !== '' && value.length >= 4,
|
validate: (value) => value.trim() !== '' && value.length >= 4,
|
||||||
})}
|
})}
|
||||||
type="password"
|
type="password"
|
||||||
/>
|
/>
|
||||||
</Field>
|
</Field>
|
||||||
<Button type="submit">Create user</Button>
|
<Button type="submit">Create user</Button>
|
||||||
</>
|
</form>
|
||||||
);
|
|
||||||
}}
|
|
||||||
</Form>
|
|
||||||
</Page.Contents>
|
</Page.Contents>
|
||||||
</Page>
|
</Page>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
import React, { PureComponent } from 'react';
|
import React, { useCallback, useEffect, useState } from 'react';
|
||||||
|
import { useForm } from 'react-hook-form';
|
||||||
import { connect, ConnectedProps } from 'react-redux';
|
import { connect, ConnectedProps } from 'react-redux';
|
||||||
|
|
||||||
import { NavModelItem } from '@grafana/data';
|
import { NavModelItem } from '@grafana/data';
|
||||||
import { featureEnabled } from '@grafana/runtime';
|
import { featureEnabled } from '@grafana/runtime';
|
||||||
import { Alert, Button, Field, Form, Input, Stack } from '@grafana/ui';
|
import { Alert, Button, Field, Input, Stack } from '@grafana/ui';
|
||||||
import { Page } from 'app/core/components/Page/Page';
|
import { Page } from 'app/core/components/Page/Page';
|
||||||
import { contextSrv } from 'app/core/core';
|
import { contextSrv } from 'app/core/core';
|
||||||
import { GrafanaRouteComponentProps } from 'app/core/navigation/types';
|
import { GrafanaRouteComponentProps } from 'app/core/navigation/types';
|
||||||
@@ -37,10 +38,6 @@ interface OwnProps extends GrafanaRouteComponentProps<{}, { username?: string }>
|
|||||||
userError?: LdapError;
|
userError?: LdapError;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface State {
|
|
||||||
isLoading: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface FormModel {
|
interface FormModel {
|
||||||
username: string;
|
username: string;
|
||||||
}
|
}
|
||||||
@@ -52,101 +49,105 @@ const pageNav: NavModelItem = {
|
|||||||
id: 'LDAP',
|
id: 'LDAP',
|
||||||
};
|
};
|
||||||
|
|
||||||
export class LdapPage extends PureComponent<Props, State> {
|
export const LdapPage = ({
|
||||||
state = {
|
clearUserMappingInfo,
|
||||||
isLoading: true,
|
queryParams,
|
||||||
};
|
loadLdapState,
|
||||||
|
loadLdapSyncStatus,
|
||||||
|
loadUserMapping,
|
||||||
|
clearUserError,
|
||||||
|
ldapUser,
|
||||||
|
userError,
|
||||||
|
ldapError,
|
||||||
|
ldapSyncInfo,
|
||||||
|
ldapConnectionInfo,
|
||||||
|
}: Props) => {
|
||||||
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
|
const { register, handleSubmit } = useForm<FormModel>();
|
||||||
|
|
||||||
async componentDidMount() {
|
const fetchUserMapping = useCallback(
|
||||||
const { clearUserMappingInfo, queryParams } = this.props;
|
async (username: string) => {
|
||||||
await clearUserMappingInfo();
|
return loadUserMapping(username);
|
||||||
await this.fetchLDAPStatus();
|
},
|
||||||
|
[loadUserMapping]
|
||||||
|
);
|
||||||
|
|
||||||
if (queryParams.username) {
|
useEffect(() => {
|
||||||
await this.fetchUserMapping(queryParams.username);
|
const fetchLDAPStatus = async () => {
|
||||||
|
return Promise.all([loadLdapState(), loadLdapSyncStatus()]);
|
||||||
|
};
|
||||||
|
|
||||||
|
async function init() {
|
||||||
|
await clearUserMappingInfo();
|
||||||
|
await fetchLDAPStatus();
|
||||||
|
|
||||||
|
if (queryParams.username) {
|
||||||
|
await fetchUserMapping(queryParams.username);
|
||||||
|
}
|
||||||
|
|
||||||
|
setIsLoading(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setState({ isLoading: false });
|
init();
|
||||||
}
|
}, [clearUserMappingInfo, fetchUserMapping, loadLdapState, loadLdapSyncStatus, queryParams]);
|
||||||
|
|
||||||
async fetchLDAPStatus() {
|
const search = ({ username }: FormModel) => {
|
||||||
const { loadLdapState, loadLdapSyncStatus } = this.props;
|
|
||||||
return Promise.all([loadLdapState(), loadLdapSyncStatus()]);
|
|
||||||
}
|
|
||||||
|
|
||||||
async fetchUserMapping(username: string) {
|
|
||||||
const { loadUserMapping } = this.props;
|
|
||||||
return await loadUserMapping(username);
|
|
||||||
}
|
|
||||||
|
|
||||||
search = (username: string) => {
|
|
||||||
if (username) {
|
if (username) {
|
||||||
this.fetchUserMapping(username);
|
fetchUserMapping(username);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
onClearUserError = () => {
|
const onClearUserError = () => {
|
||||||
this.props.clearUserError();
|
clearUserError();
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
const canReadLDAPUser = contextSrv.hasPermission(AccessControlAction.LDAPUsersRead);
|
||||||
const { ldapUser, userError, ldapError, ldapSyncInfo, ldapConnectionInfo, queryParams } = this.props;
|
return (
|
||||||
const { isLoading } = this.state;
|
<Page navId="authentication" pageNav={pageNav}>
|
||||||
const canReadLDAPUser = contextSrv.hasPermission(AccessControlAction.LDAPUsersRead);
|
<Page.Contents isLoading={isLoading}>
|
||||||
|
<Stack direction="column" gap={4}>
|
||||||
|
{ldapError && ldapError.title && (
|
||||||
|
<Alert title={ldapError.title} severity={AppNotificationSeverity.Error}>
|
||||||
|
{ldapError.body}
|
||||||
|
</Alert>
|
||||||
|
)}
|
||||||
|
|
||||||
return (
|
<LdapConnectionStatus ldapConnectionInfo={ldapConnectionInfo} />
|
||||||
<Page navId="authentication" pageNav={pageNav}>
|
|
||||||
<Page.Contents isLoading={isLoading}>
|
|
||||||
<Stack direction="column" gap={4}>
|
|
||||||
{ldapError && ldapError.title && (
|
|
||||||
<Alert title={ldapError.title} severity={AppNotificationSeverity.Error}>
|
|
||||||
{ldapError.body}
|
|
||||||
</Alert>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<LdapConnectionStatus ldapConnectionInfo={ldapConnectionInfo} />
|
{featureEnabled('ldapsync') && ldapSyncInfo && <LdapSyncInfo ldapSyncInfo={ldapSyncInfo} />}
|
||||||
|
|
||||||
{featureEnabled('ldapsync') && ldapSyncInfo && <LdapSyncInfo ldapSyncInfo={ldapSyncInfo} />}
|
{canReadLDAPUser && (
|
||||||
|
<section>
|
||||||
{canReadLDAPUser && (
|
<h3>Test user mapping</h3>
|
||||||
<section>
|
<form onSubmit={handleSubmit(search)}>
|
||||||
<h3>Test user mapping</h3>
|
<Field label="Username">
|
||||||
<Form onSubmit={(data: FormModel) => this.search(data.username)}>
|
<Input
|
||||||
{({ register }) => (
|
{...register('username', { required: true })}
|
||||||
<Field label="Username">
|
width={34}
|
||||||
<Input
|
id="username"
|
||||||
{...register('username', { required: true })}
|
type="text"
|
||||||
width={34}
|
defaultValue={queryParams.username}
|
||||||
id="username"
|
addonAfter={
|
||||||
type="text"
|
<Button variant="primary" type="submit">
|
||||||
defaultValue={queryParams.username}
|
Run
|
||||||
addonAfter={
|
</Button>
|
||||||
<Button variant="primary" type="submit">
|
}
|
||||||
Run
|
/>
|
||||||
</Button>
|
</Field>
|
||||||
}
|
</form>
|
||||||
/>
|
{userError && userError.title && (
|
||||||
</Field>
|
<Alert title={userError.title} severity={AppNotificationSeverity.Error} onRemove={onClearUserError}>
|
||||||
)}
|
{userError.body}
|
||||||
</Form>
|
</Alert>
|
||||||
{userError && userError.title && (
|
)}
|
||||||
<Alert
|
{ldapUser && <LdapUserInfo ldapUser={ldapUser} />}
|
||||||
title={userError.title}
|
</section>
|
||||||
severity={AppNotificationSeverity.Error}
|
)}
|
||||||
onRemove={this.onClearUserError}
|
</Stack>
|
||||||
>
|
</Page.Contents>
|
||||||
{userError.body}
|
</Page>
|
||||||
</Alert>
|
);
|
||||||
)}
|
};
|
||||||
{ldapUser && <LdapUserInfo ldapUser={ldapUser} />}
|
|
||||||
</section>
|
|
||||||
)}
|
|
||||||
</Stack>
|
|
||||||
</Page.Contents>
|
|
||||||
</Page>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const mapStateToProps = (state: StoreState) => ({
|
const mapStateToProps = (state: StoreState) => ({
|
||||||
ldapConnectionInfo: state.ldap.connectionInfo,
|
ldapConnectionInfo: state.ldap.connectionInfo,
|
||||||
|
|||||||
Reference in New Issue
Block a user