[v11.0.x] Alerting: Fix instances link when served from subpath (#86906)

Alerting: Fix instances link when served from subpath (#86432)

Fix instances link when served from subpath

(cherry picked from commit 9614126cb7)

Co-authored-by: Konrad Lalik <konrad.lalik@grafana.com>
This commit is contained in:
grafana-delivery-bot[bot]
2024-04-25 11:38:12 +02:00
committed by GitHub
co-authored by Konrad Lalik
parent 48e920896d
commit f5b16c223b
3 changed files with 20 additions and 14 deletions
@@ -54,7 +54,7 @@ export interface DynamicTableProps<T = unknown> {
items: Array<DynamicTableItemProps<T>> items: Array<DynamicTableItemProps<T>>
) => ReactNode; ) => ReactNode;
footerRow?: JSX.Element; footerRow?: React.ReactNode;
} }
export const DynamicTable = <T extends object>({ export const DynamicTable = <T extends object>({
@@ -15,7 +15,7 @@ interface Props {
rule?: CombinedRule; rule?: CombinedRule;
instances: Alert[]; instances: Alert[];
pagination?: PaginationProps; pagination?: PaginationProps;
footerRow?: JSX.Element; footerRow?: React.ReactNode;
} }
interface AlertWithCommonLabels extends Alert { interface AlertWithCommonLabels extends Alert {
@@ -1,10 +1,9 @@
import { css, cx } from '@emotion/css'; import { css, cx } from '@emotion/css';
import { countBy, sum } from 'lodash'; import { countBy, sum } from 'lodash';
import React, { useMemo, useState } from 'react'; import React, { useMemo, useState } from 'react';
import { useHistory } from 'react-router-dom';
import { GrafanaTheme2 } from '@grafana/data'; import { GrafanaTheme2 } from '@grafana/data';
import { Button, useStyles2 } from '@grafana/ui'; import { LinkButton, useStyles2 } from '@grafana/ui';
import { MatcherFilter } from 'app/features/alerting/unified/components/alert-groups/MatcherFilter'; import { MatcherFilter } from 'app/features/alerting/unified/components/alert-groups/MatcherFilter';
import { import {
AlertInstanceStateFilter, AlertInstanceStateFilter,
@@ -34,24 +33,28 @@ interface ShowMoreStats {
visibleItemsCount: number; visibleItemsCount: number;
} }
function ShowMoreInstances(props: { onClick: () => void; stats: ShowMoreStats }) { interface ShowMoreInstancesProps {
stats: ShowMoreStats;
onClick?: React.ComponentProps<typeof LinkButton>['onClick'];
href?: React.ComponentProps<typeof LinkButton>['href'];
}
function ShowMoreInstances({ stats, onClick, href }: ShowMoreInstancesProps) {
const styles = useStyles2(getStyles); const styles = useStyles2(getStyles);
const { onClick, stats } = props;
return ( return (
<div className={styles.footerRow}> <div className={styles.footerRow}>
<div> <div>
Showing {stats.visibleItemsCount} out of {stats.totalItemsCount} instances Showing {stats.visibleItemsCount} out of {stats.totalItemsCount} instances
</div> </div>
<Button size="sm" variant="secondary" data-testid="show-all" onClick={onClick}> <LinkButton size="sm" variant="secondary" data-testid="show-all" onClick={onClick} href={href}>
Show all {stats.totalItemsCount} alert instances Show all {stats.totalItemsCount} alert instances
</Button> </LinkButton>
</div> </div>
); );
} }
export function RuleDetailsMatchingInstances(props: Props): JSX.Element | null { export function RuleDetailsMatchingInstances(props: Props) {
const history = useHistory();
const { rule, itemsDisplayLimit = Number.POSITIVE_INFINITY, pagination, enableFiltering = false } = props; const { rule, itemsDisplayLimit = Number.POSITIVE_INFINITY, pagination, enableFiltering = false } = props;
const { promRule, namespace, instanceTotals } = rule; const { promRule, namespace, instanceTotals } = rule;
@@ -97,16 +100,19 @@ export function RuleDetailsMatchingInstances(props: Props): JSX.Element | null {
visibleItemsCount: visibleInstances.length, visibleItemsCount: visibleInstances.length,
}; };
// createViewLink returns a link containing the app subpath prefix hence cannot be used
// in locationService.push as it will result in a double prefix
const ruleViewPageLink = createViewLink(namespace.rulesSource, props.rule, location.pathname + location.search); const ruleViewPageLink = createViewLink(namespace.rulesSource, props.rule, location.pathname + location.search);
const statsComponents = getComponentsFromStats(instanceTotals); const statsComponents = getComponentsFromStats(instanceTotals);
const resetFilter = () => setAlertState(undefined); const resetFilter = () => setAlertState(undefined);
const navigateToDetailView = () => history.push(ruleViewPageLink);
const onShowMoreInstances = enableFiltering ? resetFilter : navigateToDetailView;
const footerRow = hiddenInstancesCount ? ( const footerRow = hiddenInstancesCount ? (
<ShowMoreInstances stats={stats} onClick={onShowMoreInstances} /> <ShowMoreInstances
stats={stats}
onClick={enableFiltering ? resetFilter : undefined}
href={!enableFiltering ? ruleViewPageLink : undefined}
/>
) : undefined; ) : undefined;
return ( return (