mirror of
https://github.com/grafana/grafana.git
synced 2025-08-01 06:11:51 +08:00

* i18n: removes useTranslate hook * chore: fix duplicate imports * chore: fix import sorting and hook dependencies
207 lines
5.9 KiB
TypeScript
207 lines
5.9 KiB
TypeScript
import { css } from '@emotion/css';
|
|
|
|
import { GrafanaTheme2 } from '@grafana/data';
|
|
import { Trans, t } from '@grafana/i18n';
|
|
import { Button, Drawer, Dropdown, Icon, LinkButton, Menu, Stack, Text, Tooltip, useStyles2 } from '@grafana/ui';
|
|
import { RelativeUrl, createRelativeUrl } from 'app/features/alerting/unified/utils/url';
|
|
|
|
import { SectionDto, SectionDtoStep, SectionsDto, StepButtonDto } from '../irmHooks';
|
|
|
|
import { ProgressBar, StepsStatus } from './ProgressBar';
|
|
|
|
export interface EssentialsProps {
|
|
onClose: () => void;
|
|
essentialsConfig: SectionsDto;
|
|
stepsDone: number;
|
|
totalStepsToDo: number;
|
|
}
|
|
|
|
export function Essentials({ onClose, essentialsConfig, stepsDone, totalStepsToDo }: EssentialsProps) {
|
|
return (
|
|
<Drawer
|
|
title={t('gops.essentials.title-essentials', 'Essentials')}
|
|
subtitle="Complete the following configuration tasks"
|
|
onClose={onClose}
|
|
>
|
|
<EssentialContent essentialContent={essentialsConfig} stepsDone={stepsDone} totalStepsToDo={totalStepsToDo} />
|
|
</Drawer>
|
|
);
|
|
}
|
|
|
|
export function EssentialContent({
|
|
essentialContent,
|
|
stepsDone,
|
|
totalStepsToDo,
|
|
}: {
|
|
essentialContent: SectionsDto;
|
|
stepsDone: number;
|
|
totalStepsToDo: number;
|
|
}) {
|
|
return (
|
|
<Stack direction={'column'} gap={1}>
|
|
<ProgressStatus stepsDone={stepsDone} totalStepsToDo={totalStepsToDo} />
|
|
{essentialContent.sections.map((section: SectionDto) => (
|
|
<Section key={section.title} section={section} />
|
|
))}
|
|
</Stack>
|
|
);
|
|
}
|
|
interface SectionProps {
|
|
section: SectionDto;
|
|
}
|
|
function Section({ section }: SectionProps) {
|
|
const styles = useStyles2(getStyles);
|
|
return (
|
|
<div className={styles.wrapper}>
|
|
<Text element="h4">
|
|
<span className="fs-unmask">{section.title}</span>
|
|
</Text>
|
|
|
|
<Text color="secondary">
|
|
<span className="fs-unmask">{section.description}</span>
|
|
</Text>
|
|
<Stack direction={'column'} gap={2}>
|
|
{section.steps.map((step, index) => (
|
|
<Step key={index} step={step} />
|
|
))}
|
|
</Stack>
|
|
</div>
|
|
);
|
|
}
|
|
function DoneIcon({ done }: { done: boolean }) {
|
|
return done ? (
|
|
<Icon name="check-circle" color="green" data-testid="checked-step" className="fs-unmask" />
|
|
) : (
|
|
<Icon name="circle" data-testid="unckecked-step" className="fs-unmask" />
|
|
);
|
|
}
|
|
interface StepProps {
|
|
step: SectionDtoStep;
|
|
}
|
|
|
|
function Step({ step }: StepProps) {
|
|
return (
|
|
<Stack direction={'row'} justifyContent={'space-between'} data-testid="step">
|
|
<Stack direction={'row'} alignItems="center">
|
|
{step.done !== undefined && <DoneIcon done={step.done} />}
|
|
<Text variant="body">
|
|
<span className="fs-unmask">{step.title}</span>
|
|
</Text>
|
|
<Tooltip content={step.description} placement="right">
|
|
<Icon name="question-circle" />
|
|
</Tooltip>
|
|
</Stack>
|
|
<StepButton {...step.button} done={step.done} data-testid="step-button" />
|
|
</Stack>
|
|
);
|
|
}
|
|
|
|
interface LinkButtonProps {
|
|
urlLink?: { url: RelativeUrl; queryParams?: Record<string, string> };
|
|
label: string;
|
|
urlLinkOnDone?: { url: RelativeUrl; queryParams?: Record<string, string> };
|
|
labelOnDone?: string;
|
|
done?: boolean;
|
|
}
|
|
function OpenLinkButton(props: LinkButtonProps) {
|
|
const { urlLink, label, urlLinkOnDone, labelOnDone, done } = props;
|
|
const urlToGoWhenNotDone = urlLink?.url
|
|
? createRelativeUrl(urlLink.url, {
|
|
returnTo: window.location.pathname + window.location.search,
|
|
...urlLink.queryParams,
|
|
})
|
|
: '';
|
|
const urlToGoWhenDone = urlLinkOnDone?.url
|
|
? createRelativeUrl(urlLinkOnDone.url, {
|
|
returnTo: window.location.pathname + window.location.search,
|
|
...urlLinkOnDone.queryParams,
|
|
})
|
|
: '';
|
|
const urlToGo = done ? urlToGoWhenDone : urlToGoWhenNotDone;
|
|
return (
|
|
<LinkButton href={urlToGo} variant="secondary" className="fs-unmask">
|
|
{done ? (labelOnDone ?? label) : label}
|
|
</LinkButton>
|
|
);
|
|
}
|
|
|
|
interface StepButtonProps extends StepButtonDto {
|
|
done?: boolean;
|
|
}
|
|
function StepButton({
|
|
type,
|
|
urlLink,
|
|
urlLinkOnDone,
|
|
label,
|
|
labelOnDone,
|
|
options,
|
|
onClickOption,
|
|
done,
|
|
stepNotAvailableText,
|
|
}: StepButtonProps) {
|
|
switch (type) {
|
|
case 'openLink':
|
|
return (
|
|
<OpenLinkButton
|
|
urlLink={urlLink}
|
|
label={label}
|
|
urlLinkOnDone={urlLinkOnDone}
|
|
labelOnDone={labelOnDone}
|
|
done={done}
|
|
/>
|
|
);
|
|
case 'dropDown':
|
|
if (Boolean(options?.length)) {
|
|
return (
|
|
<Dropdown
|
|
overlay={
|
|
<Menu className="fs-unmask">
|
|
{options?.map((option) => (
|
|
<Menu.Item
|
|
label={option.label}
|
|
key={option.value}
|
|
className="fs-unmask"
|
|
onClick={() => {
|
|
onClickOption?.(option.value);
|
|
}}
|
|
/>
|
|
))}
|
|
</Menu>
|
|
}
|
|
>
|
|
<Button variant="secondary" size="md" className="fs-unmask">
|
|
{label}
|
|
<Icon name="angle-down" />
|
|
</Button>
|
|
</Dropdown>
|
|
);
|
|
} else {
|
|
return <Text>{stepNotAvailableText ?? 'No options available'} </Text>;
|
|
}
|
|
}
|
|
}
|
|
|
|
function ProgressStatus({ stepsDone, totalStepsToDo }: { stepsDone: number; totalStepsToDo: number }) {
|
|
return (
|
|
<Stack direction={'row'} gap={1} alignItems="center">
|
|
<Trans i18nKey="gops.progress-status.your-progress">Your progress</Trans>
|
|
<ProgressBar stepsDone={stepsDone} totalStepsToDo={totalStepsToDo} />
|
|
<StepsStatus stepsDone={stepsDone} totalStepsToDo={totalStepsToDo} />
|
|
</Stack>
|
|
);
|
|
}
|
|
|
|
const getStyles = (theme: GrafanaTheme2) => {
|
|
return {
|
|
wrapper: css({
|
|
margin: theme.spacing(2, 0),
|
|
padding: theme.spacing(2),
|
|
border: `1px solid ${theme.colors.border.medium}`,
|
|
borderRadius: theme.shape.radius.default,
|
|
display: 'flex',
|
|
flexDirection: 'column',
|
|
gap: theme.spacing(2),
|
|
}),
|
|
};
|
|
};
|