mirror of
https://github.com/grafana/grafana.git
synced 2025-02-10 23:55:47 -06:00
155 lines
4.6 KiB
TypeScript
155 lines
4.6 KiB
TypeScript
import { css } from '@emotion/css';
|
|
import { useEffect, useState } from 'react';
|
|
import { UseFormReturn, Controller } from 'react-hook-form';
|
|
|
|
import { Checkbox, Field, Input, SecretInput, Select, Switch, useTheme2 } from '@grafana/ui';
|
|
|
|
import { fieldMap } from './fields';
|
|
import { SSOProviderDTO, SSOSettingsField } from './types';
|
|
import { isSelectableValue } from './utils/guards';
|
|
|
|
interface FieldRendererProps
|
|
extends Pick<UseFormReturn<SSOProviderDTO>, 'register' | 'control' | 'watch' | 'setValue' | 'unregister'> {
|
|
field: SSOSettingsField;
|
|
errors: UseFormReturn['formState']['errors'];
|
|
secretConfigured: boolean;
|
|
provider: string;
|
|
}
|
|
|
|
export const FieldRenderer = ({
|
|
field,
|
|
register,
|
|
errors,
|
|
watch,
|
|
setValue,
|
|
control,
|
|
unregister,
|
|
secretConfigured,
|
|
provider,
|
|
}: FieldRendererProps) => {
|
|
const [isSecretConfigured, setIsSecretConfigured] = useState(secretConfigured);
|
|
const isDependantField = typeof field !== 'string';
|
|
const name = isDependantField ? field.name : field;
|
|
const parentValue = isDependantField ? watch(field.dependsOn) : null;
|
|
const fieldData = fieldMap(provider)[name];
|
|
const theme = useTheme2();
|
|
// Unregister a field that depends on a toggle to clear its data
|
|
useEffect(() => {
|
|
if (isDependantField) {
|
|
if (!parentValue) {
|
|
unregister(name);
|
|
}
|
|
}
|
|
}, [unregister, name, parentValue, isDependantField]);
|
|
|
|
if (!field) {
|
|
console.log('missing field:', name);
|
|
return null;
|
|
}
|
|
|
|
if (!!fieldData.hidden) {
|
|
return null;
|
|
}
|
|
|
|
// Dependant field means the field depends on another field's value and shouldn't be rendered if the parent field is false
|
|
if (isDependantField) {
|
|
const parentValue = watch(field.dependsOn);
|
|
if (!parentValue) {
|
|
return null;
|
|
}
|
|
}
|
|
const fieldProps = {
|
|
label: fieldData.label,
|
|
required: !!fieldData.validation?.required,
|
|
invalid: !!errors[name],
|
|
error: fieldData.validation?.message,
|
|
description: fieldData.description,
|
|
defaultValue: fieldData.defaultValue?.value,
|
|
};
|
|
|
|
switch (fieldData.type) {
|
|
case 'text':
|
|
return (
|
|
<Field key={name} {...fieldProps}>
|
|
<Input {...register(name, fieldData.validation)} type={fieldData.type} id={name} autoComplete={'off'} />
|
|
</Field>
|
|
);
|
|
case 'secret':
|
|
return (
|
|
<Field key={name} {...fieldProps} htmlFor={name}>
|
|
<Controller
|
|
name={name}
|
|
control={control}
|
|
rules={fieldData.validation}
|
|
render={({ field: { ref, value, ...field } }) => (
|
|
<SecretInput
|
|
{...field}
|
|
autoComplete={'off'}
|
|
id={name}
|
|
value={typeof value === 'string' ? value : ''}
|
|
isConfigured={isSecretConfigured}
|
|
onReset={() => {
|
|
setIsSecretConfigured(false);
|
|
setValue(name, '');
|
|
}}
|
|
/>
|
|
)}
|
|
/>
|
|
</Field>
|
|
);
|
|
case 'select':
|
|
const watchOptions = watch(name);
|
|
let options = fieldData.options;
|
|
if (!fieldData.options?.length) {
|
|
options = isSelectableValue(watchOptions) ? watchOptions : [];
|
|
}
|
|
return (
|
|
<Field key={name} {...fieldProps} htmlFor={name}>
|
|
<Controller
|
|
rules={fieldData.validation}
|
|
name={name}
|
|
control={control}
|
|
render={({ field: { ref, onChange, ...fieldProps }, fieldState: { invalid } }) => {
|
|
return (
|
|
<Select
|
|
{...fieldProps}
|
|
placeholder={fieldData.placeholder}
|
|
isMulti={fieldData.multi}
|
|
invalid={invalid}
|
|
inputId={name}
|
|
options={options}
|
|
allowCustomValue={!!fieldData.allowCustomValue}
|
|
defaultValue={fieldData.defaultValue}
|
|
onChange={onChange}
|
|
onCreateOption={(v) => {
|
|
const customValue = { value: v, label: v };
|
|
onChange([...(options || []), customValue]);
|
|
}}
|
|
/>
|
|
);
|
|
}}
|
|
/>
|
|
</Field>
|
|
);
|
|
case 'switch':
|
|
return (
|
|
<Field key={name} {...fieldProps}>
|
|
<Switch {...register(name)} id={name} />
|
|
</Field>
|
|
);
|
|
case 'checkbox':
|
|
return (
|
|
<Checkbox
|
|
key={name}
|
|
{...register(name)}
|
|
id={name}
|
|
{...fieldProps}
|
|
className={css({ marginBottom: theme.spacing(2) })}
|
|
/>
|
|
);
|
|
default:
|
|
console.error(`Unknown field type: ${fieldData.type}`);
|
|
return null;
|
|
}
|
|
};
|