Files
grafana/public/app/features/manage-dashboards/components/ImportDashboardForm.tsx
Marcus Andersson 69201bbf8c Plugins: moving the DataSourcePicker to grafana/runtime so it can be reused in plugins (#31628)
* moved the datasource picker to grafana-runtime.

* fixed imports.

* added e2e selectors as an external package.

* adding react as external package.

* exposing dependent types for DataSourcePicker.

* added docs for ui components.

* moving component to components.
2021-03-18 10:44:26 +01:00

160 lines
5.0 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React, { FC, useEffect, useState } from 'react';
import {
Button,
FormAPI,
FormsOnSubmit,
HorizontalGroup,
FormFieldErrors,
Input,
Field,
InputControl,
Legend,
} from '@grafana/ui';
import { DataSourcePicker } from '@grafana/runtime';
import { FolderPicker } from 'app/core/components/Select/FolderPicker';
import { DashboardInput, DashboardInputs, DataSourceInput, ImportDashboardDTO } from '../state/reducers';
import { validateTitle, validateUid } from '../utils/validation';
interface Props extends Omit<FormAPI<ImportDashboardDTO>, 'formState'> {
uidReset: boolean;
inputs: DashboardInputs;
initialFolderId: number;
onCancel: () => void;
onUidReset: () => void;
onSubmit: FormsOnSubmit<ImportDashboardDTO>;
}
export const ImportDashboardForm: FC<Props> = ({
register,
errors,
control,
getValues,
uidReset,
inputs,
initialFolderId,
onUidReset,
onCancel,
onSubmit,
watch,
}) => {
const [isSubmitted, setSubmitted] = useState(false);
const watchDataSources = watch('dataSources');
/*
This useEffect is needed for overwriting a dashboard. It
submits the form even if there's validation errors on title or uid.
*/
useEffect(() => {
if (isSubmitted && (errors.title || errors.uid)) {
onSubmit(getValues({ nest: true }), {} as any);
}
}, [errors]);
return (
<>
<Legend>Options</Legend>
<Field label="Name" invalid={!!errors.title} error={errors.title && errors.title.message}>
<Input
name="title"
type="text"
ref={register({
required: 'Name is required',
validate: async (v: string) => await validateTitle(v, getValues().folder.id),
})}
/>
</Field>
<Field label="Folder">
<InputControl
as={FolderPicker}
name="folder"
enableCreateNew
initialFolderId={initialFolderId}
control={control}
/>
</Field>
<Field
label="Unique identifier (uid)"
description="The unique identifier (uid) of a dashboard can be used for uniquely identify a dashboard between multiple Grafana installs.
The uid allows having consistent URLs for accessing dashboards so changing the title of a dashboard will not break any
bookmarked links to that dashboard."
invalid={!!errors.uid}
error={errors.uid && errors.uid.message}
>
<>
{!uidReset ? (
<Input
name="uid"
disabled
ref={register({ validate: async (v: string) => await validateUid(v) })}
addonAfter={!uidReset && <Button onClick={onUidReset}>Change uid</Button>}
/>
) : (
<Input name="uid" ref={register({ required: true, validate: async (v: string) => await validateUid(v) })} />
)}
</>
</Field>
{inputs.dataSources &&
inputs.dataSources.map((input: DataSourceInput, index: number) => {
const dataSourceOption = `dataSources[${index}]`;
const current = watchDataSources ?? [];
return (
<Field
label={input.label}
key={dataSourceOption}
invalid={errors.dataSources && !!errors.dataSources[index]}
error={errors.dataSources && errors.dataSources[index] && 'A data source is required'}
>
<InputControl
as={DataSourcePicker}
noDefault={true}
pluginId={input.pluginId}
name={`${dataSourceOption}`}
current={current[index]?.name}
control={control}
placeholder={input.info}
rules={{ required: true }}
/>
</Field>
);
})}
{inputs.constants &&
inputs.constants.map((input: DashboardInput, index) => {
const constantIndex = `constants[${index}]`;
return (
<Field
label={input.label}
error={errors.constants && errors.constants[index] && `${input.label} needs a value`}
invalid={errors.constants && !!errors.constants[index]}
key={constantIndex}
>
<Input ref={register({ required: true })} name={`${constantIndex}`} defaultValue={input.value} />
</Field>
);
})}
<HorizontalGroup>
<Button
type="submit"
variant={getButtonVariant(errors)}
onClick={() => {
setSubmitted(true);
}}
>
{getButtonText(errors)}
</Button>
<Button type="reset" variant="secondary" onClick={onCancel}>
Cancel
</Button>
</HorizontalGroup>
</>
);
};
function getButtonVariant(errors: FormFieldErrors<ImportDashboardDTO>) {
return errors && (errors.title || errors.uid) ? 'destructive' : 'primary';
}
function getButtonText(errors: FormFieldErrors<ImportDashboardDTO>) {
return errors && (errors.title || errors.uid) ? 'Import (Overwrite)' : 'Import';
}