Alerting: Refactor createUrl and createAbsoluteUrl (#90667)
* Refactor url creatUrl and add tests * update createUrl to createRelativeUrl in GrafanaRules.tsx * Add slash if not present in createAbsoluteUrl * Use template type forcing url parameter to start with slash instead of adding slash if not present * address review comment
This commit is contained in:
@@ -12,7 +12,7 @@ import { generateCopiedName } from './utils/duplicate';
|
||||
import { stringifyErrorLike } from './utils/misc';
|
||||
import { rulerRuleToFormValues } from './utils/rule-form';
|
||||
import { getRuleName, isAlertingRulerRule, isGrafanaRulerRule, isRecordingRulerRule } from './utils/rules';
|
||||
import { createUrl } from './utils/url';
|
||||
import { createRelativeUrl } from './utils/url';
|
||||
|
||||
export function CloneRuleEditor({ sourceRuleId }: { sourceRuleId: RuleIdentifier }) {
|
||||
const { loading, result: rule, error } = useRuleWithLocation({ ruleIdentifier: sourceRuleId });
|
||||
@@ -40,7 +40,7 @@ export function CloneRuleEditor({ sourceRuleId }: { sourceRuleId: RuleIdentifier
|
||||
<Alert
|
||||
title="Cannot copy the rule. The rule does not exist"
|
||||
buttonContent="Go back to alert list"
|
||||
onRemove={() => locationService.replace(createUrl('/alerting/list'))}
|
||||
onRemove={() => locationService.replace(createRelativeUrl('/alerting/list'))}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
+2
-2
@@ -8,7 +8,7 @@ import ConditionalWrap from 'app/features/alerting/unified/components/Conditiona
|
||||
import { useExportContactPoint } from 'app/features/alerting/unified/components/contact-points/useExportContactPoint';
|
||||
|
||||
import { AlertmanagerAction, useAlertmanagerAbility } from '../../hooks/useAbilities';
|
||||
import { createUrl } from '../../utils/url';
|
||||
import { createRelativeUrl } from '../../utils/url';
|
||||
import MoreButton from '../MoreButton';
|
||||
import { ProvisioningBadge } from '../Provisioning';
|
||||
import { Spacer } from '../Spacer';
|
||||
@@ -96,7 +96,7 @@ export const ContactPointHeader = (props: ContactPointHeaderProps) => {
|
||||
</Stack>
|
||||
{isReferencedByAnyPolicy && (
|
||||
<TextLink
|
||||
href={createUrl('/alerting/routes', { contactPoint: name })}
|
||||
href={createRelativeUrl('/alerting/routes', { contactPoint: name })}
|
||||
variant="bodySmall"
|
||||
color="primary"
|
||||
inline={false}
|
||||
|
||||
@@ -11,7 +11,7 @@ import { stringifyErrorLike } from '../../utils/misc';
|
||||
import { formValuesFromExistingRule } from '../../utils/rule-form';
|
||||
import * as ruleId from '../../utils/rule-id';
|
||||
import { isGrafanaRulerRule } from '../../utils/rules';
|
||||
import { createUrl } from '../../utils/url';
|
||||
import { createRelativeUrl } from '../../utils/url';
|
||||
import { AlertingPageWrapper } from '../AlertingPageWrapper';
|
||||
import { ModifyExportRuleForm } from '../rule-editor/alert-rule-form/ModifyExportRuleForm';
|
||||
|
||||
@@ -79,7 +79,7 @@ function RuleModifyExport({ ruleIdentifier }: { ruleIdentifier: RuleIdentifier }
|
||||
<Alert
|
||||
title="Cannot load the rule. The rule does not exist"
|
||||
buttonContent="Go back to alert list"
|
||||
onRemove={() => locationService.replace(createUrl('/alerting/list'))}
|
||||
onRemove={() => locationService.replace(createRelativeUrl('/alerting/list'))}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -90,7 +90,7 @@ function RuleModifyExport({ ruleIdentifier }: { ruleIdentifier: RuleIdentifier }
|
||||
<Alert
|
||||
title="This rule is not a Grafana-managed alert rule"
|
||||
buttonContent="Go back to alert list"
|
||||
onRemove={() => locationService.replace(createUrl('/alerting/list'))}
|
||||
onRemove={() => locationService.replace(createRelativeUrl('/alerting/list'))}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
+4
-4
@@ -1,7 +1,7 @@
|
||||
import { css, cx, keyframes } from '@emotion/css';
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
import * as React from 'react';
|
||||
import { useFormContext, Controller } from 'react-hook-form';
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
import { Controller, useFormContext } from 'react-hook-form';
|
||||
|
||||
import { GrafanaTheme2, SelectableValue } from '@grafana/data';
|
||||
import {
|
||||
@@ -15,7 +15,7 @@ import {
|
||||
useStyles2,
|
||||
} from '@grafana/ui';
|
||||
import { RuleFormValues } from 'app/features/alerting/unified/types/rule-form';
|
||||
import { createUrl } from 'app/features/alerting/unified/utils/url';
|
||||
import { createRelativeUrl } from 'app/features/alerting/unified/utils/url';
|
||||
|
||||
import { ContactPointWithMetadata } from '../../../../contact-points/utils';
|
||||
|
||||
@@ -144,7 +144,7 @@ export function ContactPointSelector({
|
||||
function LinkToContactPoints() {
|
||||
const hrefToContactPoints = '/alerting/notifications';
|
||||
return (
|
||||
<TextLink external href={createUrl(hrefToContactPoints)} aria-label="View or create contact points">
|
||||
<TextLink external href={createRelativeUrl(hrefToContactPoints)} aria-label="View or create contact points">
|
||||
View or create contact points
|
||||
</TextLink>
|
||||
);
|
||||
|
||||
@@ -11,7 +11,7 @@ import { PromAlertingRuleState } from 'app/types/unified-alerting-dto';
|
||||
import { AlertRuleAction, useAlertRuleAbility } from '../../hooks/useAbilities';
|
||||
import { createShareLink, isLocalDevEnv, isOpenSourceEdition } from '../../utils/misc';
|
||||
import * as ruleId from '../../utils/rule-id';
|
||||
import { createUrl } from '../../utils/url';
|
||||
import { createRelativeUrl } from '../../utils/url';
|
||||
import { DeclareIncidentMenuItem } from '../bridges/DeclareIncidentButton';
|
||||
|
||||
interface Props {
|
||||
@@ -123,9 +123,12 @@ type PropsWithIdentifier = { identifier: RuleIdentifier };
|
||||
|
||||
const ExportMenuItem = ({ identifier }: PropsWithIdentifier) => {
|
||||
const returnTo = location.pathname + location.search;
|
||||
const url = createUrl(`/alerting/${encodeURIComponent(ruleId.stringifyIdentifier(identifier))}/modify-export`, {
|
||||
returnTo,
|
||||
});
|
||||
const url = createRelativeUrl(
|
||||
`/alerting/${encodeURIComponent(ruleId.stringifyIdentifier(identifier))}/modify-export`,
|
||||
{
|
||||
returnTo,
|
||||
}
|
||||
);
|
||||
|
||||
return <Menu.Item key="with-modifications" label="With modifications" icon="file-edit-alt" url={url} />;
|
||||
};
|
||||
|
||||
@@ -25,7 +25,7 @@ import {
|
||||
isGrafanaRulerRulePaused,
|
||||
isRecordingRule,
|
||||
} from '../../utils/rules';
|
||||
import { createUrl } from '../../utils/url';
|
||||
import { createRelativeUrl } from '../../utils/url';
|
||||
import { AlertLabels } from '../AlertLabels';
|
||||
import { AlertingPageWrapper } from '../AlertingPageWrapper';
|
||||
import { ProvisionedResource, ProvisioningAlert } from '../Provisioning';
|
||||
@@ -222,7 +222,7 @@ const createMetadata = (rule: CombinedRule): PageInfoItem[] => {
|
||||
// TODO move somewhere else
|
||||
export const createListFilterLink = (values: Array<[string, string]>) => {
|
||||
const params = new URLSearchParams([['search', values.map(([key, value]) => `${key}:"${value}"`).join(' ')]]);
|
||||
return createUrl(`/alerting/list?` + params.toString());
|
||||
return createRelativeUrl(`/alerting/list`, params);
|
||||
};
|
||||
|
||||
interface TitleProps {
|
||||
|
||||
@@ -17,7 +17,7 @@ import { useUnifiedAlertingSelector } from '../../hooks/useUnifiedAlertingSelect
|
||||
import { getPaginationStyles } from '../../styles/pagination';
|
||||
import { GRAFANA_RULES_SOURCE_NAME } from '../../utils/datasource';
|
||||
import { initialAsyncRequestState } from '../../utils/redux';
|
||||
import { createUrl } from '../../utils/url';
|
||||
import { createRelativeUrl } from '../../utils/url';
|
||||
import { GrafanaRulesExporter } from '../export/GrafanaRulesExporter';
|
||||
|
||||
import { RulesGroup } from './RulesGroup';
|
||||
@@ -86,7 +86,7 @@ export const GrafanaRules = ({ namespaces, expandAll }: Props) => {
|
||||
)}
|
||||
{grafanaRecordingRulesEnabled && (
|
||||
<LinkButton
|
||||
href={createUrl('/alerting/new/grafana-recording', {
|
||||
href={createRelativeUrl('/alerting/new/grafana-recording', {
|
||||
returnTo: '/alerting/list' + location.search,
|
||||
})}
|
||||
icon="plus"
|
||||
|
||||
@@ -19,7 +19,7 @@ import { GRAFANA_RULES_SOURCE_NAME, getRulesSourceName } from '../../utils/datas
|
||||
import { createViewLink } from '../../utils/misc';
|
||||
import * as ruleId from '../../utils/rule-id';
|
||||
import { isGrafanaAlertingRule, isGrafanaRulerRule } from '../../utils/rules';
|
||||
import { createUrl } from '../../utils/url';
|
||||
import { createRelativeUrl } from '../../utils/url';
|
||||
|
||||
import { RedirectToCloneRule } from './CloneRule';
|
||||
|
||||
@@ -95,7 +95,7 @@ export const RuleActionsButtons = ({ compact, showViewButton, showCopyLinkButton
|
||||
if (rulerRule && canEditRule) {
|
||||
const identifier = ruleId.fromRulerRule(sourceName, namespace.name, group.name, rulerRule);
|
||||
|
||||
const editURL = createUrl(`/alerting/${encodeURIComponent(ruleId.stringifyIdentifier(identifier))}/edit`, {
|
||||
const editURL = createRelativeUrl(`/alerting/${encodeURIComponent(ruleId.stringifyIdentifier(identifier))}/edit`, {
|
||||
returnTo,
|
||||
});
|
||||
|
||||
|
||||
+2
-2
@@ -28,7 +28,7 @@ import { usePagination } from '../../../hooks/usePagination';
|
||||
import { combineMatcherStrings, labelsMatchMatchers } from '../../../utils/alertmanager';
|
||||
import { GRAFANA_RULES_SOURCE_NAME } from '../../../utils/datasource';
|
||||
import { parsePromQLStyleMatcherLooseSafe } from '../../../utils/matchers';
|
||||
import { createUrl } from '../../../utils/url';
|
||||
import { createRelativeUrl } from '../../../utils/url';
|
||||
import { AlertLabels } from '../../AlertLabels';
|
||||
import { CollapseToggle } from '../../CollapseToggle';
|
||||
import { LogRecord } from '../state-history/common';
|
||||
@@ -240,7 +240,7 @@ function AlertRuleName({ labels, ruleUID }: AlertRuleNameProps) {
|
||||
</Text>
|
||||
);
|
||||
}
|
||||
const ruleViewUrl = createUrl(`/alerting/${GRAFANA_RULES_SOURCE_NAME}/${ruleUID}/view`, {
|
||||
const ruleViewUrl = createRelativeUrl(`/alerting/${GRAFANA_RULES_SOURCE_NAME}/${ruleUID}/view`, {
|
||||
tab: 'history',
|
||||
returnTo,
|
||||
});
|
||||
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
isProvisionedDataSource,
|
||||
isVanillaPrometheusAlertManagerDataSource,
|
||||
} from '../../utils/datasource';
|
||||
import { createUrl } from '../../utils/url';
|
||||
import { createRelativeUrl } from '../../utils/url';
|
||||
|
||||
import { AlertmanagerCard } from './AlertmanagerCard';
|
||||
import { useSettings } from './SettingsContext';
|
||||
@@ -50,8 +50,9 @@ export const ExternalAlertmanagers = ({ onEditConfiguration }: Props) => {
|
||||
const isReceiving = isReceivingGrafanaAlerts(alertmanager);
|
||||
const isProvisioned = isProvisionedDataSource(alertmanager.dataSourceSettings);
|
||||
const isReadOnly = isVanillaPrometheusAlertManagerDataSource(alertmanager.dataSourceSettings.name);
|
||||
|
||||
const detailHref = createUrl(DATASOURCES_ROUTES.Edit.replace(/:uid/gi, uid));
|
||||
// typescript on next line is wrong, as DATASOURCES_ROUTES.Edit is a RelativeUrl type, and replacing :uid with uid makes still a RelativeUrl
|
||||
// @ts-ignore
|
||||
const detailHref = createRelativeUrl(DATASOURCES_ROUTES.Edit.replace(/:uid/gi, uid));
|
||||
|
||||
const handleEditConfiguration = () => onEditConfiguration(name);
|
||||
const handleEnable = forwardingDisabled ? undefined : () => enableAlertmanager(uid);
|
||||
|
||||
@@ -13,7 +13,7 @@ import { DataSourceRef } from '@grafana/schema';
|
||||
import { Link, useStyles2 } from '@grafana/ui';
|
||||
|
||||
import { PANEL_STYLES } from '../../home/Insights';
|
||||
import { createUrl } from '../../utils/url';
|
||||
import { createRelativeUrl } from '../../utils/url';
|
||||
import { InsightsRatingModal } from '../RatingModal';
|
||||
|
||||
export function getMostFiredInstancesScene(datasource: DataSourceRef, panelTitle: string) {
|
||||
@@ -119,7 +119,7 @@ export function RuleLink({ value, ruleUID }: { value: string; ruleUID: string })
|
||||
|
||||
return (
|
||||
<div className={styles.link}>
|
||||
<Link target="_blank" href={createUrl(`/alerting/grafana/${ruleUID}/view`)}>
|
||||
<Link target="_blank" href={createRelativeUrl(`/alerting/grafana/${ruleUID}/view`)}>
|
||||
{value}
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
@@ -3,7 +3,7 @@ import { lazy, Suspense } from 'react';
|
||||
import { Drawer, LoadingPlaceholder, Stack, TextLink } from '@grafana/ui';
|
||||
|
||||
import { t } from '../../../../core/internationalization';
|
||||
import { createUrl } from '../utils/url';
|
||||
import { createRelativeUrl } from '../utils/url';
|
||||
|
||||
const AlertRulesDrawerContent = lazy(
|
||||
() => import(/* webpackChunkName: "alert-rules-drawer-content" */ './AlertRulesDrawerContent')
|
||||
@@ -30,7 +30,7 @@ function DrawerSubtitle({ dashboardUid }: { dashboardUid: string }) {
|
||||
return (
|
||||
<Stack gap={2}>
|
||||
<div>{t('dashboard.alert-rules-drawer.subtitle', 'Alert rules related to this dashboard')}</div>
|
||||
<TextLink href={createUrl(`/alerting/list/?${searchParams.toString()}`)}>
|
||||
<TextLink href={createRelativeUrl(`/alerting/list/?${searchParams.toString()}`)}>
|
||||
{t('dashboard.alert-rules-drawer.redirect-link', 'List in Grafana Alerting')}
|
||||
</TextLink>
|
||||
</Stack>
|
||||
|
||||
@@ -19,7 +19,7 @@ import { ALERTMANAGER_NAME_QUERY_KEY } from './constants';
|
||||
import { getRulesSourceName, isCloudRulesSource } from './datasource';
|
||||
import { getMatcherQueryParams } from './matchers';
|
||||
import * as ruleId from './rule-id';
|
||||
import { createAbsoluteUrl, createUrl } from './url';
|
||||
import { createAbsoluteUrl, createRelativeUrl } from './url';
|
||||
|
||||
export function createViewLink(ruleSource: RulesSource, rule: CombinedRule, returnTo?: string): string {
|
||||
const sourceName = getRulesSourceName(ruleSource);
|
||||
@@ -27,13 +27,13 @@ export function createViewLink(ruleSource: RulesSource, rule: CombinedRule, retu
|
||||
const paramId = encodeURIComponent(ruleId.stringifyIdentifier(identifier));
|
||||
const paramSource = encodeURIComponent(sourceName);
|
||||
|
||||
return createUrl(`/alerting/${paramSource}/${paramId}/view`, returnTo ? { returnTo } : {});
|
||||
return createRelativeUrl(`/alerting/${paramSource}/${paramId}/view`, returnTo ? { returnTo } : {});
|
||||
}
|
||||
|
||||
export function createExploreLink(datasource: DataSourceRef, query: string) {
|
||||
const { uid, type } = datasource;
|
||||
|
||||
return createUrl(`/explore`, {
|
||||
return createRelativeUrl(`/explore`, {
|
||||
left: JSON.stringify({
|
||||
datasource: datasource.uid,
|
||||
queries: [{ refId: 'A', datasource: { uid, type }, expr: query }],
|
||||
@@ -43,13 +43,13 @@ export function createExploreLink(datasource: DataSourceRef, query: string) {
|
||||
}
|
||||
|
||||
export function createContactPointLink(contactPoint: string, alertManagerSourceName = ''): string {
|
||||
return createUrl(`/alerting/notifications/receivers/${encodeURIComponent(contactPoint)}/edit`, {
|
||||
return createRelativeUrl(`/alerting/notifications/receivers/${encodeURIComponent(contactPoint)}/edit`, {
|
||||
alertmanager: alertManagerSourceName,
|
||||
});
|
||||
}
|
||||
|
||||
export function createMuteTimingLink(muteTimingName: string, alertManagerSourceName = ''): string {
|
||||
return createUrl('/alerting/routes/mute-timing/edit', {
|
||||
return createRelativeUrl('/alerting/routes/mute-timing/edit', {
|
||||
muteName: muteTimingName,
|
||||
alertmanager: alertManagerSourceName,
|
||||
});
|
||||
@@ -125,32 +125,32 @@ export function makeLabelBasedSilenceLink(alertManagerSourceName: string, labels
|
||||
const matcherParams = getMatcherQueryParams(labels);
|
||||
matcherParams.forEach((value, key) => silenceUrlParams.append(key, value));
|
||||
|
||||
return createUrl('/alerting/silence/new', silenceUrlParams);
|
||||
return createRelativeUrl('/alerting/silence/new', silenceUrlParams);
|
||||
}
|
||||
|
||||
export function makeDataSourceLink(uid: string) {
|
||||
return createUrl(`/datasources/edit/${uid}`);
|
||||
return createRelativeUrl(`/datasources/edit/${uid}`);
|
||||
}
|
||||
|
||||
export function makeFolderLink(folderUID: string): string {
|
||||
return createUrl(`/dashboards/f/${folderUID}`);
|
||||
return createRelativeUrl(`/dashboards/f/${folderUID}`);
|
||||
}
|
||||
|
||||
export function makeFolderAlertsLink(folderUID: string, title: string): string {
|
||||
return createUrl(`/dashboards/f/${folderUID}/${title}/alerting`);
|
||||
return createRelativeUrl(`/dashboards/f/${folderUID}/${title}/alerting`);
|
||||
}
|
||||
|
||||
export function makeFolderSettingsLink(uid: string): string {
|
||||
return createUrl(`/dashboards/f/${uid}/settings`);
|
||||
return createRelativeUrl(`/dashboards/f/${uid}/settings`);
|
||||
}
|
||||
|
||||
export function makeDashboardLink(dashboardUID: string): string {
|
||||
return createUrl(`/d/${encodeURIComponent(dashboardUID)}`);
|
||||
return createRelativeUrl(`/d/${encodeURIComponent(dashboardUID)}`);
|
||||
}
|
||||
|
||||
export function makePanelLink(dashboardUID: string, panelId: string): string {
|
||||
const panelParams = new URLSearchParams({ viewPanel: panelId });
|
||||
return createUrl(`/d/${encodeURIComponent(dashboardUID)}`, panelParams);
|
||||
return createRelativeUrl(`/d/${encodeURIComponent(dashboardUID)}`, panelParams);
|
||||
}
|
||||
|
||||
// keep retrying fn if it's error passes shouldRetry(error) and timeout has not elapsed yet
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
import { config } from '@grafana/runtime';
|
||||
|
||||
import { createAbsoluteUrl, createRelativeUrl } from './url';
|
||||
|
||||
config.appSubUrl = '/base';
|
||||
config.appUrl = 'https://example.com';
|
||||
|
||||
describe('createRelativeUrl', () => {
|
||||
it('should create a relative URL with no query parameters', () => {
|
||||
expect(createRelativeUrl('/test')).toBe('/base/test');
|
||||
});
|
||||
|
||||
it('should create a relative URL with string query parameters', () => {
|
||||
expect(createRelativeUrl('/test', 'param1=value1¶m2=value2')).toBe('/base/test?param1=value1¶m2=value2');
|
||||
});
|
||||
|
||||
it('should create a relative URL with object query parameters', () => {
|
||||
expect(createRelativeUrl('/test', { param1: 'value1', param2: 'value2' })).toBe(
|
||||
'/base/test?param1=value1¶m2=value2'
|
||||
);
|
||||
});
|
||||
|
||||
it('should create a relative URL with array query parameters', () => {
|
||||
expect(
|
||||
createRelativeUrl('/test', [
|
||||
['param1', 'value1'],
|
||||
['param2', 'value2'],
|
||||
])
|
||||
).toBe('/base/test?param1=value1¶m2=value2');
|
||||
});
|
||||
});
|
||||
|
||||
describe('createAbsoluteUrl', () => {
|
||||
it('should create an absolute URL with no query parameters', () => {
|
||||
expect(createAbsoluteUrl('/test')).toBe('https://example.com/base/test');
|
||||
});
|
||||
|
||||
it('should create an absolute URL with string query parameters', () => {
|
||||
expect(createAbsoluteUrl('/test', 'param1=value1¶m2=value2')).toBe(
|
||||
'https://example.com/base/test?param1=value1¶m2=value2'
|
||||
);
|
||||
});
|
||||
|
||||
it('should create an absolute URL with object query parameters', () => {
|
||||
expect(createAbsoluteUrl('/test', { param1: 'value1', param2: 'value2' })).toBe(
|
||||
'https://example.com/base/test?param1=value1¶m2=value2'
|
||||
);
|
||||
});
|
||||
|
||||
it('should create an absolute URL with array query parameters', () => {
|
||||
expect(
|
||||
createAbsoluteUrl('/test', [
|
||||
['param1', 'value1'],
|
||||
['param2', 'value2'],
|
||||
])
|
||||
).toBe('https://example.com/base/test?param1=value1¶m2=value2');
|
||||
});
|
||||
|
||||
it('should fallback to relative URL if base URL is invalid', () => {
|
||||
const originalAppUrl = config.appUrl;
|
||||
config.appUrl = 'invalid-url';
|
||||
expect(createAbsoluteUrl('/test')).toBe('/base/test');
|
||||
config.appUrl = originalAppUrl;
|
||||
});
|
||||
});
|
||||
@@ -1,6 +1,10 @@
|
||||
import { config } from '@grafana/runtime';
|
||||
|
||||
export function createUrl(path: string, queryParams?: string[][] | Record<string, string> | string | URLSearchParams) {
|
||||
export type RelativeUrl = `/${string}`;
|
||||
export function createRelativeUrl(
|
||||
path: RelativeUrl,
|
||||
queryParams?: string[][] | Record<string, string> | string | URLSearchParams
|
||||
) {
|
||||
const searchParams = new URLSearchParams(queryParams);
|
||||
const searchParamsString = searchParams.toString();
|
||||
|
||||
@@ -8,7 +12,7 @@ export function createUrl(path: string, queryParams?: string[][] | Record<string
|
||||
}
|
||||
|
||||
export function createAbsoluteUrl(
|
||||
path: string,
|
||||
path: RelativeUrl,
|
||||
queryParams?: string[][] | Record<string, string> | string | URLSearchParams
|
||||
) {
|
||||
const searchParams = new URLSearchParams(queryParams);
|
||||
@@ -18,6 +22,6 @@ export function createAbsoluteUrl(
|
||||
const baseUrl = new URL(config.appSubUrl + path, config.appUrl);
|
||||
return `${baseUrl.href}${searchParamsString ? `?${searchParamsString}` : ''}`;
|
||||
} catch (err) {
|
||||
return createUrl(path, queryParams);
|
||||
return createRelativeUrl(path, queryParams);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { DataQuery, DataSourceApi, DataSourceJsonData, DataSourcePlugin } from '@grafana/data';
|
||||
|
||||
import { RelativeUrl } from '../alerting/unified/utils/url';
|
||||
|
||||
export type GenericDataSourcePlugin = DataSourcePlugin<DataSourceApi<DataQuery, DataSourceJsonData>>;
|
||||
|
||||
export type DataSourceRights = {
|
||||
@@ -9,10 +11,10 @@ export type DataSourceRights = {
|
||||
};
|
||||
|
||||
export type DataSourcesRoutes = {
|
||||
New: string;
|
||||
Edit: string;
|
||||
List: string;
|
||||
Dashboards: string;
|
||||
New: RelativeUrl;
|
||||
Edit: RelativeUrl;
|
||||
List: RelativeUrl;
|
||||
Dashboards: RelativeUrl;
|
||||
};
|
||||
|
||||
export type DataSourceTestStatus = 'success' | 'warning' | 'error';
|
||||
|
||||
@@ -2,7 +2,7 @@ import { css } from '@emotion/css';
|
||||
|
||||
import { GrafanaTheme2 } from '@grafana/data';
|
||||
import { Button, Drawer, Dropdown, Icon, LinkButton, Menu, Stack, Text, Tooltip, useStyles2 } from '@grafana/ui';
|
||||
import { createUrl } from 'app/features/alerting/unified/utils/url';
|
||||
import { RelativeUrl, createRelativeUrl } from 'app/features/alerting/unified/utils/url';
|
||||
|
||||
import { SectionDto, SectionDtoStep, SectionsDto, StepButtonDto } from '../irmHooks';
|
||||
|
||||
@@ -86,22 +86,22 @@ function Step({ step }: StepProps) {
|
||||
}
|
||||
|
||||
interface LinkButtonProps {
|
||||
urlLink?: { url: string; queryParams?: Record<string, string> };
|
||||
urlLink?: { url: RelativeUrl; queryParams?: Record<string, string> };
|
||||
label: string;
|
||||
urlLinkOnDone?: { url: string; queryParams?: Record<string, 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
|
||||
? createUrl(urlLink.url, {
|
||||
? createRelativeUrl(urlLink.url, {
|
||||
returnTo: location.pathname + location.search,
|
||||
...urlLink.queryParams,
|
||||
})
|
||||
: '';
|
||||
const urlToGoWhenDone = urlLinkOnDone?.url
|
||||
? createUrl(urlLinkOnDone.url, {
|
||||
? createRelativeUrl(urlLinkOnDone.url, {
|
||||
returnTo: location.pathname + location.search,
|
||||
...urlLinkOnDone.queryParams,
|
||||
})
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { useMemo } from 'react';
|
||||
|
||||
import { locationService } from '@grafana/runtime';
|
||||
import { createUrl } from 'app/features/alerting/unified/utils/url';
|
||||
import { RelativeUrl, createRelativeUrl } from 'app/features/alerting/unified/utils/url';
|
||||
|
||||
import {
|
||||
isOnCallContactPointReady,
|
||||
@@ -16,7 +16,7 @@ import { useOnCallChatOpsConnections, useOnCallOptions } from './onCall/hooks';
|
||||
import { useSloChecks } from './slo/hooks';
|
||||
|
||||
interface UrlLink {
|
||||
url: string;
|
||||
url: RelativeUrl;
|
||||
queryParams?: Record<string, string>;
|
||||
}
|
||||
export interface StepButtonDto {
|
||||
@@ -113,8 +113,8 @@ export function useGetEssentialsConfiguration(): EssentialsConfigurationData {
|
||||
isLoading,
|
||||
} = useGetConfigurationForApps();
|
||||
|
||||
function onIntegrationClick(integrationId: string, url: string) {
|
||||
const urlToGoWithIntegration = createUrl(url + integrationId, {
|
||||
function onIntegrationClick(integrationId: string, url: RelativeUrl) {
|
||||
const urlToGoWithIntegration = createRelativeUrl(`${url} + ${integrationId}`, {
|
||||
returnTo: location.pathname + location.search,
|
||||
});
|
||||
locationService.push(urlToGoWithIntegration);
|
||||
|
||||
@@ -2,7 +2,7 @@ import { css, cx } from '@emotion/css';
|
||||
import { useLocation } from 'react-use';
|
||||
|
||||
import { GrafanaTheme2, intervalToAbbreviatedDurationString } from '@grafana/data';
|
||||
import { Icon, useStyles2, Stack } from '@grafana/ui';
|
||||
import { Icon, Stack, useStyles2 } from '@grafana/ui';
|
||||
import alertDef from 'app/features/alerting/state/alertDef';
|
||||
import { Spacer } from 'app/features/alerting/unified/components/Spacer';
|
||||
import { fromCombinedRule, stringifyIdentifier } from 'app/features/alerting/unified/utils/rule-id';
|
||||
@@ -12,11 +12,11 @@ import {
|
||||
getFirstActiveAt,
|
||||
isAlertingRule,
|
||||
} from 'app/features/alerting/unified/utils/rules';
|
||||
import { createUrl } from 'app/features/alerting/unified/utils/url';
|
||||
import { createRelativeUrl } from 'app/features/alerting/unified/utils/url';
|
||||
import { PromAlertingRuleState } from 'app/types/unified-alerting-dto';
|
||||
|
||||
import { GRAFANA_RULES_SOURCE_NAME } from '../../../../features/alerting/unified/utils/datasource';
|
||||
import { AlertingRule, AlertInstanceTotalState, CombinedRuleWithLocation } from '../../../../types/unified-alerting';
|
||||
import { AlertInstanceTotalState, AlertingRule, CombinedRuleWithLocation } from '../../../../types/unified-alerting';
|
||||
import { AlertInstances } from '../AlertInstances';
|
||||
import { getStyles } from '../UnifiedAlertList';
|
||||
import { UnifiedAlertListOptions } from '../types';
|
||||
@@ -63,7 +63,7 @@ const UngroupedModeView = ({ rules, options, handleInstancesLimit, limitInstance
|
||||
? getGrafanaInstancesTotal(ruleWithLocation.filteredInstanceTotals)
|
||||
: undefined;
|
||||
|
||||
const href = createUrl(
|
||||
const href = createRelativeUrl(
|
||||
`/alerting/${encodeURIComponent(dataSourceName)}/${encodeURIComponent(strIndentifier)}/view`,
|
||||
{ returnTo: returnTo ?? '' }
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user