195 lines
7.2 KiB
TypeScript
195 lines
7.2 KiB
TypeScript
import { css } from '@emotion/css';
|
|
import { useId } from 'react';
|
|
import { SubmitHandler, useForm } from 'react-hook-form';
|
|
|
|
import { GrafanaTheme2 } from '@grafana/data';
|
|
import { Modal, Button, Stack, TextLink, Field, Input, Text, useStyles2 } from '@grafana/ui';
|
|
import { Trans, t } from 'app/core/internationalization';
|
|
import { AlertWithTraceID } from 'app/features/migrate-to-cloud/shared/AlertWithTraceID';
|
|
|
|
import { CreateSessionApiArg } from '../../../api';
|
|
import { maybeAPIError } from '../../../api/errors';
|
|
|
|
interface Props {
|
|
isOpen: boolean;
|
|
isLoading: boolean;
|
|
error: unknown;
|
|
hideModal: () => void;
|
|
onConfirm: (connectStackData: CreateSessionApiArg) => Promise<unknown>;
|
|
}
|
|
|
|
interface FormData {
|
|
token: string;
|
|
}
|
|
|
|
function getTMessage(messageId: string): string {
|
|
switch (messageId) {
|
|
case 'cloudmigrations.createMigration.tokenInvalid':
|
|
return t(
|
|
'migrate-to-cloud.connect-modal.token-errors.token-invalid',
|
|
'Token is not valid. Generate a new token on your cloud instance and try again.'
|
|
);
|
|
case 'cloudmigrations.createMigration.tokenRequestError':
|
|
return t(
|
|
'migrate-to-cloud.connect-modal.token-errors.token-request-error',
|
|
'An error occurred while validating the token. Please check the Grafana instance logs.'
|
|
);
|
|
case 'cloudmigrations.createMigration.tokenValidationFailure':
|
|
return t(
|
|
'migrate-to-cloud.connect-modal.token-errors.token-validation-failure',
|
|
'Token is not valid. Please ensure the token matches the migration token on your cloud instance.'
|
|
);
|
|
case 'cloudmigrations.createMigration.instanceUnreachable':
|
|
return t(
|
|
'migrate-to-cloud.connect-modal.token-errors.instance-unreachable',
|
|
'The cloud instance cannot be reached. Make sure the instance is running and try again.'
|
|
);
|
|
case 'cloudmigrations.createMigration.instanceRequestError':
|
|
return t(
|
|
'migrate-to-cloud.connect-modal.token-errors.instance-request-error',
|
|
"An error occurred while attempting to verify the cloud instance's connectivity. Please check the network settings or cloud instance status."
|
|
);
|
|
case 'cloudmigrations.createMigration.sessionCreationFailure':
|
|
return t(
|
|
'migrate-to-cloud.connect-modal.token-errors.session-creation-failure',
|
|
'There was an error creating the migration. Please try again.'
|
|
);
|
|
case 'cloudmigrations.createMigration.migrationDisabled':
|
|
return t(
|
|
'migrate-to-cloud.connect-modal.token-errors.migration-disabled',
|
|
'Cloud migrations are disabled on this instance.'
|
|
);
|
|
default:
|
|
return t(
|
|
'migrate-to-cloud.connect-modal.token-errors.token-not-saved',
|
|
'There was an error saving the token. See the Grafana server logs for more details.'
|
|
);
|
|
}
|
|
}
|
|
|
|
export const ConnectModal = ({ isOpen, isLoading, error, hideModal, onConfirm }: Props) => {
|
|
const tokenId = useId();
|
|
const styles = useStyles2(getStyles);
|
|
|
|
const {
|
|
handleSubmit,
|
|
register,
|
|
formState: { errors },
|
|
watch,
|
|
} = useForm<FormData>({
|
|
defaultValues: {
|
|
token: '',
|
|
},
|
|
});
|
|
|
|
const token = watch('token');
|
|
|
|
const onConfirmConnect: SubmitHandler<FormData> = (formData) => {
|
|
onConfirm({
|
|
cloudMigrationSessionRequestDto: {
|
|
authToken: formData.token,
|
|
},
|
|
}).then((resp) => {
|
|
const didError = typeof resp === 'object' && resp && 'error' in resp;
|
|
if (!didError) {
|
|
hideModal();
|
|
}
|
|
});
|
|
};
|
|
|
|
return (
|
|
<Modal
|
|
isOpen={isOpen}
|
|
title={t('migrate-to-cloud.connect-modal.title', 'Connect to a cloud stack')}
|
|
onDismiss={hideModal}
|
|
>
|
|
<form onSubmit={handleSubmit(onConfirmConnect)}>
|
|
<Text color="secondary">
|
|
<Stack direction="column" gap={2}>
|
|
<Trans i18nKey="migrate-to-cloud.connect-modal.body-get-started">
|
|
To get started, you'll need a Grafana.com account.
|
|
</Trans>
|
|
|
|
<div>
|
|
<TextLink href="https://grafana.com/auth/sign-up/create-user?pg=prod-cloud" external>
|
|
{t('migrate-to-cloud.connect-modal.body-sign-up', 'Sign up for a Grafana.com account')}
|
|
</TextLink>
|
|
</div>
|
|
|
|
<Trans i18nKey="migrate-to-cloud.connect-modal.body-cloud-stack">
|
|
You'll also need a cloud stack. If you just signed up, we'll automatically create your first
|
|
stack. If you have an account, you'll need to select or create a stack.
|
|
</Trans>
|
|
|
|
<div>
|
|
<TextLink href="https://grafana.com/auth/sign-in/" external>
|
|
{t('migrate-to-cloud.connect-modal.body-view-stacks', 'View my cloud stacks')}
|
|
</TextLink>
|
|
</div>
|
|
|
|
<div>
|
|
<Trans i18nKey="migrate-to-cloud.connect-modal.body-token">
|
|
Your self-managed Grafana installation needs special access to securely migrate content. You'll
|
|
need to create a migration token on your chosen cloud stack.
|
|
</Trans>
|
|
</div>
|
|
|
|
<div>
|
|
<Trans i18nKey="migrate-to-cloud.connect-modal.body-token-instructions">
|
|
Log into your cloud stack and navigate to Administration, General, Migrate to Grafana Cloud. Create a
|
|
migration token on that screen and paste the token here.
|
|
</Trans>
|
|
</div>
|
|
|
|
{error ? (
|
|
<AlertWithTraceID
|
|
error={error}
|
|
severity="error"
|
|
title={t('migrate-to-cloud.connect-modal.token-error-title', 'Error saving token')}
|
|
>
|
|
<Text element="p">
|
|
{getTMessage(maybeAPIError(error)?.messageId || '') ||
|
|
'There was an error saving the token. See the Grafana server logs for more details.'}
|
|
</Text>
|
|
</AlertWithTraceID>
|
|
) : undefined}
|
|
|
|
<Field
|
|
className={styles.field}
|
|
invalid={!!errors.token}
|
|
error={errors.token?.message}
|
|
label={t('migrate-to-cloud.connect-modal.body-token-field', 'Migration token')}
|
|
required
|
|
>
|
|
<Input
|
|
{...register('token', {
|
|
required: t('migrate-to-cloud.connect-modal.token-required-error', 'Migration token is required'),
|
|
})}
|
|
id={tokenId}
|
|
placeholder={t('migrate-to-cloud.connect-modal.body-token-field-placeholder', 'Paste token here')}
|
|
/>
|
|
</Field>
|
|
</Stack>
|
|
</Text>
|
|
|
|
<Modal.ButtonRow>
|
|
<Button variant="secondary" onClick={hideModal}>
|
|
<Trans i18nKey="migrate-to-cloud.connect-modal.cancel">Cancel</Trans>
|
|
</Button>
|
|
<Button type="submit" disabled={isLoading || !token}>
|
|
{isLoading
|
|
? t('migrate-to-cloud.connect-modal.connecting', 'Connecting to this stack...')
|
|
: t('migrate-to-cloud.connect-modal.connect', 'Connect to this stack')}
|
|
</Button>
|
|
</Modal.ButtonRow>
|
|
</form>
|
|
</Modal>
|
|
);
|
|
};
|
|
|
|
const getStyles = (theme: GrafanaTheme2) => ({
|
|
field: css({
|
|
alignSelf: 'stretch',
|
|
}),
|
|
});
|