Files
grafana/public/app/features/manage-dashboards/components/ImportDashboardForm.tsx
Peter Holmberg ec743cf9a7 Migration: Migrate Dashboard Import to React (#22338)
* first things

* introduce headers and moving buttons

* adding reducer and action for gcom dashboard

* action working

* continue building on import form

* change dashboard title

* add prop to not render a label

* first things

* introduce headers and moving buttons

* adding reducer and action for gcom dashboard

* action working

* continue building on import form

* change dashboard title

* add prop to not render a label

* import form layout

* break out form to component

* add actions and reader for file upload

* fix upload issue

* modified data types to handle both gcom and file upload

* import dashboard json

* save dashboard

* start change uid

* change dashboard uid

* fix spacing and date format

* fix import from json

* handle uid and title change

* revert change in panelinspect

* redo fileupload component

* after review

* redo forms to use Forms functionality

* first attempt on async validation

* use ternary on uid input

* removed unused actions, fixed async validation on form

* post form if invalid, break out form to component

* sync file with master

* fix after merge

* nits

* export formapi type

* redo page to use forms validation

* fix inputs and validation

* readd post

* add guards on data source and constants

* type checks and strict nulls

* strict nulls

* validate onchange and fix import button when valid

* shorten validate call

* reexport OnSubmit type

* add comment for overwrite useEffect

* move validation functions to util

* fix button imports

* remove angular import

* move title and uid validation
2020-03-31 16:29:44 +02:00

156 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, Forms, FormAPI, FormsOnSubmit, HorizontalGroup, FormFieldErrors } 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,
}) => {
const [isSubmitted, setSubmitted] = useState(false);
/*
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 (
<>
<Forms.Legend>Options</Forms.Legend>
<Forms.Field label="Name" invalid={!!errors.title} error={errors.title && errors.title.message}>
<Forms.Input
name="title"
size="md"
type="text"
ref={register({
required: 'Name is required',
validate: async (v: string) => await validateTitle(v, getValues().folderId),
})}
/>
</Forms.Field>
<Forms.Field label="Folder">
<Forms.InputControl
as={FolderPicker}
name="folderId"
useNewForms
initialFolderId={initialFolderId}
control={control}
/>
</Forms.Field>
<Forms.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 ? (
<Forms.Input
size="md"
name="uid"
disabled
ref={register({ validate: async (v: string) => await validateUid(v) })}
addonAfter={!uidReset && <Button onClick={onUidReset}>Change uid</Button>}
/>
) : (
<Forms.Input
size="md"
name="uid"
ref={register({ required: true, validate: async (v: string) => await validateUid(v) })}
/>
)}
</>
</Forms.Field>
{inputs.dataSources &&
inputs.dataSources.map((input: DataSourceInput, index: number) => {
const dataSourceOption = `dataSources[${index}]`;
return (
<Forms.Field
label={input.label}
key={dataSourceOption}
invalid={errors.dataSources && !!errors.dataSources[index]}
error={errors.dataSources && errors.dataSources[index] && 'A data source is required'}
>
<Forms.InputControl
as={DataSourcePicker}
name={`${dataSourceOption}`}
datasources={input.options}
control={control}
placeholder={input.info}
rules={{ required: true }}
/>
</Forms.Field>
);
})}
{inputs.constants &&
inputs.constants.map((input: DashboardInput, index) => {
const constantIndex = `constants[${index}]`;
return (
<Forms.Field
label={input.label}
error={errors.constants && errors.constants[index] && `${input.label} needs a value`}
invalid={errors.constants && !!errors.constants[index]}
key={constantIndex}
>
<Forms.Input
ref={register({ required: true })}
name={`${constantIndex}`}
size="md"
defaultValue={input.value}
/>
</Forms.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';
}