Files
grafana/public/app/features/manage-dashboards/components/ImportDashboardForm.tsx
Torkel Ödegaard 3d6380a0aa QueryGroup & DataSourceSrv & DataSourcePicker changes simplify usage, error handling and reduce duplication, support for uid (#29542)
* Starting moving more stuff into data source picker

* WIP progress

* Progress on datasource picker rethink

* Things are working now some details to figure out

* Removed commented part

* Complex work on getting data source lists

* Fixed variable support showing correct data sources

* Tried fixing dashboard import but failed

* Fixes

* Fixed import dashboard

* Fixed unit test

* Fixed explore test

* Fixed test

* Fix

* fixed more tests

* fixed more tests

* fixed showing which option is default in picker

* Changed query variable to use data source picker, updated tests and e2e

* Fixed more tests

* Updated snapshots, had wrong typescript version
2020-12-04 14:24:55 +01:00

161 lines
5.1 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 { FolderPicker } from 'app/core/components/Select/FolderPicker';
import { DataSourcePicker } from 'app/core/components/Select/DataSourcePicker';
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"
useNewForms
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';
}