E2C: Add initial empty state (#83232)

* update subtitle

* add empty state

* rename to InfoPaneLeft/Right

* use '

* add "direction" prop to Box

* update subtitle

* Revert "add "direction" prop to Box"

This reverts commit 99f82a27c732541fe9ca0f1dc87e6db0f6eb72fc.
This commit is contained in:
Ashley Harrison
2024-02-23 11:18:09 +00:00
committed by GitHub
parent c63456612e
commit a3c73ae7c4
10 changed files with 256 additions and 12 deletions

View File

@ -139,7 +139,7 @@ func (s *ServiceImpl) getAdminNode(c *contextmodel.ReqContext) (*navtree.NavLink
migrateToCloud := &navtree.NavLink{
Text: "Migrate to Grafana Cloud",
Id: "migrate-to-cloud",
SubTitle: "Copy data sources, dashboards, and alerts from this installation to a cloud stack",
SubTitle: "Copy configuration from your self-managed installation to a cloud stack",
Url: s.cfg.AppSubURL + "/admin/migrate-to-cloud",
}
configNodes = append(configNodes, migrateToCloud)

View File

@ -253,7 +253,7 @@ export function getNavSubTitle(navId: string | undefined) {
case 'migrate-to-cloud':
return t(
'nav.migrate-to-cloud.subtitle',
'Copy data sources, dashboards, and alerts from this installation to a cloud stack'
'Copy configuration from your self-managed installation to a cloud stack'
);
case 'support-bundles':
return t('nav.support-bundles.subtitle', 'Download support bundles');

View File

@ -0,0 +1,23 @@
import React from 'react';
import { Box, Button, Stack, Text } from '@grafana/ui';
import { Trans } from 'app/core/internationalization';
export const CallToAction = () => {
const onClickMigrate = () => {
console.log('TODO migration!');
};
return (
<Box padding={5} backgroundColor="secondary">
<Stack gap={2} direction="column" alignItems="center">
<Text variant="h3" textAlignment="center">
<Trans i18nKey="migrate-to-cloud.cta.header">Let us manage your Grafana stack</Trans>
</Text>
<Button onClick={onClickMigrate}>
<Trans i18nKey="migrate-to-cloud.cta.button">Migrate this instance to Cloud</Trans>
</Button>
</Stack>
</Box>
);
};

View File

@ -0,0 +1,37 @@
import { css } from '@emotion/css';
import React from 'react';
import { GrafanaTheme2 } from '@grafana/data';
import { Grid, Stack, useStyles2 } from '@grafana/ui';
import { CallToAction } from './CallToAction';
import { InfoPaneLeft } from './InfoPaneLeft';
import { InfoPaneRight } from './InfoPaneRight';
export const EmptyState = () => {
const styles = useStyles2(getStyles);
return (
<div className={styles.container}>
<Stack direction="column">
<CallToAction />
<Grid
gap={1}
columns={{
xs: 1,
lg: 2,
}}
>
<InfoPaneLeft />
<InfoPaneRight />
</Grid>
</Stack>
</div>
);
};
const getStyles = (theme: GrafanaTheme2) => ({
container: css({
maxWidth: theme.breakpoints.values.xl,
}),
});

View File

@ -0,0 +1,26 @@
import React, { ReactNode } from 'react';
import { Stack, Text, TextLink } from '@grafana/ui';
interface Props {
children: NonNullable<ReactNode>;
title: string;
linkTitle?: string;
linkHref?: string;
}
export const InfoItem = ({ children, title, linkHref, linkTitle }: Props) => {
return (
<Stack gap={2} direction="column">
<Text element="h4">{title}</Text>
<Text element="p" color="secondary">
{children}
</Text>
{linkHref && (
<TextLink href={linkHref} external>
{linkTitle ?? linkHref}
</TextLink>
)}
</Stack>
);
};

View File

@ -0,0 +1,47 @@
import React from 'react';
import { Box, Stack } from '@grafana/ui';
import { t, Trans } from 'app/core/internationalization';
import { InfoItem } from './InfoItem';
export const InfoPaneLeft = () => {
return (
<Box padding={2} backgroundColor="secondary">
<Stack gap={2} direction="column">
<InfoItem
title={t('migrate-to-cloud.what-is-cloud.title', 'What is Grafana Cloud?')}
linkTitle={t('migrate-to-cloud.what-is-cloud.link-title', 'Learn about cloud features')}
linkHref="https://grafana.com/products/cloud"
>
<Trans i18nKey="migrate-to-cloud.what-is-cloud.body">
Grafana cloud is a fully managed cloud-hosted observability platform ideal for cloud native environments.
It&apos;s everything you love about Grafana without the overhead of maintaining, upgrading, and supporting
an installation.
</Trans>
</InfoItem>
<InfoItem
title={t('migrate-to-cloud.why-host.title', 'Why host with Grafana?')}
linkTitle={t('migrate-to-cloud.why-host.link-title', 'More questions? Talk to an expert')}
linkHref="https://grafana.com/contact"
>
<Trans i18nKey="migrate-to-cloud.why-host.body">
In addition to the convenience of managed hosting, Grafana Cloud includes many cloud-exclusive features like
SLOs, incident management, machine learning, and powerful observability integrations.
</Trans>
</InfoItem>
<InfoItem
title={t('migrate-to-cloud.is-it-secure.title', 'Is it secure?')}
linkTitle={t('migrate-to-cloud.is-it-secure.link-title', 'Grafana Labs Trust Center')}
linkHref="https://trust.grafana.com"
>
<Trans i18nKey="migrate-to-cloud.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&apos; data from
unauthorized access, use, or disclosure.
</Trans>
</InfoItem>
</Stack>
</Box>
);
};

View File

@ -0,0 +1,45 @@
import React from 'react';
import { Box, Stack } from '@grafana/ui';
import { t, Trans } from 'app/core/internationalization';
import { InfoItem } from './InfoItem';
export const InfoPaneRight = () => {
return (
<Box padding={2} backgroundColor="secondary">
<Stack gap={2} direction="column">
<InfoItem
title={t('migrate-to-cloud.pdc.title', 'Not all my data sources are on the public internet')}
linkTitle={t('migrate-to-cloud.pdc.link-title', 'Learn about PDC')}
linkHref="https://grafana.com/docs/grafana-cloud/connect-externally-hosted/private-data-source-connect"
>
<Trans i18nKey="migrate-to-cloud.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.
</Trans>
</InfoItem>
<InfoItem
title={t('migrate-to-cloud.pricing.title', 'How much does it cost?')}
linkTitle={t('migrate-to-cloud.pricing.link-title', 'Grafana Cloud pricing')}
linkHref="https://grafana.com/pricing"
>
<Trans i18nKey="migrate-to-cloud.pricing.body">
Grafana Cloud has a generous free plan and a 14 day unlimited usage trial. After your trial expires,
you&apos;ll be billed based on usage over the free plan limits.
</Trans>
</InfoItem>
<InfoItem
title={t('migrate-to-cloud.can-i-move.title', 'Can I move this installation to Grafana Cloud?')}
linkTitle={t('migrate-to-cloud.can-i-move.link-title', 'Learn about migrating other settings')}
linkHref="https://grafana.com/docs/grafana-cloud/account-management/migration-guide"
>
<Trans i18nKey="migrate-to-cloud.can-i-move.body">
Once you connect this installation to a cloud stack, you&apos;ll be able to upload data sources and
dashboards.
</Trans>
</InfoItem>
</Stack>
</Box>
);
};

View File

@ -1,19 +1,13 @@
import React from 'react';
import { Stack, Text } from '@grafana/ui';
import { Page } from 'app/core/components/Page/Page';
import { useGetStatusQuery } from './api';
import { EmptyState } from './EmptyState/EmptyState';
export default function MigrateToCloud() {
const { data } = useGetStatusQuery();
return (
<Page navId="migrate-to-cloud">
<Stack>
<Text>TODO</Text>
<pre>{JSON.stringify(data)}</pre>
</Stack>
<EmptyState />
</Page>
);
}

View File

@ -691,6 +691,42 @@
"new-to-question": "New to Grafana?"
}
},
"migrate-to-cloud": {
"can-i-move": {
"body": "Once you connect this installation to a cloud stack, you'll be able to upload data sources and dashboards.",
"link-title": "Learn about migrating other settings",
"title": "Can I move this installation to Grafana Cloud?"
},
"cta": {
"button": "Migrate this instance to Cloud",
"header": "Let us manage your Grafana stack"
},
"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?"
},
"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",
"title": "Not all my data sources are on the public internet"
},
"pricing": {
"body": "Grafana Cloud has a generous free plan and a 14 day unlimited usage trial. After your trial expires, you'll be billed based on usage over the free plan limits.",
"link-title": "Grafana Cloud pricing",
"title": "How much does it cost?"
},
"what-is-cloud": {
"body": "Grafana cloud is a fully managed cloud-hosted observability platform ideal for cloud native environments. It's everything you love about Grafana without the overhead of maintaining, upgrading, and supporting an installation.",
"link-title": "Learn about cloud features",
"title": "What is Grafana Cloud?"
},
"why-host": {
"body": "In addition to the convenience of managed hosting, Grafana Cloud includes many cloud-exclusive features like SLOs, incident management, machine learning, and powerful observability integrations.",
"link-title": "More questions? Talk to an expert",
"title": "Why host with Grafana?"
}
},
"nav": {
"add-new-connections": {
"title": "Add new connection"
@ -877,7 +913,7 @@
"subtitle": "Manage folder dashboards and permissions"
},
"migrate-to-cloud": {
"subtitle": "Copy data sources, dashboards, and alerts from this installation to a cloud stack",
"subtitle": "Copy configuration from your self-managed installation to a cloud stack",
"title": "Migrate to Grafana Cloud"
},
"monitoring": {

View File

@ -691,6 +691,42 @@
"new-to-question": "Ńęŵ ŧő Ğřäƒäʼnä?"
}
},
"migrate-to-cloud": {
"can-i-move": {
"body": "Øʼnčę yőū čőʼnʼnęčŧ ŧĥįş įʼnşŧäľľäŧįőʼn ŧő ä čľőūđ şŧäčĸ, yőū'ľľ þę äþľę ŧő ūpľőäđ đäŧä şőūřčęş äʼnđ đäşĥþőäřđş.",
"link-title": "Ŀęäřʼn äþőūŧ mįģřäŧįʼnģ őŧĥęř şęŧŧįʼnģş",
"title": "Cäʼn Ĩ mővę ŧĥįş įʼnşŧäľľäŧįőʼn ŧő Ğřäƒäʼnä Cľőūđ?"
},
"cta": {
"button": "Mįģřäŧę ŧĥįş įʼnşŧäʼnčę ŧő Cľőūđ",
"header": "Ŀęŧ ūş mäʼnäģę yőūř Ğřäƒäʼnä şŧäčĸ"
},
"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": "Ĩş įŧ şęčūřę?"
},
"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",
"title": "Ńőŧ äľľ my đäŧä şőūřčęş äřę őʼn ŧĥę pūþľįč įʼnŧęřʼnęŧ"
},
"pricing": {
"body": "Ğřäƒäʼnä Cľőūđ ĥäş ä ģęʼnęřőūş ƒřęę pľäʼn äʼnđ ä 14 đäy ūʼnľįmįŧęđ ūşäģę ŧřįäľ. Ńŧęř yőūř ŧřįäľ ęχpįřęş, yőū'ľľ þę þįľľęđ þäşęđ őʼn ūşäģę ővęř ŧĥę ƒřęę pľäʼn ľįmįŧş.",
"link-title": "Ğřäƒäʼnä Cľőūđ přįčįʼnģ",
"title": "Ħőŵ mūčĥ đőęş įŧ čőşŧ?"
},
"what-is-cloud": {
"body": "Ğřäƒäʼnä čľőūđ įş ä ƒūľľy mäʼnäģęđ čľőūđ-ĥőşŧęđ őþşęřväþįľįŧy pľäŧƒőřm įđęäľ ƒőř čľőūđ ʼnäŧįvę ęʼnvįřőʼnmęʼnŧş. Ĩŧ'ş ęvęřyŧĥįʼnģ yőū ľővę äþőūŧ Ğřäƒäʼnä ŵįŧĥőūŧ ŧĥę ővęřĥęäđ őƒ mäįʼnŧäįʼnįʼnģ, ūpģřäđįʼnģ, äʼnđ şūppőřŧįʼnģ äʼn įʼnşŧäľľäŧįőʼn.",
"link-title": "Ŀęäřʼn äþőūŧ čľőūđ ƒęäŧūřęş",
"title": "Ŵĥäŧ įş Ğřäƒäʼnä Cľőūđ?"
},
"why-host": {
"body": "Ĩʼn äđđįŧįőʼn ŧő ŧĥę čőʼnvęʼnįęʼnčę őƒ mäʼnäģęđ ĥőşŧįʼnģ, Ğřäƒäʼnä Cľőūđ įʼnčľūđęş mäʼny čľőūđ-ęχčľūşįvę ƒęäŧūřęş ľįĸę ŜĿØş, įʼnčįđęʼnŧ mäʼnäģęmęʼnŧ, mäčĥįʼnę ľęäřʼnįʼnģ, äʼnđ pőŵęřƒūľ őþşęřväþįľįŧy įʼnŧęģřäŧįőʼnş.",
"link-title": "Mőřę qūęşŧįőʼnş? Ŧäľĸ ŧő äʼn ęχpęřŧ",
"title": "Ŵĥy ĥőşŧ ŵįŧĥ Ğřäƒäʼnä?"
}
},
"nav": {
"add-new-connections": {
"title": "Åđđ ʼnęŵ čőʼnʼnęčŧįőʼn"
@ -877,7 +913,7 @@
"subtitle": "Mäʼnäģę ƒőľđęř đäşĥþőäřđş äʼnđ pęřmįşşįőʼnş"
},
"migrate-to-cloud": {
"subtitle": "Cőpy đäŧä şőūřčęş, đäşĥþőäřđş, äʼnđ äľęřŧş ƒřőm ŧĥįş įʼnşŧäľľäŧįőʼn ŧő ä čľőūđ şŧäčĸ",
"subtitle": "Cőpy čőʼnƒįģūřäŧįőʼn ƒřőm yőūř şęľƒ-mäʼnäģęđ įʼnşŧäľľäŧįőʼn ŧő ä čľőūđ şŧäčĸ",
"title": "Mįģřäŧę ŧő Ğřäƒäʼnä Cľőūđ"
},
"monitoring": {