diff --git a/public/app/features/explore/TraceView/components/TraceTimelineViewer/SpanDetailRow.test.tsx b/public/app/features/explore/TraceView/components/TraceTimelineViewer/SpanDetailRow.test.tsx
index f1768425ceb..629e6da37c5 100644
--- a/public/app/features/explore/TraceView/components/TraceTimelineViewer/SpanDetailRow.test.tsx
+++ b/public/app/features/explore/TraceView/components/TraceTimelineViewer/SpanDetailRow.test.tsx
@@ -14,7 +14,7 @@
import { render, screen } from '@testing-library/react';
-import { createTheme } from '@grafana/data';
+import { createTheme, dateTime } from '@grafana/data';
import { setPluginLinksHook } from '@grafana/runtime';
import DetailState from './SpanDetail/DetailState';
@@ -48,6 +48,8 @@ const setup = (propOverrides?: SpanDetailRowProps) => {
theme: createTheme(),
traceFlameGraphs: {},
timeRange: {
+ from: dateTime(0),
+ to: dateTime(1000000000000),
raw: {
from: 0,
to: 1000000000000,
diff --git a/public/app/features/logs/components/LogDetails.test.tsx b/public/app/features/logs/components/LogDetails.test.tsx
index f8e7b6ff3bb..454d80b8a23 100644
--- a/public/app/features/logs/components/LogDetails.test.tsx
+++ b/public/app/features/logs/components/LogDetails.test.tsx
@@ -12,6 +12,7 @@ import {
DataFrameType,
CoreApp,
PluginExtensionPoints,
+ dateTime,
} from '@grafana/data';
import { setPluginLinksHook } from '@grafana/runtime';
@@ -43,6 +44,14 @@ const setup = (propOverrides?: Partial
, rowOverrides?: Partial {
type: 'loki',
uid: 'grafanacloud-logs',
},
+ timeRange: {
+ from: 1757937009041,
+ to: 1757940609041,
+ },
attributes: { key1: ['label1'], key2: ['label2'] },
},
});
diff --git a/public/app/features/logs/components/LogDetails.tsx b/public/app/features/logs/components/LogDetails.tsx
index 99313cf1ae9..83f19909845 100644
--- a/public/app/features/logs/components/LogDetails.tsx
+++ b/public/app/features/logs/components/LogDetails.tsx
@@ -2,6 +2,7 @@ import { cx } from '@emotion/css';
import { PureComponent, useMemo } from 'react';
import {
+ TimeRange,
CoreApp,
DataFrame,
DataFrameType,
@@ -44,23 +45,25 @@ export interface Props extends Themeable2 {
onPinLine?: (row: LogRowModel) => void;
pinLineButtonTooltipTitle?: PopoverContent;
links?: Record;
+ timeRange: TimeRange;
}
interface LinkModelWithIcon extends LinkModel {
icon?: IconName;
}
-export const useAttributesExtensionLinks = (row: LogRowModel) => {
+export const useAttributesExtensionLinks = (row: LogRowModel, timeRange: TimeRange) => {
// Stable context for useMemo inside usePluginLinks
const context: PluginExtensionResourceAttributesContext = useMemo(() => {
return {
attributes: Object.fromEntries(Object.entries(row.labels).map(([key, value]) => [key, [value]])),
+ timeRange: { from: timeRange.from.valueOf(), to: timeRange.to.valueOf() },
datasource: {
type: row.datasourceType ?? '',
uid: row.datasourceUid ?? '',
},
};
- }, [row.labels, row.datasourceType, row.datasourceUid]);
+ }, [row.labels, row.datasourceType, row.datasourceUid, timeRange]);
const { links } = usePluginLinks({
extensionPointId: PluginExtensionPoints.LogsViewResourceAttributes,
@@ -93,7 +96,7 @@ export const useAttributesExtensionLinks = (row: LogRowModel) => {
const withAttributesExtensionLinks = (Component: React.ComponentType) => {
function ComponentWithLinks(props: Props) {
- const labelLinks = useAttributesExtensionLinks(props.row);
+ const labelLinks = useAttributesExtensionLinks(props.row, props.timeRange);
return ;
}
diff --git a/public/app/features/logs/components/LogRow.test.tsx b/public/app/features/logs/components/LogRow.test.tsx
index 3760ebf4b1f..f718fcf3a9e 100644
--- a/public/app/features/logs/components/LogRow.test.tsx
+++ b/public/app/features/logs/components/LogRow.test.tsx
@@ -4,6 +4,7 @@ import { ComponentProps } from 'react';
import tinycolor from 'tinycolor2';
import { CoreApp, createTheme, LogLevel, LogRowModel } from '@grafana/data';
+import { mockTimeRange } from '@grafana/plugin-ui';
import { LogRow } from './LogRow';
import { getLogRowStyles } from './getLogRowStyles';
@@ -40,6 +41,7 @@ const setup = (propOverrides?: Partial>, rowOverri
wrapLogMessage: false,
timeZone: 'utc',
styles,
+ timeRange: mockTimeRange(),
...(propOverrides || {}),
};
diff --git a/public/app/features/logs/components/LogRow.tsx b/public/app/features/logs/components/LogRow.tsx
index 5c12fbbd88f..5c6bc170c61 100644
--- a/public/app/features/logs/components/LogRow.tsx
+++ b/public/app/features/logs/components/LogRow.tsx
@@ -1,7 +1,15 @@
import { debounce } from 'lodash';
import { MouseEvent, ReactNode, useCallback, useEffect, useMemo, useRef, useState } from 'react';
-import { CoreApp, DataFrame, dateTimeFormat, LogRowContextOptions, LogRowModel, LogsSortOrder } from '@grafana/data';
+import {
+ CoreApp,
+ DataFrame,
+ dateTimeFormat,
+ LogRowContextOptions,
+ LogRowModel,
+ LogsSortOrder,
+ TimeRange,
+} from '@grafana/data';
import { t } from '@grafana/i18n';
import { reportInteraction } from '@grafana/runtime';
import { DataQuery, TimeZone } from '@grafana/schema';
@@ -56,6 +64,7 @@ export interface Props {
handleTextSelection?: (e: MouseEvent, row: LogRowModel) => boolean;
logRowMenuIconsBefore?: ReactNode[];
logRowMenuIconsAfter?: ReactNode[];
+ timeRange: TimeRange;
}
export const LogRow = ({
@@ -314,6 +323,7 @@ export const LogRow = ({
styles={styles}
isFilterLabelActive={props.isFilterLabelActive}
pinLineButtonTooltipTitle={props.pinLineButtonTooltipTitle}
+ timeRange={props.timeRange}
/>
)}
>
diff --git a/public/app/features/logs/components/LogRows.test.tsx b/public/app/features/logs/components/LogRows.test.tsx
index a79ac2787c0..ac38cea7c3f 100644
--- a/public/app/features/logs/components/LogRows.test.tsx
+++ b/public/app/features/logs/components/LogRows.test.tsx
@@ -2,6 +2,7 @@ import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { LogRowModel, LogsDedupStrategy, LogsSortOrder } from '@grafana/data';
+import { mockTimeRange } from '@grafana/plugin-ui';
import { disablePopoverMenu, enablePopoverMenu, isPopoverMenuDisabled } from '../utils';
@@ -46,6 +47,7 @@ describe('LogRows', () => {
onClickHideField={() => {}}
onClickShowField={() => {}}
scrollElement={null}
+ timeRange={mockTimeRange()}
/>
);
@@ -75,6 +77,7 @@ describe('LogRows', () => {
onClickHideField={() => {}}
onClickShowField={() => {}}
scrollElement={null}
+ timeRange={mockTimeRange()}
/>
);
expect(screen.queryAllByRole('row')).toHaveLength(2);
@@ -105,6 +108,7 @@ describe('LogRows', () => {
onClickHideField={() => {}}
onClickShowField={() => {}}
scrollElement={null}
+ timeRange={mockTimeRange()}
/>
);
@@ -135,6 +139,7 @@ describe('LogRows', () => {
onClickHideField={() => {}}
onClickShowField={() => {}}
scrollElement={null}
+ timeRange={mockTimeRange()}
/>
);
@@ -162,6 +167,7 @@ describe('Popover menu', () => {
onClickFilterOutString={() => {}}
onClickFilterString={() => {}}
scrollElement={null}
+ timeRange={mockTimeRange()}
{...overrides}
/>
);
diff --git a/public/app/features/logs/components/LogRows.tsx b/public/app/features/logs/components/LogRows.tsx
index 85c4af15f7a..3c564f5c538 100644
--- a/public/app/features/logs/components/LogRows.tsx
+++ b/public/app/features/logs/components/LogRows.tsx
@@ -9,6 +9,7 @@ import {
CoreApp,
DataFrame,
LogRowContextOptions,
+ TimeRange,
} from '@grafana/data';
import { Trans, t } from '@grafana/i18n';
import { config } from '@grafana/runtime';
@@ -61,6 +62,7 @@ export interface Props {
scrollIntoView?: (element: HTMLElement) => void;
isFilterLabelActive?: (key: string, value: string, refId?: string) => Promise;
pinnedLogs?: string[];
+ timeRange: TimeRange;
/**
* If false or undefined, the `contain:strict` css property will be added to the wrapping `` for performance reasons.
* Any overflowing content will be clipped at the table boundary.
diff --git a/public/app/features/logs/components/log-context/LogRowContextModal.tsx b/public/app/features/logs/components/log-context/LogRowContextModal.tsx
index c7aaa58a3af..2c712094a6d 100644
--- a/public/app/features/logs/components/log-context/LogRowContextModal.tsx
+++ b/public/app/features/logs/components/log-context/LogRowContextModal.tsx
@@ -492,6 +492,7 @@ export const LogRowContextModal: React.FunctionComponent
@@ -575,6 +577,7 @@ export const LogRowContextModal: React.FunctionComponent
@@ -594,6 +597,7 @@ export const LogRowContextModal: React.FunctionComponent
>
@@ -637,7 +641,7 @@ export const LogRowContextModal: React.FunctionComponent {
type: 'loki',
uid: 'grafanacloud-logs',
},
+ timeRange: {
+ from: 1757937009041,
+ to: 1757940609041,
+ },
attributes: { key1: ['label1'], key2: ['label2'] },
},
});
diff --git a/public/app/features/logs/components/panel/LogLineDetailsComponent.tsx b/public/app/features/logs/components/panel/LogLineDetailsComponent.tsx
index 0f274e4ed6d..240bc546313 100644
--- a/public/app/features/logs/components/panel/LogLineDetailsComponent.tsx
+++ b/public/app/features/logs/components/panel/LogLineDetailsComponent.tsx
@@ -37,7 +37,7 @@ export const LogLineDetailsComponent = memo(
const inputRef = useRef('');
const styles = useStyles2(getStyles);
- const extensionLinks = useAttributesExtensionLinks(log);
+ const extensionLinks = useAttributesExtensionLinks(log, timeRange);
const fieldsWithLinks = useMemo(() => {
const fieldsWithLinks = log.fields.filter((f) => f.links?.length);
diff --git a/public/app/features/provisioning/GettingStarted/FeaturesList.tsx b/public/app/features/provisioning/GettingStarted/FeaturesList.tsx
index e3352e461b5..0b932e725df 100644
--- a/public/app/features/provisioning/GettingStarted/FeaturesList.tsx
+++ b/public/app/features/provisioning/GettingStarted/FeaturesList.tsx
@@ -1,8 +1,10 @@
import { css } from '@emotion/css';
-import { GrafanaTheme2 } from '@grafana/data';
+import { FeatureState, GrafanaTheme2 } from '@grafana/data';
+import { GrafanaEdition } from '@grafana/data/internal';
import { Trans } from '@grafana/i18n';
-import { Box, LinkButton, Stack, Text, useStyles2 } from '@grafana/ui';
+import { config } from '@grafana/runtime';
+import { Box, FeatureBadge, LinkButton, Stack, Text, TextLink, useStyles2 } from '@grafana/ui';
import { RepositoryTypeCards } from '../Shared/RepositoryTypeCards';
@@ -13,13 +15,15 @@ interface FeaturesListProps {
export const FeaturesList = ({ hasRequiredFeatures, onSetupFeatures }: FeaturesListProps) => {
const styles = useStyles2(getStyles);
+ const isOnPrem = [GrafanaEdition.OpenSource, GrafanaEdition.Enterprise].includes(config.buildInfo.edition);
return (
Get started with Git Sync
-
+ {' '}
+ {!isOnPrem && }
-
@@ -33,6 +37,20 @@ export const FeaturesList = ({ hasRequiredFeatures, onSetupFeatures }: FeaturesL
+
+
+ Want to learn more? See our{' '}
+
+ documentation
+
+ .
+
+
{!hasRequiredFeatures ? (
diff --git a/public/app/features/provisioning/GettingStarted/GettingStartedPage.tsx b/public/app/features/provisioning/GettingStarted/GettingStartedPage.tsx
index 14fefada984..ff9999698ba 100644
--- a/public/app/features/provisioning/GettingStarted/GettingStartedPage.tsx
+++ b/public/app/features/provisioning/GettingStarted/GettingStartedPage.tsx
@@ -1,4 +1,6 @@
+import { GrafanaEdition } from '@grafana/data/internal';
import { Trans, t } from '@grafana/i18n';
+import { config } from '@grafana/runtime';
import { Box, Text, TextLink } from '@grafana/ui';
import { Repository } from 'app/api/clients/provisioning/v0alpha1';
import { Page } from 'app/core/components/Page/Page';
@@ -30,6 +32,12 @@ export default function GettingStartedPage({ items }: Props) {
}
function Banner() {
+ const isOnPrem = [GrafanaEdition.OpenSource, GrafanaEdition.Enterprise].includes(config.buildInfo.edition);
+
+ if (!isOnPrem) {
+ return null;
+ }
+
return (
{
const opts: SelectableValue[] = [
diff --git a/public/app/features/search/service/dummy.ts b/public/app/features/search/service/dummy.ts
index d014fd22c6a..fe805bbe33a 100644
--- a/public/app/features/search/service/dummy.ts
+++ b/public/app/features/search/service/dummy.ts
@@ -1,7 +1,7 @@
import { SelectableValue, DataFrame, DataFrameView } from '@grafana/data';
import { TermCount } from 'app/core/components/TagFilter/TagFilter';
-import { GrafanaSearcher, QueryResponse, SearchQuery } from './types';
+import { GrafanaSearcher, LocationInfo, QueryResponse, SearchQuery } from './types';
// This is a dummy search useful for tests
export class DummySearcher implements GrafanaSearcher {
@@ -9,6 +9,7 @@ export class DummySearcher implements GrafanaSearcher {
expectedStarsResponse: QueryResponse | undefined;
expectedSortResponse: SelectableValue[] = [];
expectedTagsResponse: TermCount[] = [];
+ expectedLocationInfoResponse: Record = {};
setExpectedSearchResult(result: DataFrame) {
this.expectedSearchResponse = {
@@ -35,6 +36,10 @@ export class DummySearcher implements GrafanaSearcher {
return Promise.resolve(this.expectedTagsResponse);
}
+ async getLocationInfo(): Promise> {
+ return Promise.resolve(this.expectedLocationInfoResponse);
+ }
+
getFolderViewSort(): string {
return '';
}
diff --git a/public/app/features/search/service/frontend.ts b/public/app/features/search/service/frontend.ts
index 11634988f7a..b926d0c2cb2 100644
--- a/public/app/features/search/service/frontend.ts
+++ b/public/app/features/search/service/frontend.ts
@@ -76,6 +76,10 @@ export class FrontendSearcher implements GrafanaSearcher {
return this.parent.tags(query);
}
+ async getLocationInfo() {
+ return this.parent.getLocationInfo();
+ }
+
getFolderViewSort(): string {
return this.parent.getFolderViewSort();
}
diff --git a/public/app/features/search/service/sql.ts b/public/app/features/search/service/sql.ts
index ba0dbc9c894..137fee41620 100644
--- a/public/app/features/search/service/sql.ts
+++ b/public/app/features/search/service/sql.ts
@@ -130,6 +130,10 @@ export class SQLSearcher implements GrafanaSearcher {
return terms.sort((a, b) => b.count - a.count);
}
+ async getLocationInfo() {
+ return this.locationInfo;
+ }
+
async doAPIQuery(query: APIQuery): Promise {
let rsp: DashboardSearchHit[];
diff --git a/public/app/features/search/service/types.ts b/public/app/features/search/service/types.ts
index cd043a2f8fe..6617bb284f9 100644
--- a/public/app/features/search/service/types.ts
+++ b/public/app/features/search/service/types.ts
@@ -97,6 +97,7 @@ export interface GrafanaSearcher {
tags: (query: SearchQuery) => Promise;
getSortOptions: () => Promise;
sortPlaceholder?: string;
+ getLocationInfo: () => Promise>;
/** Gets the default sort used for the Folder view */
getFolderViewSort: () => string;
diff --git a/public/app/features/search/service/unified.ts b/public/app/features/search/service/unified.ts
index 272881a478a..c0514db43f9 100644
--- a/public/app/features/search/service/unified.ts
+++ b/public/app/features/search/service/unified.ts
@@ -92,6 +92,10 @@ export class UnifiedSearcher implements GrafanaSearcher {
return resp.facets?.tags?.terms || [];
}
+ async getLocationInfo() {
+ return this.locationInfo;
+ }
+
// TODO: Implement this correctly
getSortOptions(): Promise {
const opts: SelectableValue[] = [
diff --git a/public/app/plugins/datasource/cloudwatch/migrations/dashboardMigrations.ts b/public/app/plugins/datasource/cloudwatch/migrations/dashboardMigrations.ts
index d492a5ad3ce..4d97404fdcb 100644
--- a/public/app/plugins/datasource/cloudwatch/migrations/dashboardMigrations.ts
+++ b/public/app/plugins/datasource/cloudwatch/migrations/dashboardMigrations.ts
@@ -36,15 +36,17 @@ export function migrateMultipleStatsAnnotationQuery(
): Array> {
const newAnnotations: Array> = [];
- if (annotationQuery && 'statistics' in annotationQuery && annotationQuery?.statistics?.length) {
- for (const stat of annotationQuery.statistics.splice(1)) {
- const { statistics, name, ...newAnnotation } = annotationQuery;
- newAnnotations.push({ ...newAnnotation, statistic: stat, name: `${name} - ${stat}` });
- }
- annotationQuery.statistic = annotationQuery.statistics[0];
- // Only change the name of the original if new annotations have been created
- if (newAnnotations.length !== 0) {
- annotationQuery.name = `${annotationQuery.name} - ${annotationQuery.statistic}`;
+ if (annotationQuery && 'statistics' in annotationQuery) {
+ if (annotationQuery?.statistics?.length) {
+ for (const stat of annotationQuery.statistics.splice(1)) {
+ const { statistics, name, ...newAnnotation } = annotationQuery;
+ newAnnotations.push({ ...newAnnotation, statistic: stat, name: `${name} - ${stat}` });
+ }
+ annotationQuery.statistic = annotationQuery.statistics[0];
+ // Only change the name of the original if new annotations have been created
+ if (newAnnotations.length !== 0) {
+ annotationQuery.name = `${annotationQuery.name} - ${annotationQuery.statistic}`;
+ }
}
delete annotationQuery.statistics;
}
diff --git a/public/app/plugins/panel/annolist/AnnoListPanel.test.tsx b/public/app/plugins/panel/annolist/AnnoListPanel.test.tsx
index 1c9dbd45abc..8ad01c6427c 100644
--- a/public/app/plugins/panel/annolist/AnnoListPanel.test.tsx
+++ b/public/app/plugins/panel/annolist/AnnoListPanel.test.tsx
@@ -105,7 +105,7 @@ describe('AnnoListPanel', () => {
tags: ['tag A', 'tag B'],
type: 'annotation',
},
- 'anno-list-panel-1'
+ expect.stringMatching(/^anno-list-panel-\d\.\d+/) // string is appended with Math.random()
);
});
});
@@ -268,7 +268,7 @@ describe('AnnoListPanel', () => {
tags: ['tag A', 'tag B', 'Result tag B'],
type: 'annotation',
},
- 'anno-list-panel-1'
+ expect.stringMatching(/^anno-list-panel-\d\.\d+/) // string is appended with Math.random()
);
expect(screen.getByText(/filter:/i)).toBeInTheDocument();
expect(screen.getAllByText(/result tag b/i)).toHaveLength(2);
@@ -293,7 +293,7 @@ describe('AnnoListPanel', () => {
type: 'annotation',
userId: 1,
},
- 'anno-list-panel-1'
+ expect.stringMatching(/^anno-list-panel-\d\.\d+/) // string is appended with Math.random()
);
expect(screen.getByText(/filter:/i)).toBeInTheDocument();
expect(screen.getByRole('button', { name: /result email/i })).toBeInTheDocument();
diff --git a/public/app/plugins/panel/annolist/AnnoListPanel.tsx b/public/app/plugins/panel/annolist/AnnoListPanel.tsx
index 744f905e483..69c21cebdb1 100644
--- a/public/app/plugins/panel/annolist/AnnoListPanel.tsx
+++ b/public/app/plugins/panel/annolist/AnnoListPanel.tsx
@@ -7,7 +7,7 @@ import {
AnnotationEvent,
AppEvents,
dateTime,
- DurationUnit,
+ dateMath,
GrafanaTheme2,
locationUtil,
PanelProps,
@@ -35,6 +35,7 @@ interface State {
loaded: boolean;
queryUser?: UserInfo;
queryTags: string[];
+ requestId: string;
}
export class AnnoListPanel extends PureComponent {
style = getStyles(config.theme2);
@@ -49,6 +50,7 @@ export class AnnoListPanel extends PureComponent {
timeInfo: '',
loaded: false,
queryTags: [],
+ requestId: `anno-list-panel-${Math.random()}`,
};
}
@@ -126,7 +128,7 @@ export class AnnoListPanel extends PureComponent {
params.tags = params.tags ? [...params.tags, ...queryTags] : queryTags;
}
- const annotations = await getBackendSrv().get('/api/annotations', params, `anno-list-panel-${this.props.id}`);
+ const annotations = await getBackendSrv().get('/api/annotations', params, this.state.requestId);
this.setState({
annotations,
@@ -180,7 +182,12 @@ export class AnnoListPanel extends PureComponent {
if (subtract) {
incr *= -1;
}
- return t.add(incr, unit as DurationUnit).valueOf();
+
+ if (!dateMath.isDurationUnit(unit)) {
+ return 0;
+ }
+
+ return t.add(incr, unit).valueOf();
}
onTagClick = (tag: string, remove?: boolean) => {
diff --git a/public/app/plugins/panel/dashlist/DashList.test.tsx b/public/app/plugins/panel/dashlist/DashList.test.tsx
new file mode 100644
index 00000000000..d1febc53817
--- /dev/null
+++ b/public/app/plugins/panel/dashlist/DashList.test.tsx
@@ -0,0 +1,128 @@
+import { render, screen } from 'test/test-utils';
+
+import { setBackendSrv } from '@grafana/runtime';
+import { setupMockServer } from '@grafana/test-utils/server';
+import { getFolderFixtures } from '@grafana/test-utils/unstable';
+import { backendSrv } from 'app/core/services/backend_srv';
+import impressionSrv from 'app/core/services/impression_srv';
+import { testWithFeatureToggles } from 'app/features/alerting/unified/test/test-utils';
+
+import { getPanelProps } from '../test-utils';
+
+import { DashList } from './DashList';
+import { Options } from './panelcfg.gen';
+
+const [_, { folderA, folderA_dashbdD, dashbdE }] = getFolderFixtures();
+
+setBackendSrv(backendSrv);
+setupMockServer();
+
+const defaultOptions: Options = {
+ includeVars: false,
+ keepTime: false,
+ maxItems: 10,
+ query: '*',
+ showFolderNames: false,
+ showHeadings: false,
+ showRecentlyViewed: false,
+ showSearch: false,
+ showStarred: false,
+ tags: [],
+};
+
+const findStarButton = (title: string, isStarred: boolean) =>
+ screen.findByRole('button', { name: new RegExp(`^${isStarred ? 'unmark' : 'mark'} "${title}" as favorite`, 'i') });
+
+describe.each([
+ // App platform APIs
+ true,
+ // Legacy APIs
+ false,
+])('DashList - app platform APIs: %s', (featureTogglesEnabled) => {
+ testWithFeatureToggles(featureTogglesEnabled ? ['unifiedStorageSearchUI'] : []);
+
+ it('renders different groups of dashboards', async () => {
+ const props = getPanelProps({
+ ...defaultOptions,
+ showHeadings: true,
+ showRecentlyViewed: true,
+ showStarred: true,
+ showSearch: true,
+ });
+ render();
+
+ const headings = (await screen.findAllByRole('heading')).map((heading) => heading.textContent);
+ expect(headings).toEqual(['Starred dashboards', 'Recently viewed dashboards', 'Search']);
+ });
+
+ it('renders folder names', async () => {
+ const props = getPanelProps({ ...defaultOptions, showStarred: true, showFolderNames: true });
+ render();
+
+ // Based on the fixtures, we expect to see a dashboard that's contained in folderA
+ const [folderTitle] = await screen.findAllByText(folderA.item.title);
+ expect(folderTitle).toBeInTheDocument();
+ });
+
+ it('renders empty state', async () => {
+ const props = getPanelProps({
+ ...defaultOptions,
+ showStarred: false,
+ showRecentlyViewed: false,
+ showSearch: false,
+ });
+ render();
+
+ expect(await screen.findByText('No dashboard groups configured')).toBeInTheDocument();
+ });
+
+ it('allows un-starring a dashboard', async () => {
+ const props = getPanelProps({
+ ...defaultOptions,
+ showStarred: true,
+ });
+ const { user } = render(, {
+ preloadedState: { navIndex: { starred: { text: 'Starred', children: [] } } },
+ });
+
+ const starButton = await findStarButton(folderA_dashbdD.item.title, true);
+
+ await user.click(starButton);
+
+ expect(screen.queryByText(folderA_dashbdD.item.title)).not.toBeInTheDocument();
+ });
+
+ it('allows starring a dashboard', async () => {
+ const props = getPanelProps({
+ ...defaultOptions,
+ showStarred: true,
+ showSearch: true,
+ });
+
+ const { user } = render(, {
+ preloadedState: { navIndex: { starred: { text: 'Starred', children: [] } } },
+ });
+
+ const starButton = await findStarButton(dashbdE.item.title, false);
+
+ await user.click(starButton);
+
+ // We use `findAll` because the dashboard will appear in two sections (starred and search)
+ // but this is fine, because there will have been none before starring it
+ const [unmarkButton] = await screen.findAllByRole('button', {
+ name: new RegExp(`^unmark "${dashbdE.item.title}" as favorite`, 'i'),
+ });
+ expect(unmarkButton).toBeInTheDocument();
+ });
+
+ it('shows recently viewed dashboards', async () => {
+ impressionSrv.addDashboardImpression(dashbdE.item.uid);
+ const props = getPanelProps({
+ ...defaultOptions,
+ showRecentlyViewed: true,
+ });
+ render();
+
+ expect(await screen.findByText(dashbdE.item.title)).toBeInTheDocument();
+ });
+});
diff --git a/public/app/plugins/panel/dashlist/DashList.tsx b/public/app/plugins/panel/dashlist/DashList.tsx
index d997bcb36a6..76ee1497a9e 100644
--- a/public/app/plugins/panel/dashlist/DashList.tsx
+++ b/public/app/plugins/panel/dashlist/DashList.tsx
@@ -3,16 +3,16 @@ import { SyntheticEvent, useEffect, useMemo, useState } from 'react';
import { useThrottle } from 'react-use';
import { InterpolateFunction, PanelProps, textUtil } from '@grafana/data';
+import { t } from '@grafana/i18n';
import { config } from '@grafana/runtime';
-import { useStyles2, IconButton, ScrollContainer } from '@grafana/ui';
-import { updateNavIndex } from 'app/core/actions';
+import { useStyles2, IconButton, ScrollContainer, Box, Text, EmptyState, Link } from '@grafana/ui';
import { getConfig } from 'app/core/config';
import { ID_PREFIX, setStarred } from 'app/core/reducers/navBarTree';
-import { removeNavIndex } from 'app/core/reducers/navModel';
-import { getBackendSrv } from 'app/core/services/backend_srv';
+import { removeNavIndex, updateNavIndex } from 'app/core/reducers/navModel';
import impressionSrv from 'app/core/services/impression_srv';
import { getDashboardSrv } from 'app/features/dashboard/services/DashboardSrv';
-import { DashboardSearchItem } from 'app/features/search/types';
+import { getGrafanaSearcher } from 'app/features/search/service/searcher';
+import { DashboardQueryResult, LocationInfo, QueryResponse, SearchQuery } from 'app/features/search/service/types';
import { StarToolbarButtonApiServer } from 'app/features/stars/StarToolbarButton';
import { useDispatch, useSelector } from 'app/types/store';
@@ -20,7 +20,11 @@ import { Options } from './panelcfg.gen';
import { getStyles } from './styles';
import { useDashListUrlParams } from './utils';
-type Dashboard = DashboardSearchItem & { id?: number; isSearchResult?: boolean; isRecent?: boolean };
+type Dashboard = DashboardQueryResult & {
+ isSearchResult?: boolean;
+ isRecent?: boolean;
+ isStarred?: boolean;
+};
interface DashboardGroup {
show: boolean;
@@ -29,73 +33,94 @@ interface DashboardGroup {
}
async function fetchDashboards(options: Options, replaceVars: InterpolateFunction) {
- let starredDashboards: Promise = Promise.resolve([]);
+ const searcher = getGrafanaSearcher();
+ let starredDashboards: Promise = Promise.resolve();
+ let recentDashboards: Promise = Promise.resolve();
+ let searchedDashboards: Promise = Promise.resolve();
if (options.showStarred) {
- const params = { limit: options.maxItems, starred: 'true' };
- starredDashboards = getBackendSrv().search(params);
+ const params: SearchQuery = { limit: options.maxItems, starred: true };
+ starredDashboards = searcher.starred(params);
}
- let recentDashboards: Promise = Promise.resolve([]);
let dashUIDs: string[] = [];
if (options.showRecentlyViewed) {
let uids = await impressionSrv.getDashboardOpened();
dashUIDs = take(uids, options.maxItems);
- recentDashboards = getBackendSrv().search({ dashboardUIDs: dashUIDs, limit: options.maxItems });
+
+ recentDashboards = searcher.search({ uid: dashUIDs, limit: options.maxItems, kind: ['dashboard'] });
}
- let searchedDashboards: Promise = Promise.resolve([]);
if (options.showSearch) {
const uid = options.folderUID === '' ? 'general' : options.folderUID;
- const params = {
+ const params: SearchQuery = {
limit: options.maxItems,
query: replaceVars(options.query, {}, 'text'),
- folderUIDs: uid,
- tag: options.tags.map((tag: string) => replaceVars(tag, {}, 'text')),
- type: 'dash-db',
+ location: uid,
+ tags: options.tags.map((tag: string) => replaceVars(tag, {}, 'text')),
+ kind: ['dashboard'],
};
- searchedDashboards = getBackendSrv().search(params);
+ searchedDashboards = searcher.search(params);
}
- const [starred, searched, recent] = await Promise.all([starredDashboards, searchedDashboards, recentDashboards]);
+ const [starred, searched, recent] = await Promise.allSettled([
+ starredDashboards,
+ searchedDashboards,
+ recentDashboards,
+ ]);
// We deliberately deal with recent dashboards first so that the order of dash IDs is preserved
- let dashMap = new Map();
- for (const dashUID of dashUIDs) {
- const dash = recent.find((d) => d.uid === dashUID);
- if (dash) {
- dashMap.set(dashUID, { ...dash, isRecent: true });
+ let dashMap = new Map();
+ if (recent && recent.status === 'fulfilled') {
+ for (const dashUID of dashUIDs) {
+ const dash = recent.value?.view.find((d: DashboardQueryResult): d is DashboardQueryResult => {
+ return d.uid === dashUID;
+ });
+ if (dash) {
+ dashMap.set(dashUID, { ...dash, title: dash.name, isRecent: true });
+ }
}
}
- searched.forEach((dash) => {
- if (!dash.uid) {
- return;
- }
- if (dashMap.has(dash.uid)) {
- dashMap.get(dash.uid)!.isSearchResult = true;
- } else {
- dashMap.set(dash.uid, { ...dash, isSearchResult: true });
- }
- });
+ if (searched && searched.status === 'fulfilled') {
+ searched?.value?.view.forEach((dash) => {
+ if (!dash.uid) {
+ return;
+ }
+ if (dashMap.has(dash.uid)) {
+ dashMap.get(dash.uid)!.isSearchResult = true;
+ } else {
+ dashMap.set(dash.uid, { ...dash, isSearchResult: true });
+ }
+ });
+ }
- starred.forEach((dash) => {
- if (!dash.uid) {
- return;
- }
- if (dashMap.has(dash.uid)) {
- dashMap.get(dash.uid)!.isStarred = true;
- } else {
- dashMap.set(dash.uid, { ...dash, isStarred: true });
- }
- });
+ if (starred && starred.status === 'fulfilled') {
+ starred?.value?.view.forEach((dash) => {
+ if (!dash.uid) {
+ return;
+ }
+ if (dashMap.has(dash.uid)) {
+ dashMap.get(dash.uid)!.isStarred = true;
+ } else {
+ dashMap.set(dash.uid, { ...dash, isStarred: true });
+ }
+ });
+ }
return dashMap;
}
+async function fetchDashboardFolders() {
+ return getGrafanaSearcher().getLocationInfo();
+}
+
+const collator = new Intl.Collator();
+
export function DashList(props: PanelProps) {
const [dashboards, setDashboards] = useState(new Map());
+ const [foldersTitleMap, setFoldersTitleMap] = useState>({});
const dispatch = useDispatch();
const navIndex = useSelector((state) => state.navIndex);
@@ -107,22 +132,30 @@ export function DashList(props: PanelProps) {
});
}, [props.options, props.replaceVariables, throttledRenderCount]);
+ useEffect(() => {
+ if (props.options.showFolderNames && dashboards.size > 0) {
+ fetchDashboardFolders().then((locationInfo) => {
+ setFoldersTitleMap(locationInfo);
+ });
+ }
+ }, [props.options.showFolderNames, dashboards]);
+
const toggleDashboardStar = async (e: SyntheticEvent, dash: Dashboard) => {
- const { uid, title, url } = dash;
+ const { uid, name, url } = dash;
e.preventDefault();
e.stopPropagation();
- const isStarred = await getDashboardSrv().starDashboard(dash.uid, dash.isStarred);
+ const isStarred = await getDashboardSrv().starDashboard(dash.uid, Boolean(dash.isStarred));
const updatedDashboards = new Map(dashboards);
updatedDashboards.set(dash?.uid ?? '', { ...dash, isStarred });
setDashboards(updatedDashboards);
- dispatch(setStarred({ id: uid ?? '', title, url, isStarred }));
+ dispatch(setStarred({ id: uid ?? '', title: name, url, isStarred }));
- const starredNavItem = navIndex['starred'];
+ const starredNavItem = navIndex.starred;
if (isStarred) {
starredNavItem.children?.push({
id: ID_PREFIX + uid,
- text: title,
+ text: name,
url: url ?? '',
parentItem: starredNavItem,
});
@@ -138,10 +171,27 @@ export function DashList(props: PanelProps) {
const [starredDashboards, recentDashboards, searchedDashboards] = useMemo(() => {
const dashboardList = [...dashboards.values()];
+ const dashboardsGroupsMap: Record = {
+ starred: [],
+ recent: [],
+ searched: [],
+ };
+
+ for (const dash of dashboardList) {
+ if (dash.isStarred) {
+ dashboardsGroupsMap.starred.push(dash);
+ }
+ if (dash.isRecent) {
+ dashboardsGroupsMap.recent.push(dash);
+ }
+ if (dash.isSearchResult) {
+ dashboardsGroupsMap.searched.push(dash);
+ }
+ }
return [
- dashboardList.filter((dash) => dash.isStarred).sort((a, b) => a.title.localeCompare(b.title)),
- dashboardList.filter((dash) => dash.isRecent),
- dashboardList.filter((dash) => dash.isSearchResult).sort((a, b) => a.title.localeCompare(b.title)),
+ dashboardsGroupsMap.starred.sort((a, b) => collator.compare(a.name, b.name)),
+ dashboardsGroupsMap.recent,
+ dashboardsGroupsMap.searched.sort((a, b) => collator.compare(a.name, b.name)),
];
}, [dashboards]);
@@ -149,17 +199,17 @@ export function DashList(props: PanelProps) {
const dashboardGroups: DashboardGroup[] = [
{
- header: 'Starred dashboards',
+ header: t('panel.dashlist.starred-dashboards', 'Starred dashboards'),
dashboards: starredDashboards,
show: showStarred,
},
{
- header: 'Recently viewed dashboards',
+ header: t('panel.dashlist.recently-viewed-dashboards', 'Recently viewed dashboards'),
dashboards: recentDashboards,
show: showRecentlyViewed,
},
{
- header: 'Search',
+ header: t('panel.dashlist.search', 'Search'),
dashboards: searchedDashboards,
show: showSearch,
},
@@ -173,21 +223,30 @@ export function DashList(props: PanelProps) {
{dashboards.map((dash) => {
let url = dash.url + urlParams;
url = getConfig().disableSanitizeHtml ? url : textUtil.sanitizeUrl(url);
+ const markAsStarredText = t('panel.dashlist.mark-as-starred', 'Mark "{{title}}" as favorite', {
+ title: dash.title,
+ });
+ const unmarkAsStarredText = t('panel.dashlist.unmark-as-starred', 'Unmark "{{title}}" as favorite', {
+ title: dash.title,
+ });
+ const locationInfo = showFolderNames && dash.location ? foldersTitleMap[dash.location] : undefined;
return (
-
+
-
-
- {dash.title}
-
- {showFolderNames && dash.folderTitle &&
{dash.folderTitle}
}
-
+
+ {dash.name}
+ {showFolderNames && locationInfo && (
+
+ {locationInfo?.name}
+
+ )}
+
{config.featureToggles.starsFromAPIServer ? (
) : (
toggleDashboardStar(e, dash)}
@@ -200,15 +259,30 @@ export function DashList(props: PanelProps) {
);
+ const showEmptyState = dashboardGroups.every(({ show }) => !show);
+
return (
+ {showEmptyState && (
+
+ )}
{dashboardGroups.map(
({ show, header, dashboards }, i) =>
show && (
-
- {showHeadings &&
{header}
}
+
+ {showHeadings && (
+
+
+ {header}
+
+
+ )}
{renderList(dashboards)}
-
+
)
)}
diff --git a/public/app/plugins/panel/dashlist/styles.ts b/public/app/plugins/panel/dashlist/styles.ts
index 8d482d09960..56becdd0684 100644
--- a/public/app/plugins/panel/dashlist/styles.ts
+++ b/public/app/plugins/panel/dashlist/styles.ts
@@ -4,14 +4,6 @@ import { GrafanaTheme2 } from '@grafana/data';
export const getStyles = (theme: GrafanaTheme2) => {
return {
- dashlistSectionHeader: css({
- padding: theme.spacing(0.25, 1),
- marginRight: theme.spacing(1),
- }),
- dashlistSection: css({
- marginBottom: theme.spacing(2),
- paddingTop: theme.spacing(0.5),
- }),
dashlistLink: css({
display: 'flex',
cursor: 'pointer',
@@ -27,27 +19,5 @@ export const getStyles = (theme: GrafanaTheme2) => {
},
},
}),
- dashlistFolder: css({
- color: theme.colors.text.secondary,
- fontSize: theme.typography.bodySmall.fontSize,
- lineHeight: theme.typography.body.lineHeight,
- }),
- dashlistTitle: css({
- '&::after': {
- position: 'absolute',
- content: '""',
- left: 0,
- top: 0,
- bottom: 0,
- right: 0,
- },
- }),
- dashlistLinkBody: css({
- flexGrow: 1,
- }),
- dashlistItem: css({
- position: 'relative',
- listStyle: 'none',
- }),
};
};
diff --git a/public/app/plugins/panel/logs/LogsPanel.tsx b/public/app/plugins/panel/logs/LogsPanel.tsx
index 80bedeef841..ac03ed51932 100644
--- a/public/app/plugins/panel/logs/LogsPanel.tsx
+++ b/public/app/plugins/panel/logs/LogsPanel.tsx
@@ -674,6 +674,7 @@ export const LogsPanel = ({
logRowMenuIconsAfter={isReactNodeArray(logRowMenuIconsAfter) ? logRowMenuIconsAfter : undefined}
// Ascending order causes scroll to stick to the bottom, so previewing is futile
renderPreview={isAscending ? false : true}
+ timeRange={data.timeRange}
/>
{showCommonLabels && isAscending && renderCommonLabels()}
@@ -727,6 +728,7 @@ export const LogsPanel = ({
logOptionsStorageKey={controlsStorageKey}
// Ascending order causes scroll to stick to the bottom, so previewing is futile
renderPreview={isAscending ? false : true}
+ timeRange={data.timeRange}
/>
{showCommonLabels && isAscending && renderCommonLabels()}
diff --git a/public/app/plugins/panel/test-utils.ts b/public/app/plugins/panel/test-utils.ts
new file mode 100644
index 00000000000..ca6ac854fcf
--- /dev/null
+++ b/public/app/plugins/panel/test-utils.ts
@@ -0,0 +1,30 @@
+import { PanelProps, LoadingState, getDefaultTimeRange, FieldConfigSource } from '@grafana/data';
+import { getAppEvents } from '@grafana/runtime';
+
+/**
+ * Get mock panel props for test purposes
+ */
+export const getPanelProps = (
+ defaultOptions: T,
+ panelPropsOverrides?: Partial, 'options'>>
+): PanelProps => {
+ return {
+ id: 1,
+ data: { state: LoadingState.Done, series: [], timeRange: getDefaultTimeRange() },
+ options: defaultOptions,
+ eventBus: getAppEvents(),
+ fieldConfig: {} as unknown as FieldConfigSource,
+ height: 400,
+ onChangeTimeRange: jest.fn(),
+ onFieldConfigChange: jest.fn(),
+ onOptionsChange: jest.fn(),
+ replaceVariables: jest.fn(),
+ renderCounter: 1,
+ timeRange: getDefaultTimeRange(),
+ timeZone: 'utc',
+ title: 'DashList test title',
+ transparent: false,
+ width: 320,
+ ...panelPropsOverrides,
+ };
+};
diff --git a/public/locales/cs-CZ/grafana.json b/public/locales/cs-CZ/grafana.json
index 6e8962abf59..a5b30c2d737 100644
--- a/public/locales/cs-CZ/grafana.json
+++ b/public/locales/cs-CZ/grafana.json
@@ -1931,9 +1931,6 @@
"title-remove": "Odebrat",
"tooltip-remove-time-range": "Odebrat časový rozsah"
},
- "namespace": {
- "title-alert-rules": "Pravidla výstrah"
- },
"namespace-and-group-filter": {
"select-group": "Vybrat skupinu",
"select-namespace": "Vyberte jmenný prostor"
@@ -2051,7 +2048,9 @@
"recipient-notification-fires": "Vyberte, kdo by měl obdržet oznámení při spuštění pravidla výstrahy."
},
"option-customfield": {
- "label-custom-template": "Vlastní šablona"
+ "label-custom-template": "Vlastní šablona",
+ "placeholder": "",
+ "placeholder-with-template": ""
},
"other-alert-managers-available": {
"body-selected-alertmanager-not-found": "Vybraný správce výstrah již neexistuje nebo nemáte potřebná oprávnění. Vyberte jiného správce výstrah z rozevíracího seznamu.",
@@ -5392,7 +5391,6 @@
"json": "Exportovat jako JSON"
}
},
- "mark-favorite": "Označit jako oblíbené",
"more-save-options": "Další možnosti uložení",
"playlist-next": "Přejít na další nástěnku",
"playlist-previous": "Přejít na předchozí nástěnku",
@@ -5421,8 +5419,7 @@
"yesText": "Uložit"
}
},
- "unlink-library-panel": "Odpojit panel knihovny",
- "unmark-favorite": "Zrušit označení jako oblíbené"
+ "unlink-library-panel": "Odpojit panel knihovny"
},
"open-original": "Otevřít původní nástěnku",
"playlist-next": "Přejít na další nástěnku",
@@ -5443,6 +5440,10 @@
"save-library-panel": "Uložit panel knihovny",
"settings": "Nastavení nástěnky",
"share-button": "Sdílet",
+ "star-add-error": "",
+ "star-added": "",
+ "star-remove-error": "",
+ "star-removed": "",
"unlink-library-panel": "Odpojit panel knihovny",
"unmark-favorite": "Odznačit z oblíbených"
},
diff --git a/public/locales/de-DE/grafana.json b/public/locales/de-DE/grafana.json
index 3a75a924c77..83a4aef9486 100644
--- a/public/locales/de-DE/grafana.json
+++ b/public/locales/de-DE/grafana.json
@@ -1919,9 +1919,6 @@
"title-remove": "Entfernen",
"tooltip-remove-time-range": "Zeitbereich entfernen"
},
- "namespace": {
- "title-alert-rules": "Warnregeln"
- },
"namespace-and-group-filter": {
"select-group": "Gruppe auswählen",
"select-namespace": "Namensraum auswählen"
@@ -2039,7 +2036,9 @@
"recipient-notification-fires": "Wählen Sie aus, wer eine Benachrichtigung erhalten soll, wenn eine Warnregel ausgelöst wird."
},
"option-customfield": {
- "label-custom-template": "Individuelle Vorlage"
+ "label-custom-template": "Individuelle Vorlage",
+ "placeholder": "",
+ "placeholder-with-template": ""
},
"other-alert-managers-available": {
"body-selected-alertmanager-not-found": "Der ausgewählte Alertmanager existiert nicht mehr oder Sie haben keine Berechtigung, darauf zuzugreifen. Sie können einen anderen Alertmanager aus der Dropdown-Liste auswählen.",
@@ -5350,7 +5349,6 @@
"json": "Als JSON exportieren"
}
},
- "mark-favorite": "Als Favorit markieren",
"more-save-options": "Weitere Speicheroptionen",
"playlist-next": "Zum nächsten Dashboard",
"playlist-previous": "Zum vorherigen Dashboard",
@@ -5379,8 +5377,7 @@
"yesText": "Speichern"
}
},
- "unlink-library-panel": "Verknüpfung mit der Bibliotheksleiste aufheben",
- "unmark-favorite": "Markierung als Favorit entfernen"
+ "unlink-library-panel": "Verknüpfung mit der Bibliotheksleiste aufheben"
},
"open-original": "Original-Dashboard öffnen",
"playlist-next": "Zum nächsten Dashboard",
@@ -5401,6 +5398,10 @@
"save-library-panel": "Bibliotheks-Panel speichern",
"settings": "Dashboard-Einstellungen",
"share-button": "Teilen",
+ "star-add-error": "",
+ "star-added": "",
+ "star-remove-error": "",
+ "star-removed": "",
"unlink-library-panel": "Verknüpfung mit der Bibliotheksleiste aufheben",
"unmark-favorite": "Markierung als Favorit entfernen"
},
diff --git a/public/locales/en-US/grafana.json b/public/locales/en-US/grafana.json
index 70c00740aa9..95d771db840 100644
--- a/public/locales/en-US/grafana.json
+++ b/public/locales/en-US/grafana.json
@@ -10651,6 +10651,14 @@
}
},
"panel": {
+ "dashlist": {
+ "empty-state-message": "No dashboard groups configured",
+ "mark-as-starred": "Mark \"{{title}}\" as favorite",
+ "recently-viewed-dashboards": "Recently viewed dashboards",
+ "search": "Search",
+ "starred-dashboards": "Starred dashboards",
+ "unmark-as-starred": "Unmark \"{{title}}\" as favorite"
+ },
"get-calculation-value-data-links-variable-suggestions": {
"value-calc-var": {
"label": {
@@ -11327,6 +11335,7 @@
"actions": {
"set-up-required-feature-toggles": "Set up required feature toggles"
},
+ "learn-more-documentation": "Want to learn more? See our <2>documentation2>.",
"manage-dashboards-provision-updates-automatically": "Manage dashboards as code in Git and provision updates automatically",
"manage-your-dashboards-with-remote-provisioning": "Get started with Git Sync",
"store-dashboards-in-version-controlled-storage": "Store dashboards in version-controlled storage for better organization and history tracking"
diff --git a/public/locales/es-ES/grafana.json b/public/locales/es-ES/grafana.json
index ea17b8d8414..aeff0bbc3b3 100644
--- a/public/locales/es-ES/grafana.json
+++ b/public/locales/es-ES/grafana.json
@@ -1919,9 +1919,6 @@
"title-remove": "Eliminar",
"tooltip-remove-time-range": "Quitar rango de tiempo"
},
- "namespace": {
- "title-alert-rules": "Reglas de alerta"
- },
"namespace-and-group-filter": {
"select-group": "Seleccionar grupo",
"select-namespace": "Seleccionar espacio de nombres"
@@ -2039,7 +2036,9 @@
"recipient-notification-fires": "Selecciona quién debe recibir una notificación cuando se active una regla de alerta."
},
"option-customfield": {
- "label-custom-template": "Plantilla personalizada"
+ "label-custom-template": "Plantilla personalizada",
+ "placeholder": "",
+ "placeholder-with-template": ""
},
"other-alert-managers-available": {
"body-selected-alertmanager-not-found": "El Alertmanager seleccionado ya no existe o es posible que no tengas permiso para acceder a él. Puedes seleccionar otro Alertmanager en el menú desplegable.",
@@ -5350,7 +5349,6 @@
"json": "Exportar como JSON"
}
},
- "mark-favorite": "Marcar como favorito",
"more-save-options": "Más opciones de guardado",
"playlist-next": "Ir al siguiente panel de control",
"playlist-previous": "Ir al panel de control anterior",
@@ -5379,8 +5377,7 @@
"yesText": "Guardar"
}
},
- "unlink-library-panel": "Desvincular panel de librería",
- "unmark-favorite": "Deshacer marca como favorito"
+ "unlink-library-panel": "Desvincular panel de librería"
},
"open-original": "Abrir el panel de control original",
"playlist-next": "Ir al siguiente panel de control",
@@ -5401,6 +5398,10 @@
"save-library-panel": "Guardar panel de biblioteca",
"settings": "Ajustes del panel de control",
"share-button": "Compartir",
+ "star-add-error": "",
+ "star-added": "",
+ "star-remove-error": "",
+ "star-removed": "",
"unlink-library-panel": "Desvincular panel de librería",
"unmark-favorite": "Deshacer marca como favorito"
},
diff --git a/public/locales/fr-FR/grafana.json b/public/locales/fr-FR/grafana.json
index 7aa52d1737b..4789550f125 100644
--- a/public/locales/fr-FR/grafana.json
+++ b/public/locales/fr-FR/grafana.json
@@ -1919,9 +1919,6 @@
"title-remove": "Supprimer",
"tooltip-remove-time-range": "Supprimer la plage temporelle"
},
- "namespace": {
- "title-alert-rules": "Règles d'alerte"
- },
"namespace-and-group-filter": {
"select-group": "Sélectionner un groupe",
"select-namespace": "Sélectionner le namespace"
@@ -2039,7 +2036,9 @@
"recipient-notification-fires": "Sélectionnez qui doit recevoir une notification lorsqu’une règle d’alerte se déclenche."
},
"option-customfield": {
- "label-custom-template": "Personnaliser le modèle"
+ "label-custom-template": "Personnaliser le modèle",
+ "placeholder": "",
+ "placeholder-with-template": ""
},
"other-alert-managers-available": {
"body-selected-alertmanager-not-found": "L’Alertmanager sélectionné n’existe plus ou vous n’avez peut-être pas l’autorisation d’y accéder. Vous pouvez sélectionner un autre Alertmanager dans la liste déroulante.",
@@ -5350,7 +5349,6 @@
"json": "Exporter en tant que JSON"
}
},
- "mark-favorite": "Marquer comme favori",
"more-save-options": "Plus d’options d’enregistrement",
"playlist-next": "Accéder au tableau de bord suivant",
"playlist-previous": "Accéder au tableau de bord précédent",
@@ -5379,8 +5377,7 @@
"yesText": "Enregistrer"
}
},
- "unlink-library-panel": "Dissocier le panneau Bibliothèque",
- "unmark-favorite": "Supprimer des favoris"
+ "unlink-library-panel": "Dissocier le panneau Bibliothèque"
},
"open-original": "Ouvrir le tableau de bord d'origine",
"playlist-next": "Accéder au tableau de bord suivant",
@@ -5401,6 +5398,10 @@
"save-library-panel": "Enregistrer le panneau de la bibliothèque",
"settings": "Paramètres du tableau de bord",
"share-button": "Partager",
+ "star-add-error": "",
+ "star-added": "",
+ "star-remove-error": "",
+ "star-removed": "",
"unlink-library-panel": "Dissocier le panneau de la bibliothèque",
"unmark-favorite": "Supprimer des favoris"
},
diff --git a/public/locales/hu-HU/grafana.json b/public/locales/hu-HU/grafana.json
index 1f9b033ce8a..08c0b65f753 100644
--- a/public/locales/hu-HU/grafana.json
+++ b/public/locales/hu-HU/grafana.json
@@ -1919,9 +1919,6 @@
"title-remove": "Eltávolítás",
"tooltip-remove-time-range": "Időtartomány eltávolítása"
},
- "namespace": {
- "title-alert-rules": "Riasztási szabályok"
- },
"namespace-and-group-filter": {
"select-group": "Csoport kijelölése",
"select-namespace": "Névtér kijelölése"
@@ -2039,7 +2036,9 @@
"recipient-notification-fires": "Válassza ki, hogy ki kapjon értesítést, amikor egy riasztási szabály aktiválódik."
},
"option-customfield": {
- "label-custom-template": "Egyéni sablon"
+ "label-custom-template": "Egyéni sablon",
+ "placeholder": "",
+ "placeholder-with-template": ""
},
"other-alert-managers-available": {
"body-selected-alertmanager-not-found": "A kijelölt riasztáskezelő már nem létezik, vagy előfordulhat, hogy nincs hozzáférési joga. A legördülő menüből választhat másik riasztáskezelőt.",
@@ -5350,7 +5349,6 @@
"json": "Exportálás JSON-fájlként"
}
},
- "mark-favorite": "Megjelölés kedvencként",
"more-save-options": "További mentési beállítások",
"playlist-next": "Tovább a következő irányítópulthoz",
"playlist-previous": "Tovább az előző irányítópulthoz",
@@ -5379,8 +5377,7 @@
"yesText": "Mentés"
}
},
- "unlink-library-panel": "Könyvtárpanel leválasztása",
- "unmark-favorite": "Kedvencnek jelölés visszavonása"
+ "unlink-library-panel": "Könyvtárpanel leválasztása"
},
"open-original": "Eredeti irányítópult megnyitása",
"playlist-next": "Ugrás a következő irányítópulthoz",
@@ -5401,6 +5398,10 @@
"save-library-panel": "Könyvtárpanel mentése",
"settings": "Irányítópult beállításai",
"share-button": "Megosztás",
+ "star-add-error": "",
+ "star-added": "",
+ "star-remove-error": "",
+ "star-removed": "",
"unlink-library-panel": "Könyvtárpanel leválasztása",
"unmark-favorite": "Kedvencnek jelölés visszavonása"
},
diff --git a/public/locales/id-ID/grafana.json b/public/locales/id-ID/grafana.json
index 166a9fd5ccc..6d305d2dc28 100644
--- a/public/locales/id-ID/grafana.json
+++ b/public/locales/id-ID/grafana.json
@@ -1913,9 +1913,6 @@
"title-remove": "Hapus",
"tooltip-remove-time-range": "Hapus rentang waktu"
},
- "namespace": {
- "title-alert-rules": "Aturan peringatan"
- },
"namespace-and-group-filter": {
"select-group": "Pilih grup",
"select-namespace": "Pilih namespace"
@@ -2033,7 +2030,9 @@
"recipient-notification-fires": "Pilih siapa yang akan menerima pemberitahuan saat aturan peringatan menyala."
},
"option-customfield": {
- "label-custom-template": "Templat kustom"
+ "label-custom-template": "Templat kustom",
+ "placeholder": "",
+ "placeholder-with-template": ""
},
"other-alert-managers-available": {
"body-selected-alertmanager-not-found": "Alertmanager yang dipilih tidak ada lagi atau Anda mungkin tidak memiliki izin untuk mengaksesnya. Anda dapat memilih Alertmanager lain dari menu dropdown.",
@@ -5329,7 +5328,6 @@
"json": "Ekspor sebagai JSON"
}
},
- "mark-favorite": "Tandai sebagai favorit",
"more-save-options": "Opsi simpan lainnya",
"playlist-next": "Buka dasbor berikutnya",
"playlist-previous": "Buka dasbor sebelumnya",
@@ -5358,8 +5356,7 @@
"yesText": "Simpan"
}
},
- "unlink-library-panel": "Putus tautan panel pustaka",
- "unmark-favorite": "Batal tandai sebagai favorit"
+ "unlink-library-panel": "Putus tautan panel pustaka"
},
"open-original": "Buka dasbor asli",
"playlist-next": "Buka dasbor berikutnya",
@@ -5380,6 +5377,10 @@
"save-library-panel": "Simpan panel pustaka",
"settings": "Pengaturan dasbor",
"share-button": "Bagikan",
+ "star-add-error": "",
+ "star-added": "",
+ "star-remove-error": "",
+ "star-removed": "",
"unlink-library-panel": "Putuskan tautan panel pustaka",
"unmark-favorite": "Batal tanda sebagai favorit"
},
diff --git a/public/locales/it-IT/grafana.json b/public/locales/it-IT/grafana.json
index 6083613b82b..449f0d6ed08 100644
--- a/public/locales/it-IT/grafana.json
+++ b/public/locales/it-IT/grafana.json
@@ -1919,9 +1919,6 @@
"title-remove": "Rimuovi",
"tooltip-remove-time-range": "Rimuovi intervallo di tempo"
},
- "namespace": {
- "title-alert-rules": "Regole di avviso"
- },
"namespace-and-group-filter": {
"select-group": "Seleziona gruppo",
"select-namespace": "Seleziona spazio di nomi"
@@ -2039,7 +2036,9 @@
"recipient-notification-fires": "Seleziona chi deve ricevere una notifica quando viene attivata una regola di avviso."
},
"option-customfield": {
- "label-custom-template": "Modello personalizzato"
+ "label-custom-template": "Modello personalizzato",
+ "placeholder": "",
+ "placeholder-with-template": ""
},
"other-alert-managers-available": {
"body-selected-alertmanager-not-found": "L'Alertmanager selezionato non esiste più o potresti non avere l'autorizzazione per accedervi. È possibile selezionare un diverso Alertmanager dal menu a discesa.",
@@ -5350,7 +5349,6 @@
"json": "Esporta in formato JSON"
}
},
- "mark-favorite": "Contrassegna come preferito",
"more-save-options": "Altre opzioni di salvataggio",
"playlist-next": "Vai alla dashboard successiva",
"playlist-previous": "Vai alla dashboard precedente",
@@ -5379,8 +5377,7 @@
"yesText": "Salva"
}
},
- "unlink-library-panel": "Scollega pannello della libreria",
- "unmark-favorite": "Rimuovi dai preferiti"
+ "unlink-library-panel": "Scollega pannello della libreria"
},
"open-original": "Apri il originale",
"playlist-next": "Vai al dashboard successivo",
@@ -5401,6 +5398,10 @@
"save-library-panel": "Salva pannello della libreria",
"settings": "Impostazioni dashboard",
"share-button": "Condividi",
+ "star-add-error": "",
+ "star-added": "",
+ "star-remove-error": "",
+ "star-removed": "",
"unlink-library-panel": "Scollega pannello della libreria",
"unmark-favorite": "Rimuovi dai preferiti"
},
diff --git a/public/locales/ja-JP/grafana.json b/public/locales/ja-JP/grafana.json
index f86f2936033..9dec8395f9c 100644
--- a/public/locales/ja-JP/grafana.json
+++ b/public/locales/ja-JP/grafana.json
@@ -1913,9 +1913,6 @@
"title-remove": "削除",
"tooltip-remove-time-range": "時間範囲を削除"
},
- "namespace": {
- "title-alert-rules": "アラートルール"
- },
"namespace-and-group-filter": {
"select-group": "グループを選択",
"select-namespace": "名前空間を選択"
@@ -2033,7 +2030,9 @@
"recipient-notification-fires": "アラートルールの発生時に通知を受け取る相手を選択してください。"
},
"option-customfield": {
- "label-custom-template": "カスタムテンプレート"
+ "label-custom-template": "カスタムテンプレート",
+ "placeholder": "",
+ "placeholder-with-template": ""
},
"other-alert-managers-available": {
"body-selected-alertmanager-not-found": "選択したAlertmanagerは存在しないか、アクセス権限がない可能性があります。ドロップダウンから別のAlertmanagerを選択できます。",
@@ -5329,7 +5328,6 @@
"json": "JSON形式でエクスポート"
}
},
- "mark-favorite": "お気に入りに登録",
"more-save-options": "その他の保存オプション",
"playlist-next": "次のダッシュボードへ",
"playlist-previous": "前のダッシュボードへ",
@@ -5358,8 +5356,7 @@
"yesText": "保存"
}
},
- "unlink-library-panel": "ライブラリパネルのリンクを解除",
- "unmark-favorite": "お気に入りから削除"
+ "unlink-library-panel": "ライブラリパネルのリンクを解除"
},
"open-original": "元のダッシュボードを開く",
"playlist-next": "次のダッシュボードに移動",
@@ -5380,6 +5377,10 @@
"save-library-panel": "ライブラリパネルを保存",
"settings": "ダッシュボードの設定",
"share-button": "共有",
+ "star-add-error": "",
+ "star-added": "",
+ "star-remove-error": "",
+ "star-removed": "",
"unlink-library-panel": "ライブラリパネルのリンクを解除",
"unmark-favorite": "お気に入りを解除"
},
diff --git a/public/locales/ko-KR/grafana.json b/public/locales/ko-KR/grafana.json
index c183422000a..5a28fd8883c 100644
--- a/public/locales/ko-KR/grafana.json
+++ b/public/locales/ko-KR/grafana.json
@@ -1913,9 +1913,6 @@
"title-remove": "제거",
"tooltip-remove-time-range": "시간 범위 제거"
},
- "namespace": {
- "title-alert-rules": "경고 규칙"
- },
"namespace-and-group-filter": {
"select-group": "그룹 선택",
"select-namespace": "네임스페이스 선택"
@@ -2033,7 +2030,9 @@
"recipient-notification-fires": "경고 규칙이 발생될 때 알림을 받을 사람을 선택하세요."
},
"option-customfield": {
- "label-custom-template": "사용자 정의 템플릿"
+ "label-custom-template": "사용자 정의 템플릿",
+ "placeholder": "",
+ "placeholder-with-template": ""
},
"other-alert-managers-available": {
"body-selected-alertmanager-not-found": "선택하신 Alertmanager가 더 이상 존재하지 않거나 액세스 권한이 없습니다. 드롭다운에서 다른 Alertmanager를 선택할 수 있습니다.",
@@ -5329,7 +5328,6 @@
"json": "JSON으로 내보내기"
}
},
- "mark-favorite": "즐겨찾기로 표시",
"more-save-options": "저장 옵션 더 보기",
"playlist-next": "다음 대시보드로 이동",
"playlist-previous": "이전 대시보드로 이동",
@@ -5358,8 +5356,7 @@
"yesText": "저장"
}
},
- "unlink-library-panel": "라이브러리 패널 연결 해제",
- "unmark-favorite": "즐겨찾기 표시 취소"
+ "unlink-library-panel": "라이브러리 패널 연결 해제"
},
"open-original": "원래 대시보드 열기",
"playlist-next": "다음 대시보드로 이동",
@@ -5380,6 +5377,10 @@
"save-library-panel": "라이브러리 패널 저장",
"settings": "대시보드 설정",
"share-button": "공유",
+ "star-add-error": "",
+ "star-added": "",
+ "star-remove-error": "",
+ "star-removed": "",
"unlink-library-panel": "라이브러리 패널 연결 해제",
"unmark-favorite": "즐겨찾기 표시 취소"
},
diff --git a/public/locales/nl-NL/grafana.json b/public/locales/nl-NL/grafana.json
index e03f2982cdb..9a93d720c09 100644
--- a/public/locales/nl-NL/grafana.json
+++ b/public/locales/nl-NL/grafana.json
@@ -1919,9 +1919,6 @@
"title-remove": "Verwijderen",
"tooltip-remove-time-range": "Tijdsbereik verwijderen"
},
- "namespace": {
- "title-alert-rules": "Waarschuwingsregels"
- },
"namespace-and-group-filter": {
"select-group": "Groep selecteren",
"select-namespace": "Namespace selecteren"
@@ -2039,7 +2036,9 @@
"recipient-notification-fires": "Selecteer wie een melding moet ontvangen wanneer een waarschuwingsregel geactiveerd wordt."
},
"option-customfield": {
- "label-custom-template": "Aangepast sjabloon"
+ "label-custom-template": "Aangepast sjabloon",
+ "placeholder": "",
+ "placeholder-with-template": ""
},
"other-alert-managers-available": {
"body-selected-alertmanager-not-found": "De geselecteerde waarschuwingsmanager bestaat niet meer of je hebt mogelijk geen toestemming om deze te openen. Je kunt een andere waarschuwingsmanager selecteren in de vervolgkeuzelijst.",
@@ -5350,7 +5349,6 @@
"json": "Exporteren als JSON"
}
},
- "mark-favorite": "Markeren als favoriet",
"more-save-options": "Meer opties voor opslaan",
"playlist-next": "Naar het volgende dashboard",
"playlist-previous": "Naar het vorige dashboard",
@@ -5379,8 +5377,7 @@
"yesText": "Opslaan"
}
},
- "unlink-library-panel": "Bibliotheekpaneel ontkoppelen",
- "unmark-favorite": "Markering als favoriet ongedaan maken"
+ "unlink-library-panel": "Bibliotheekpaneel ontkoppelen"
},
"open-original": "Origineel dashboard openen",
"playlist-next": "Naar het volgende dashboard",
@@ -5401,6 +5398,10 @@
"save-library-panel": "Bibliotheekpaneel",
"settings": "Dashboardinstellingen",
"share-button": "Delen",
+ "star-add-error": "",
+ "star-added": "",
+ "star-remove-error": "",
+ "star-removed": "",
"unlink-library-panel": "Bibliotheekpaneel ontkoppelen",
"unmark-favorite": "Markering als favoriet ongedaan maken"
},
diff --git a/public/locales/pl-PL/grafana.json b/public/locales/pl-PL/grafana.json
index 9fffbee13da..cbb9646f775 100644
--- a/public/locales/pl-PL/grafana.json
+++ b/public/locales/pl-PL/grafana.json
@@ -1931,9 +1931,6 @@
"title-remove": "Usuń",
"tooltip-remove-time-range": "Usuń zakres czasu"
},
- "namespace": {
- "title-alert-rules": "Reguły alertu"
- },
"namespace-and-group-filter": {
"select-group": "Wybierz grupę",
"select-namespace": "Wybierz przestrzeń nazw"
@@ -2051,7 +2048,9 @@
"recipient-notification-fires": "Wybierz, kto powinien otrzymywać powiadomienia o uruchomieniu reguły alertu."
},
"option-customfield": {
- "label-custom-template": "Szablon niestandardowy"
+ "label-custom-template": "Szablon niestandardowy",
+ "placeholder": "",
+ "placeholder-with-template": ""
},
"other-alert-managers-available": {
"body-selected-alertmanager-not-found": "Wybrany menedżer alertów już nie istnieje lub możesz nie mieć do niego dostępu. Możesz wybrać innego menedżera alertów z listy rozwijanej.",
@@ -5392,7 +5391,6 @@
"json": "Eksportowanie jako JSON"
}
},
- "mark-favorite": "Oznacz jako ulubione",
"more-save-options": "Więcej opcji zapisywania",
"playlist-next": "Przejdź do następnego pulpitu",
"playlist-previous": "Przejdź do poprzedniego pulpitu",
@@ -5421,8 +5419,7 @@
"yesText": "Zapisz"
}
},
- "unlink-library-panel": "Rozłącz panel biblioteki",
- "unmark-favorite": "Usuń z ulubionych"
+ "unlink-library-panel": "Rozłącz panel biblioteki"
},
"open-original": "Otwórz oryginalny pulpit",
"playlist-next": "Przejdź do następnego pulpitu",
@@ -5443,6 +5440,10 @@
"save-library-panel": "Zapisz panel biblioteki",
"settings": "Ustawienia panelu",
"share-button": "Udostępnij",
+ "star-add-error": "",
+ "star-added": "",
+ "star-remove-error": "",
+ "star-removed": "",
"unlink-library-panel": "Rozłącz panel biblioteki",
"unmark-favorite": "Usuń oznaczenie jako ulubione"
},
diff --git a/public/locales/pt-BR/grafana.json b/public/locales/pt-BR/grafana.json
index abdf70e7745..a7e59b477e2 100644
--- a/public/locales/pt-BR/grafana.json
+++ b/public/locales/pt-BR/grafana.json
@@ -1919,9 +1919,6 @@
"title-remove": "Remover",
"tooltip-remove-time-range": "Remover intervalo de tempo"
},
- "namespace": {
- "title-alert-rules": "Regras de alerta"
- },
"namespace-and-group-filter": {
"select-group": "Selecionar o grupo",
"select-namespace": "Selecionar nomenclatura "
@@ -2039,7 +2036,9 @@
"recipient-notification-fires": "Selecione quem deve receber uma notificação quando uma regra de alerta for acionada."
},
"option-customfield": {
- "label-custom-template": "Modelo personalizado"
+ "label-custom-template": "Modelo personalizado",
+ "placeholder": "",
+ "placeholder-with-template": ""
},
"other-alert-managers-available": {
"body-selected-alertmanager-not-found": "O Alertmanager selecionado não existe mais ou talvez você não tenha permissão para acessá-lo. Você pode selecionar um Alertmanager diferente no menu suspenso.",
@@ -5350,7 +5349,6 @@
"json": "Exportar como JSON"
}
},
- "mark-favorite": "Marcar como favorito",
"more-save-options": "Mais opções de salvamento",
"playlist-next": "Ir para o próximo painel de controle",
"playlist-previous": "Ir para o painel de controle anterior",
@@ -5379,8 +5377,7 @@
"yesText": "Salvar"
}
},
- "unlink-library-panel": "Desvincular painel de biblioteca",
- "unmark-favorite": "Desmarcar como favorito"
+ "unlink-library-panel": "Desvincular painel de biblioteca"
},
"open-original": "Abrir painel de controle original",
"playlist-next": "Ir para o próximo painel de controle",
@@ -5401,6 +5398,10 @@
"save-library-panel": "Salvar painel da biblioteca",
"settings": "Configurações do painel de controle",
"share-button": "Compartilhar",
+ "star-add-error": "",
+ "star-added": "",
+ "star-remove-error": "",
+ "star-removed": "",
"unlink-library-panel": "Desvincular painel de biblioteca",
"unmark-favorite": "Desmarcar como favorito"
},
diff --git a/public/locales/pt-PT/grafana.json b/public/locales/pt-PT/grafana.json
index 30afc4edf92..6e2f7af299e 100644
--- a/public/locales/pt-PT/grafana.json
+++ b/public/locales/pt-PT/grafana.json
@@ -1919,9 +1919,6 @@
"title-remove": "Remover",
"tooltip-remove-time-range": "Remover intervalo de tempo"
},
- "namespace": {
- "title-alert-rules": "Regras de alerta"
- },
"namespace-and-group-filter": {
"select-group": "Selecionar grupo",
"select-namespace": "Selecionar espaço de nome"
@@ -2039,7 +2036,9 @@
"recipient-notification-fires": "Selecionar quem deve receber uma notificação quando uma regra de alerta for acionada."
},
"option-customfield": {
- "label-custom-template": "Modelo personalizado"
+ "label-custom-template": "Modelo personalizado",
+ "placeholder": "",
+ "placeholder-with-template": ""
},
"other-alert-managers-available": {
"body-selected-alertmanager-not-found": "O Alertmanager selecionado já não existe ou poderá não ter permissão para aceder ao mesmo. Pode selecionar um Alertmanager diferente no menu suspenso.",
@@ -5350,7 +5349,6 @@
"json": "Exportar como JSON"
}
},
- "mark-favorite": "Marcar como favorito",
"more-save-options": "Mais opções de guardar",
"playlist-next": "Ir para o próximo painel de controlo",
"playlist-previous": "Ir para o painel de controlo anterior",
@@ -5379,8 +5377,7 @@
"yesText": "Guardar"
}
},
- "unlink-library-panel": "Desassociar painel de biblioteca",
- "unmark-favorite": "Desmarcar como favorito"
+ "unlink-library-panel": "Desassociar painel de biblioteca"
},
"open-original": "Abrir o painel de controlo original",
"playlist-next": "Ir para o próximo painel de controlo",
@@ -5401,6 +5398,10 @@
"save-library-panel": "Guardar painel de biblioteca",
"settings": "Definições do painel de controlo",
"share-button": "Partilhar",
+ "star-add-error": "",
+ "star-added": "",
+ "star-remove-error": "",
+ "star-removed": "",
"unlink-library-panel": "Desassociar painel de biblioteca",
"unmark-favorite": "Desmarcar como favorito"
},
diff --git a/public/locales/ru-RU/grafana.json b/public/locales/ru-RU/grafana.json
index 3824d675ded..3eb55c8bdee 100644
--- a/public/locales/ru-RU/grafana.json
+++ b/public/locales/ru-RU/grafana.json
@@ -1931,9 +1931,6 @@
"title-remove": "Удалить",
"tooltip-remove-time-range": "Удалить временной диапазон"
},
- "namespace": {
- "title-alert-rules": "Правила оповещения"
- },
"namespace-and-group-filter": {
"select-group": "Выбрать группу",
"select-namespace": "Выбрать пространство имен"
@@ -2051,7 +2048,9 @@
"recipient-notification-fires": "Выберите, кто должен получать уведомление при активации правила оповещения."
},
"option-customfield": {
- "label-custom-template": "Пользовательский шаблон"
+ "label-custom-template": "Пользовательский шаблон",
+ "placeholder": "",
+ "placeholder-with-template": ""
},
"other-alert-managers-available": {
"body-selected-alertmanager-not-found": "Выбранный обработчик оповещений Alertmanager больше не существует или у вас может не быть разрешения на доступ к нему. Вы можете выбрать другой обработчик оповещений из раскрывающегося списка.",
@@ -5392,7 +5391,6 @@
"json": "Экспорт в формате JSON"
}
},
- "mark-favorite": "Добавить в избранное",
"more-save-options": "Больше параметров сохранения",
"playlist-next": "Перейти к следующему дашборду",
"playlist-previous": "Перейти к предыдущему дашборду",
@@ -5421,8 +5419,7 @@
"yesText": "Сохранить"
}
},
- "unlink-library-panel": "Отсоединить панель библиотеки",
- "unmark-favorite": "Убрать из избранного"
+ "unlink-library-panel": "Отсоединить панель библиотеки"
},
"open-original": "Открыть исходный дашборд",
"playlist-next": "Перейти к следующему дашборду",
@@ -5443,6 +5440,10 @@
"save-library-panel": "Сохранить панель библиотеки",
"settings": "Параметры дашборда",
"share-button": "Общий доступ",
+ "star-add-error": "",
+ "star-added": "",
+ "star-remove-error": "",
+ "star-removed": "",
"unlink-library-panel": "Отсоединить панель библиотеки",
"unmark-favorite": "Убрать из избранного"
},
diff --git a/public/locales/sv-SE/grafana.json b/public/locales/sv-SE/grafana.json
index 7f44f59d58b..9a11f9f0380 100644
--- a/public/locales/sv-SE/grafana.json
+++ b/public/locales/sv-SE/grafana.json
@@ -1919,9 +1919,6 @@
"title-remove": "Ta bort",
"tooltip-remove-time-range": "Ta bort tidsintervall"
},
- "namespace": {
- "title-alert-rules": "Varningsregler"
- },
"namespace-and-group-filter": {
"select-group": "Markera grupp",
"select-namespace": "Välj namnutrymme"
@@ -2039,7 +2036,9 @@
"recipient-notification-fires": "Välj vem som ska få en avisering när en larmregel utlöses."
},
"option-customfield": {
- "label-custom-template": "Anpassad mall"
+ "label-custom-template": "Anpassad mall",
+ "placeholder": "",
+ "placeholder-with-template": ""
},
"other-alert-managers-available": {
"body-selected-alertmanager-not-found": "Vald Alertmanager finns inte längre eller så kanske du inte har behörighet att komma åt den. Du kan välja en annan larmhanterare i rullgardinsmenyn.",
@@ -5350,7 +5349,6 @@
"json": "Exportera som JSON"
}
},
- "mark-favorite": "Markera som favorit",
"more-save-options": "Fler sparalternativ",
"playlist-next": "Gå till nästa instrumentpanel",
"playlist-previous": "Gå till föregående instrumentpanel",
@@ -5379,8 +5377,7 @@
"yesText": "Spara"
}
},
- "unlink-library-panel": "Ta bort länk till bibliotekspanel",
- "unmark-favorite": "Avmarkera som favorit"
+ "unlink-library-panel": "Ta bort länk till bibliotekspanel"
},
"open-original": "Öppna ursprunglig instrumentpanel",
"playlist-next": "Gå till nästa instrumentpanel",
@@ -5401,6 +5398,10 @@
"save-library-panel": "Spara bibliotekspanel",
"settings": "Instrumentpanelens inställningar",
"share-button": "Dela",
+ "star-add-error": "",
+ "star-added": "",
+ "star-remove-error": "",
+ "star-removed": "",
"unlink-library-panel": "Ta bort länk till bibliotekspanel",
"unmark-favorite": "Avmarkera som favorit"
},
diff --git a/public/locales/tr-TR/grafana.json b/public/locales/tr-TR/grafana.json
index 73e7b427e1e..145f42308c5 100644
--- a/public/locales/tr-TR/grafana.json
+++ b/public/locales/tr-TR/grafana.json
@@ -1919,9 +1919,6 @@
"title-remove": "Kaldır",
"tooltip-remove-time-range": "Zaman aralığını kaldır"
},
- "namespace": {
- "title-alert-rules": "Uyarı kuralları"
- },
"namespace-and-group-filter": {
"select-group": "Grup seç",
"select-namespace": "Ad alanı seç"
@@ -2039,7 +2036,9 @@
"recipient-notification-fires": "Bir uyarı kuralı tetiklendiğinde bildirimi kimin alacağını seçin."
},
"option-customfield": {
- "label-custom-template": "Özel şablon"
+ "label-custom-template": "Özel şablon",
+ "placeholder": "",
+ "placeholder-with-template": ""
},
"other-alert-managers-available": {
"body-selected-alertmanager-not-found": "Seçilen Alertmanager artık mevcut değil veya erişim izniniz olmayabilir. Açılır menüden başka bir Alertmanager seçebilirsiniz.",
@@ -5350,7 +5349,6 @@
"json": "JSON olarak dışa aktar"
}
},
- "mark-favorite": "Favori olarak işaretle",
"more-save-options": "Diğer kaydetme seçenekleri",
"playlist-next": "Sonraki panoya git",
"playlist-previous": "Önceki panoya git",
@@ -5379,8 +5377,7 @@
"yesText": "Kaydet"
}
},
- "unlink-library-panel": "Kütüphane panelinin bağlantısını kaldır",
- "unmark-favorite": "Favorilerden kaldır"
+ "unlink-library-panel": "Kütüphane panelinin bağlantısını kaldır"
},
"open-original": "Orijinal panoyu aç",
"playlist-next": "Sonraki panoya git",
@@ -5401,6 +5398,10 @@
"save-library-panel": "Kütüphane panelini kaydet",
"settings": "Pano ayarları",
"share-button": "Paylaş",
+ "star-add-error": "",
+ "star-added": "",
+ "star-remove-error": "",
+ "star-removed": "",
"unlink-library-panel": "Kütüphane panelinin bağlantısını kaldır",
"unmark-favorite": "Favorilerden kaldır"
},
diff --git a/public/locales/zh-Hans/grafana.json b/public/locales/zh-Hans/grafana.json
index 2d361138eec..e92a03eb587 100644
--- a/public/locales/zh-Hans/grafana.json
+++ b/public/locales/zh-Hans/grafana.json
@@ -1913,9 +1913,6 @@
"title-remove": "删除",
"tooltip-remove-time-range": "移除时间范围"
},
- "namespace": {
- "title-alert-rules": "警报规则"
- },
"namespace-and-group-filter": {
"select-group": "选择组",
"select-namespace": "选择命名空间"
@@ -2033,7 +2030,9 @@
"recipient-notification-fires": "选择警报规则触发时应向谁发送通知。"
},
"option-customfield": {
- "label-custom-template": "自定义模板"
+ "label-custom-template": "自定义模板",
+ "placeholder": "",
+ "placeholder-with-template": ""
},
"other-alert-managers-available": {
"body-selected-alertmanager-not-found": "所选 Alertmanager 不再存在,或者您可能没有访问它的权限。您可以从下拉列表中选择其他 Alertmanager。",
@@ -5329,7 +5328,6 @@
"json": "导出为 JSON"
}
},
- "mark-favorite": "标记为收藏",
"more-save-options": "更多保存选项",
"playlist-next": "前往下一个仪表板",
"playlist-previous": "前往上一个仪表板",
@@ -5358,8 +5356,7 @@
"yesText": "保存"
}
},
- "unlink-library-panel": "取消链接库面板",
- "unmark-favorite": "取消标记为收藏"
+ "unlink-library-panel": "取消链接库面板"
},
"open-original": "打开原始仪表板",
"playlist-next": "前往下一个仪表板",
@@ -5380,6 +5377,10 @@
"save-library-panel": "保存库面板",
"settings": "仪表板设置",
"share-button": "分享",
+ "star-add-error": "",
+ "star-added": "",
+ "star-remove-error": "",
+ "star-removed": "",
"unlink-library-panel": "取消链接库面板",
"unmark-favorite": "取消标记为收藏"
},
diff --git a/public/locales/zh-Hant/grafana.json b/public/locales/zh-Hant/grafana.json
index ac6f2755950..90abf1e3117 100644
--- a/public/locales/zh-Hant/grafana.json
+++ b/public/locales/zh-Hant/grafana.json
@@ -1913,9 +1913,6 @@
"title-remove": "移除",
"tooltip-remove-time-range": "移除時間範圍"
},
- "namespace": {
- "title-alert-rules": "警報規則"
- },
"namespace-and-group-filter": {
"select-group": "選擇群組",
"select-namespace": "選擇命名空間"
@@ -2033,7 +2030,9 @@
"recipient-notification-fires": "選擇當警報規則觸發時應該收到通知的人。"
},
"option-customfield": {
- "label-custom-template": "自訂範本"
+ "label-custom-template": "自訂範本",
+ "placeholder": "",
+ "placeholder-with-template": ""
},
"other-alert-managers-available": {
"body-selected-alertmanager-not-found": "所選的 Alertmanager 不再存在,或者您可能沒有存取權限。您可以從下拉式選單中選擇其他的 Alertmanager。",
@@ -5329,7 +5328,6 @@
"json": "匯出為 JSON"
}
},
- "mark-favorite": "標記為「我的最愛」",
"more-save-options": "更多儲存選項",
"playlist-next": "前往下一個儀表板",
"playlist-previous": "前往上一個儀表板",
@@ -5358,8 +5356,7 @@
"yesText": "儲存"
}
},
- "unlink-library-panel": "取消連結資料庫面板",
- "unmark-favorite": "取消標記為「我的最愛」"
+ "unlink-library-panel": "取消連結資料庫面板"
},
"open-original": "開啟原始儀表板",
"playlist-next": "前往下一個儀表板",
@@ -5380,6 +5377,10 @@
"save-library-panel": "儲存資料庫面板",
"settings": "儀表板設定",
"share-button": "分享",
+ "star-add-error": "",
+ "star-added": "",
+ "star-remove-error": "",
+ "star-removed": "",
"unlink-library-panel": "取消連結資料庫面板",
"unmark-favorite": "取消標記為「我的最愛」"
},