diff --git a/public/app/features/admin/migrate-to-cloud/MigrateToCloud.tsx b/public/app/features/admin/migrate-to-cloud/MigrateToCloud.tsx
index a30d26fd97e..3545be33a21 100644
--- a/public/app/features/admin/migrate-to-cloud/MigrateToCloud.tsx
+++ b/public/app/features/admin/migrate-to-cloud/MigrateToCloud.tsx
@@ -2,7 +2,7 @@ import React from 'react';
import { Page } from 'app/core/components/Page/Page';
-import { EmptyState } from './EmptyState/EmptyState';
+import { EmptyState } from './onprem/EmptyState/EmptyState';
export default function MigrateToCloud() {
return (
diff --git a/public/app/features/admin/migrate-to-cloud/cloud/EmptyState/EmptyState.tsx b/public/app/features/admin/migrate-to-cloud/cloud/EmptyState/EmptyState.tsx
new file mode 100644
index 00000000000..9ffcc839993
--- /dev/null
+++ b/public/app/features/admin/migrate-to-cloud/cloud/EmptyState/EmptyState.tsx
@@ -0,0 +1,34 @@
+import { css } from '@emotion/css';
+import React from 'react';
+
+import { GrafanaTheme2 } from '@grafana/data';
+import { Grid, useStyles2 } from '@grafana/ui';
+
+import { InfoPane } from './InfoPane';
+import { MigrationTokenPane } from './MigrationTokenPane';
+
+export const EmptyState = () => {
+ const styles = useStyles2(getStyles);
+
+ return (
+
+
+
+
+
+
+ );
+};
+
+const getStyles = (theme: GrafanaTheme2) => ({
+ container: css({
+ maxWidth: theme.breakpoints.values.xl,
+ }),
+});
diff --git a/public/app/features/admin/migrate-to-cloud/cloud/EmptyState/InfoPane.tsx b/public/app/features/admin/migrate-to-cloud/cloud/EmptyState/InfoPane.tsx
new file mode 100644
index 00000000000..27b30134b40
--- /dev/null
+++ b/public/app/features/admin/migrate-to-cloud/cloud/EmptyState/InfoPane.tsx
@@ -0,0 +1,75 @@
+import { css } from '@emotion/css';
+import React from 'react';
+
+import { GrafanaTheme2 } from '@grafana/data';
+import { Box, Stack, TextLink, useStyles2 } from '@grafana/ui';
+import { t, Trans } from 'app/core/internationalization';
+
+import { InfoItem } from '../../shared/InfoItem';
+
+export const InfoPane = () => {
+ const styles = useStyles2(getStyles);
+
+ return (
+
+
+
+ Some configuration from your self-managed Grafana instance can be automatically copied to this cloud stack.
+
+
+
+
+
+ The migration process must be started from your self-managed Grafana instance.
+
+
+
+
+ Log in to your self-managed instance and navigate to Administration, General, Migrate to Grafana Cloud.
+
+
+
+
+ Select "Migrate this instance to Cloud".
+
+
+
+
+ You'll be prompted for a migration token. Generate one from this screen.
+
+
+
+
+ In your self-managed instance, select "Upload everything" to upload data sources and
+ dashboards to this cloud stack.
+
+
+
+
+ If some of your data sources will not work over the public internet, you’ll need to install Private Data
+ Source Connect in your self-managed environment.
+
+
+
+
+
+
+ {t('migrate-to-cloud.get-started.configure-pdc-link', 'Configure PDC for this stack')}
+
+
+ );
+};
+
+const getStyles = (theme: GrafanaTheme2) => ({
+ list: css({
+ padding: 'revert',
+ }),
+});
diff --git a/public/app/features/admin/migrate-to-cloud/cloud/EmptyState/MigrationTokenPane.tsx b/public/app/features/admin/migrate-to-cloud/cloud/EmptyState/MigrationTokenPane.tsx
new file mode 100644
index 00000000000..192a54c9231
--- /dev/null
+++ b/public/app/features/admin/migrate-to-cloud/cloud/EmptyState/MigrationTokenPane.tsx
@@ -0,0 +1,30 @@
+import React from 'react';
+
+import { Box, Button, Text } from '@grafana/ui';
+import { t, Trans } from 'app/core/internationalization';
+
+import { InfoItem } from '../../shared/InfoItem';
+
+export const MigrationTokenPane = () => {
+ const onGenerateToken = () => {
+ console.log('TODO: generate token!');
+ };
+ const tokenStatus = 'TODO';
+
+ return (
+
+
+
+ Your self-managed Grafana instance will require a special authentication token to securely connect to this
+ cloud stack.
+
+
+
+ Current status: {{ tokenStatus }}
+
+
+
+ );
+};
diff --git a/public/app/features/admin/migrate-to-cloud/EmptyState/CallToAction.tsx b/public/app/features/admin/migrate-to-cloud/onprem/EmptyState/CallToAction.tsx
similarity index 100%
rename from public/app/features/admin/migrate-to-cloud/EmptyState/CallToAction.tsx
rename to public/app/features/admin/migrate-to-cloud/onprem/EmptyState/CallToAction.tsx
diff --git a/public/app/features/admin/migrate-to-cloud/EmptyState/EmptyState.tsx b/public/app/features/admin/migrate-to-cloud/onprem/EmptyState/EmptyState.tsx
similarity index 96%
rename from public/app/features/admin/migrate-to-cloud/EmptyState/EmptyState.tsx
rename to public/app/features/admin/migrate-to-cloud/onprem/EmptyState/EmptyState.tsx
index 09c01b40099..02183bbc95d 100644
--- a/public/app/features/admin/migrate-to-cloud/EmptyState/EmptyState.tsx
+++ b/public/app/features/admin/migrate-to-cloud/onprem/EmptyState/EmptyState.tsx
@@ -16,6 +16,7 @@ export const EmptyState = () => {
{
return (
-
+ {
return (
-
+ {
return (
{title}
-
- {children}
-
+ {children}
{linkHref && (
{linkTitle ?? linkHref}
diff --git a/public/locales/en-US/grafana.json b/public/locales/en-US/grafana.json
index 1e66599fe41..bfb19353212 100644
--- a/public/locales/en-US/grafana.json
+++ b/public/locales/en-US/grafana.json
@@ -701,11 +701,33 @@
"button": "Migrate this instance to Cloud",
"header": "Let us manage your Grafana stack"
},
+ "get-started": {
+ "body": "The migration process must be started from your self-managed Grafana instance.",
+ "configure-pdc-link": "Configure PDC for this stack",
+ "link-title": "Learn more about Private Data Source Connect",
+ "step-1": "Log in to your self-managed instance and navigate to Administration, General, Migrate to Grafana Cloud.",
+ "step-2": "Select \"Migrate this instance to Cloud\".",
+ "step-3": "You'll be prompted for a migration token. Generate one from this screen.",
+ "step-4": "In your self-managed instance, select \"Upload everything\" to upload data sources and dashboards to this cloud stack.",
+ "step-5": "If some of your data sources will not work over the public internet, you’ll need to install Private Data Source Connect in your self-managed environment.",
+ "title": "How to get started"
+ },
"is-it-secure": {
"body": "Grafana Labs is committed to maintaining the highest standards of data privacy and security. By implementing industry-standard security technologies and procedures, we help protect our customers' data from unauthorized access, use, or disclosure.",
"link-title": "Grafana Labs Trust Center",
"title": "Is it secure?"
},
+ "migrate-to-this-stack": {
+ "body": "Some configuration from your self-managed Grafana instance can be automatically copied to this cloud stack.",
+ "link-title": "View the full migration guide",
+ "title": "Migrate configuration to this stack"
+ },
+ "migration-token": {
+ "body": "Your self-managed Grafana instance will require a special authentication token to securely connect to this cloud stack.",
+ "generate-button": "Generate a migration token",
+ "status": "Current status: {{tokenStatus}}",
+ "title": "Migration token"
+ },
"pdc": {
"body": "Exposing your data sources to the internet can raise security concerns. Private data source connect (PDC) allows Grafana Cloud to access your existing data sources over a secure network tunnel.",
"link-title": "Learn about PDC",
diff --git a/public/locales/pseudo-LOCALE/grafana.json b/public/locales/pseudo-LOCALE/grafana.json
index 6cd2c16ee40..2608eb4fef9 100644
--- a/public/locales/pseudo-LOCALE/grafana.json
+++ b/public/locales/pseudo-LOCALE/grafana.json
@@ -701,11 +701,33 @@
"button": "Mįģřäŧę ŧĥįş įʼnşŧäʼnčę ŧő Cľőūđ",
"header": "Ŀęŧ ūş mäʼnäģę yőūř Ğřäƒäʼnä şŧäčĸ"
},
+ "get-started": {
+ "body": "Ŧĥę mįģřäŧįőʼn přőčęşş mūşŧ þę şŧäřŧęđ ƒřőm yőūř şęľƒ-mäʼnäģęđ Ğřäƒäʼnä įʼnşŧäʼnčę.",
+ "configure-pdc-link": "Cőʼnƒįģūřę PĐC ƒőř ŧĥįş şŧäčĸ",
+ "link-title": "Ŀęäřʼn mőřę äþőūŧ Přįväŧę Đäŧä Ŝőūřčę Cőʼnʼnęčŧ",
+ "step-1": "Ŀőģ įʼn ŧő yőūř şęľƒ-mäʼnäģęđ įʼnşŧäʼnčę äʼnđ ʼnävįģäŧę ŧő Åđmįʼnįşŧřäŧįőʼn, Ğęʼnęřäľ, Mįģřäŧę ŧő Ğřäƒäʼnä Cľőūđ.",
+ "step-2": "Ŝęľęčŧ \"Mįģřäŧę ŧĥįş įʼnşŧäʼnčę ŧő Cľőūđ\".",
+ "step-3": "Ÿőū'ľľ þę přőmpŧęđ ƒőř ä mįģřäŧįőʼn ŧőĸęʼn. Ğęʼnęřäŧę őʼnę ƒřőm ŧĥįş şčřęęʼn.",
+ "step-4": "Ĩʼn yőūř şęľƒ-mäʼnäģęđ įʼnşŧäʼnčę, şęľęčŧ \"Ůpľőäđ ęvęřyŧĥįʼnģ\" ŧő ūpľőäđ đäŧä şőūřčęş äʼnđ đäşĥþőäřđş ŧő ŧĥįş čľőūđ şŧäčĸ.",
+ "step-5": "Ĩƒ şőmę őƒ yőūř đäŧä şőūřčęş ŵįľľ ʼnőŧ ŵőřĸ ővęř ŧĥę pūþľįč įʼnŧęřʼnęŧ, yőū’ľľ ʼnęęđ ŧő įʼnşŧäľľ Přįväŧę Đäŧä Ŝőūřčę Cőʼnʼnęčŧ įʼn yőūř şęľƒ-mäʼnäģęđ ęʼnvįřőʼnmęʼnŧ.",
+ "title": "Ħőŵ ŧő ģęŧ şŧäřŧęđ"
+ },
"is-it-secure": {
"body": "Ğřäƒäʼnä Ŀäþş įş čőmmįŧŧęđ ŧő mäįʼnŧäįʼnįʼnģ ŧĥę ĥįģĥęşŧ şŧäʼnđäřđş őƒ đäŧä přįväčy äʼnđ şęčūřįŧy. ßy įmpľęmęʼnŧįʼnģ įʼnđūşŧřy-şŧäʼnđäřđ şęčūřįŧy ŧęčĥʼnőľőģįęş äʼnđ přőčęđūřęş, ŵę ĥęľp přőŧęčŧ őūř čūşŧőmęřş' đäŧä ƒřőm ūʼnäūŧĥőřįžęđ äččęşş, ūşę, őř đįşčľőşūřę.",
"link-title": "Ğřäƒäʼnä Ŀäþş Ŧřūşŧ Cęʼnŧęř",
"title": "Ĩş įŧ şęčūřę?"
},
+ "migrate-to-this-stack": {
+ "body": "Ŝőmę čőʼnƒįģūřäŧįőʼn ƒřőm yőūř şęľƒ-mäʼnäģęđ Ğřäƒäʼnä įʼnşŧäʼnčę čäʼn þę äūŧőmäŧįčäľľy čőpįęđ ŧő ŧĥįş čľőūđ şŧäčĸ.",
+ "link-title": "Vįęŵ ŧĥę ƒūľľ mįģřäŧįőʼn ģūįđę",
+ "title": "Mįģřäŧę čőʼnƒįģūřäŧįőʼn ŧő ŧĥįş şŧäčĸ"
+ },
+ "migration-token": {
+ "body": "Ÿőūř şęľƒ-mäʼnäģęđ Ğřäƒäʼnä įʼnşŧäʼnčę ŵįľľ řęqūįřę ä şpęčįäľ äūŧĥęʼnŧįčäŧįőʼn ŧőĸęʼn ŧő şęčūřęľy čőʼnʼnęčŧ ŧő ŧĥįş čľőūđ şŧäčĸ.",
+ "generate-button": "Ğęʼnęřäŧę ä mįģřäŧįőʼn ŧőĸęʼn",
+ "status": "Cūřřęʼnŧ şŧäŧūş: {{tokenStatus}}",
+ "title": "Mįģřäŧįőʼn ŧőĸęʼn"
+ },
"pdc": {
"body": "Ēχpőşįʼnģ yőūř đäŧä şőūřčęş ŧő ŧĥę įʼnŧęřʼnęŧ čäʼn řäįşę şęčūřįŧy čőʼnčęřʼnş. Přįväŧę đäŧä şőūřčę čőʼnʼnęčŧ (PĐC) äľľőŵş Ğřäƒäʼnä Cľőūđ ŧő äččęşş yőūř ęχįşŧįʼnģ đäŧä şőūřčęş ővęř ä şęčūřę ʼnęŧŵőřĸ ŧūʼnʼnęľ.",
"link-title": "Ŀęäřʼn äþőūŧ PĐC",