mirror of https://github.com/grafana/grafana.git
159 lines
5.6 KiB
TypeScript
159 lines
5.6 KiB
TypeScript
import { useEffect, useMemo } from 'react';
|
|
import { Controller, useFormContext } from 'react-hook-form';
|
|
|
|
import { Trans, t } from '@grafana/i18n';
|
|
import { Box, Card, Field, Input, LoadingPlaceholder, Stack, Text } from '@grafana/ui';
|
|
import {
|
|
RepositoryViewList,
|
|
useGetRepositoryFilesQuery,
|
|
useGetResourceStatsQuery,
|
|
} from 'app/api/clients/provisioning/v0alpha1';
|
|
import { generateRepositoryTitle } from 'app/features/provisioning/utils/data';
|
|
|
|
import { useStepStatus } from './StepStatusContext';
|
|
import { getResourceStats, useModeOptions } from './actions';
|
|
import { WizardFormData } from './types';
|
|
|
|
export interface Props {
|
|
onOptionSelect: (requiresMigration: boolean) => void;
|
|
settingsData?: RepositoryViewList;
|
|
repoName: string;
|
|
}
|
|
|
|
export function BootstrapStep({ onOptionSelect, settingsData, repoName }: Props) {
|
|
const { setStepStatusInfo } = useStepStatus();
|
|
const {
|
|
register,
|
|
control,
|
|
setValue,
|
|
watch,
|
|
getValues,
|
|
formState: { errors },
|
|
} = useFormContext<WizardFormData>();
|
|
|
|
const resourceStats = useGetResourceStatsQuery();
|
|
const filesQuery = useGetRepositoryFilesQuery({ name: repoName });
|
|
const selectedTarget = watch('repository.sync.target');
|
|
const options = useModeOptions(repoName, settingsData);
|
|
const { target } = options[0];
|
|
const { resourceCount, resourceCountString, fileCount } = useMemo(
|
|
() => getResourceStats(filesQuery.data, resourceStats.data),
|
|
[filesQuery.data, resourceStats.data]
|
|
);
|
|
const requiresMigration = settingsData?.legacyStorage || resourceCount > 0;
|
|
const isLoading = resourceStats.isLoading || filesQuery.isLoading;
|
|
|
|
useEffect(() => {
|
|
// Pick a name nice name based on type+settings
|
|
const repository = getValues('repository');
|
|
const title = generateRepositoryTitle(repository);
|
|
setValue('repository.title', title);
|
|
}, [getValues, setValue]);
|
|
|
|
useEffect(() => {
|
|
setStepStatusInfo({ status: isLoading ? 'running' : 'idle' });
|
|
}, [isLoading, setStepStatusInfo]);
|
|
|
|
useEffect(() => {
|
|
setValue('repository.sync.target', target);
|
|
onOptionSelect(requiresMigration);
|
|
}, [target, setValue, onOptionSelect, requiresMigration]);
|
|
|
|
if (isLoading) {
|
|
return (
|
|
<Box padding={4}>
|
|
<LoadingPlaceholder
|
|
text={t('provisioning.bootstrap-step.text-loading-resource-information', 'Loading resource information...')}
|
|
/>
|
|
</Box>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<Stack direction="column" gap={2}>
|
|
<Stack direction="column" gap={2}>
|
|
<Box alignItems="center" padding={4}>
|
|
<Stack direction="row" gap={4} alignItems="flex-start" justifyContent="center">
|
|
<Stack direction="column" gap={1} alignItems="center">
|
|
<Text color="secondary">
|
|
<Trans i18nKey="provisioning.bootstrap-step.grafana">Grafana instance</Trans>
|
|
</Text>
|
|
<Stack direction="row" gap={2}>
|
|
<Text variant="h4">
|
|
{resourceCount > 0 ? resourceCountString : t('provisioning.bootstrap-step.empty', 'Empty')}
|
|
</Text>
|
|
</Stack>
|
|
</Stack>
|
|
<Stack direction="column" gap={1} alignItems="center">
|
|
<Text color="secondary">
|
|
<Trans i18nKey="provisioning.bootstrap-step.ext-storage">External storage</Trans>
|
|
</Text>
|
|
<Text variant="h4">
|
|
{fileCount > 0
|
|
? t('provisioning.bootstrap-step.files-count', '{{count}} files', { count: fileCount })
|
|
: t('provisioning.bootstrap-step.empty', 'Empty')}
|
|
</Text>
|
|
</Stack>
|
|
</Stack>
|
|
</Box>
|
|
|
|
<Controller
|
|
name="repository.sync.target"
|
|
control={control}
|
|
render={({ field: { ref, onChange, ...field } }) => (
|
|
<>
|
|
{options.map((action) => (
|
|
<Card
|
|
key={action.target}
|
|
isSelected={action.target === selectedTarget}
|
|
onClick={() => {
|
|
onChange(action.target);
|
|
}}
|
|
noMargin
|
|
{...field}
|
|
>
|
|
<Card.Heading>{action.label}</Card.Heading>
|
|
<Card.Description>
|
|
<Stack direction="column" gap={3}>
|
|
{action.description}
|
|
<Text color="primary">{action.subtitle}</Text>
|
|
</Stack>
|
|
</Card.Description>
|
|
</Card>
|
|
))}
|
|
</>
|
|
)}
|
|
/>
|
|
|
|
{/* Only show title field if folder sync */}
|
|
{selectedTarget === 'folder' && (
|
|
<Field
|
|
label={t('provisioning.bootstrap-step.label-display-name', 'Display name')}
|
|
description={t(
|
|
'provisioning.bootstrap-step.description-clear-repository-connection',
|
|
'Add a clear name for this repository connection'
|
|
)}
|
|
error={errors.repository?.title?.message}
|
|
invalid={!!errors.repository?.title}
|
|
required
|
|
noMargin
|
|
>
|
|
<Input
|
|
id="repository-title"
|
|
{...register('repository.title', {
|
|
required: t('provisioning.bootstrap-step.error-field-required', 'This field is required.'),
|
|
})}
|
|
placeholder={t(
|
|
'provisioning.bootstrap-step.placeholder-my-repository-connection',
|
|
'My repository connection'
|
|
)}
|
|
// Autofocus the title field if it's the only available option
|
|
autoFocus={options.length === 1 && options[0].target === 'folder'}
|
|
/>
|
|
</Field>
|
|
)}
|
|
</Stack>
|
|
</Stack>
|
|
);
|
|
}
|