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:
Alex Khomenko 2024-02-01 06:58:50 +01:00 committed by GitHub
parent 177fa1b947
commit a416bd761d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 142 additions and 143 deletions

View File

@ -1,8 +1,9 @@
import React, { useState, useEffect } from 'react';
import { useForm } from 'react-hook-form';
import { useAsyncFn } from 'react-use';
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 { contextSrv } from 'app/core/core';
import { GrafanaRouteComponentProps } from 'app/core/navigation/types';
@ -27,6 +28,11 @@ const AdminEditOrgPage = ({ match }: Props) => {
const [totalPages, setTotalPages] = useState(1);
const [orgState, fetchOrg] = useAsyncFn(() => getOrg(orgId), []);
const {
handleSubmit,
register,
formState: { errors },
} = useForm<OrgNameDTO>();
const [, fetchOrgUsers] = useAsyncFn(async (page) => {
const result = await getOrgUsers(orgId, page);
@ -45,8 +51,8 @@ const AdminEditOrgPage = ({ match }: Props) => {
fetchOrgUsers(page);
}, [fetchOrg, fetchOrgUsers, page]);
const onUpdateOrgName = async (name: string) => {
await updateOrgName(name, orgId);
const onUpdateOrgName = async ({ orgName }: OrgNameDTO) => {
await updateOrgName(orgName, orgId);
};
const renderMissingPermissionMessage = () => (
@ -82,21 +88,18 @@ const AdminEditOrgPage = ({ match }: Props) => {
<>
<Legend>Edit organization</Legend>
{orgState.value && (
<Form
defaultValues={{ orgName: orgState.value.name }}
onSubmit={(values: OrgNameDTO) => onUpdateOrgName(values.orgName)}
>
{({ register, errors }) => (
<>
<Field label="Name" invalid={!!errors.orgName} error="Name is required" disabled={!canWriteOrg}>
<Input {...register('orgName', { required: true })} id="org-name-input" />
</Field>
<Button type="submit" disabled={!canWriteOrg}>
Update
</Button>
</>
)}
</Form>
<form onSubmit={handleSubmit(onUpdateOrgName)} style={{ maxWidth: '600px' }}>
<Field label="Name" invalid={!!errors.orgName} error="Name is required" disabled={!canWriteOrg}>
<Input
{...register('orgName', { required: true })}
id="org-name-input"
defaultValue={orgState.value.name}
/>
</Field>
<Button type="submit" disabled={!canWriteOrg}>
Update
</Button>
</form>
)}
<div style={{ marginTop: '20px' }}>

View File

@ -1,9 +1,10 @@
import React, { useCallback } from 'react';
import { useForm } from 'react-hook-form';
import { useHistory } from 'react-router-dom';
import { NavModelItem } from '@grafana/data';
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';
interface UserDTO {
@ -24,6 +25,11 @@ const pageNav: NavModelItem = {
const UserCreatePage = () => {
const history = useHistory();
const {
handleSubmit,
register,
formState: { errors },
} = useForm<UserDTO>({ mode: 'onBlur' });
const onSubmit = useCallback(
async (data: UserDTO) => {
@ -37,45 +43,34 @@ const UserCreatePage = () => {
return (
<Page navId="global-users" pageNav={pageNav}>
<Page.Contents>
<Form onSubmit={onSubmit} validateOn="onBlur">
{({ register, errors }) => {
return (
<>
<Field
label="Name"
required
invalid={!!errors.name}
error={errors.name ? 'Name is required' : undefined}
>
<Input id="name-input" {...register('name', { required: true })} />
</Field>
<form onSubmit={handleSubmit(onSubmit)} style={{ maxWidth: '600px' }}>
<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">
<Input id="email-input" {...register('email')} />
</Field>
<Field label="Email">
<Input id="email-input" {...register('email')} />
</Field>
<Field label="Username">
<Input id="username-input" {...register('login')} />
</Field>
<Field
label="Password"
required
invalid={!!errors.password}
error={errors.password ? 'Password is required and must contain at least 4 characters' : undefined}
>
<Input
id="password-input"
{...register('password', {
validate: (value) => value.trim() !== '' && value.length >= 4,
})}
type="password"
/>
</Field>
<Button type="submit">Create user</Button>
</>
);
}}
</Form>
<Field label="Username">
<Input id="username-input" {...register('login')} />
</Field>
<Field
label="Password"
required
invalid={!!errors.password}
error={errors.password ? 'Password is required and must contain at least 4 characters' : undefined}
>
<Input
id="password-input"
{...register('password', {
validate: (value) => value.trim() !== '' && value.length >= 4,
})}
type="password"
/>
</Field>
<Button type="submit">Create user</Button>
</form>
</Page.Contents>
</Page>
);

View File

@ -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 { NavModelItem } from '@grafana/data';
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 { contextSrv } from 'app/core/core';
import { GrafanaRouteComponentProps } from 'app/core/navigation/types';
@ -37,10 +38,6 @@ interface OwnProps extends GrafanaRouteComponentProps<{}, { username?: string }>
userError?: LdapError;
}
interface State {
isLoading: boolean;
}
interface FormModel {
username: string;
}
@ -52,101 +49,105 @@ const pageNav: NavModelItem = {
id: 'LDAP',
};
export class LdapPage extends PureComponent<Props, State> {
state = {
isLoading: true,
};
export const LdapPage = ({
clearUserMappingInfo,
queryParams,
loadLdapState,
loadLdapSyncStatus,
loadUserMapping,
clearUserError,
ldapUser,
userError,
ldapError,
ldapSyncInfo,
ldapConnectionInfo,
}: Props) => {
const [isLoading, setIsLoading] = useState(true);
const { register, handleSubmit } = useForm<FormModel>();
async componentDidMount() {
const { clearUserMappingInfo, queryParams } = this.props;
await clearUserMappingInfo();
await this.fetchLDAPStatus();
const fetchUserMapping = useCallback(
async (username: string) => {
return loadUserMapping(username);
},
[loadUserMapping]
);
if (queryParams.username) {
await this.fetchUserMapping(queryParams.username);
useEffect(() => {
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 { loadLdapState, loadLdapSyncStatus } = this.props;
return Promise.all([loadLdapState(), loadLdapSyncStatus()]);
}
async fetchUserMapping(username: string) {
const { loadUserMapping } = this.props;
return await loadUserMapping(username);
}
search = (username: string) => {
const search = ({ username }: FormModel) => {
if (username) {
this.fetchUserMapping(username);
fetchUserMapping(username);
}
};
onClearUserError = () => {
this.props.clearUserError();
const onClearUserError = () => {
clearUserError();
};
render() {
const { ldapUser, userError, ldapError, ldapSyncInfo, ldapConnectionInfo, queryParams } = this.props;
const { isLoading } = this.state;
const canReadLDAPUser = contextSrv.hasPermission(AccessControlAction.LDAPUsersRead);
const canReadLDAPUser = contextSrv.hasPermission(AccessControlAction.LDAPUsersRead);
return (
<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>
)}
return (
<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} />
<LdapConnectionStatus ldapConnectionInfo={ldapConnectionInfo} />
{featureEnabled('ldapsync') && ldapSyncInfo && <LdapSyncInfo ldapSyncInfo={ldapSyncInfo} />}
{featureEnabled('ldapsync') && ldapSyncInfo && <LdapSyncInfo ldapSyncInfo={ldapSyncInfo} />}
{canReadLDAPUser && (
<section>
<h3>Test user mapping</h3>
<Form onSubmit={(data: FormModel) => this.search(data.username)}>
{({ register }) => (
<Field label="Username">
<Input
{...register('username', { required: true })}
width={34}
id="username"
type="text"
defaultValue={queryParams.username}
addonAfter={
<Button variant="primary" type="submit">
Run
</Button>
}
/>
</Field>
)}
</Form>
{userError && userError.title && (
<Alert
title={userError.title}
severity={AppNotificationSeverity.Error}
onRemove={this.onClearUserError}
>
{userError.body}
</Alert>
)}
{ldapUser && <LdapUserInfo ldapUser={ldapUser} />}
</section>
)}
</Stack>
</Page.Contents>
</Page>
);
}
}
{canReadLDAPUser && (
<section>
<h3>Test user mapping</h3>
<form onSubmit={handleSubmit(search)}>
<Field label="Username">
<Input
{...register('username', { required: true })}
width={34}
id="username"
type="text"
defaultValue={queryParams.username}
addonAfter={
<Button variant="primary" type="submit">
Run
</Button>
}
/>
</Field>
</form>
{userError && userError.title && (
<Alert title={userError.title} severity={AppNotificationSeverity.Error} onRemove={onClearUserError}>
{userError.body}
</Alert>
)}
{ldapUser && <LdapUserInfo ldapUser={ldapUser} />}
</section>
)}
</Stack>
</Page.Contents>
</Page>
);
};
const mapStateToProps = (state: StoreState) => ({
ldapConnectionInfo: state.ldap.connectionInfo,