Chore: Remove code related to viz/widget split feature (#95614)

This commit is contained in:
kay delaney 2024-10-30 16:12:03 +00:00 committed by GitHub
parent 08e880a823
commit db5f893ea6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
23 changed files with 24 additions and 193 deletions

View File

@ -151,7 +151,6 @@ Experimental features might be changed or removed without prior notice.
| `pluginsFrontendSandbox` | Enables the plugins frontend sandbox |
| `frontendSandboxMonitorOnly` | Enables monitor only in the plugin frontend sandbox (if enabled) |
| `pluginsDetailsRightPanel` | Enables right panel for the plugins details page |
| `vizAndWidgetSplit` | Split panels between visualizations and widgets |
| `awsDatasourcesTempCredentials` | Support temporary security credentials in AWS plugins for Grafana Cloud customers |
| `mlExpressions` | Enable support for Machine Learning in server-side expressions |
| `metricsSummary` | Enables metrics summary queries in the Tempo data source |

View File

@ -80,7 +80,6 @@ export interface FeatureToggles {
pluginsDetailsRightPanel?: boolean;
sqlDatasourceDatabaseSelection?: boolean;
recordedQueriesMulti?: boolean;
vizAndWidgetSplit?: boolean;
logsExploreTableVisualisation?: boolean;
awsDatasourcesTempCredentials?: boolean;
transformationsRedesign?: boolean;

View File

@ -463,13 +463,6 @@ var (
Owner: grafanaObservabilityMetricsSquad,
AllowSelfServe: false,
},
{
Name: "vizAndWidgetSplit",
Description: "Split panels between visualizations and widgets",
Stage: FeatureStageExperimental,
FrontendOnly: true,
Owner: grafanaDashboardsSquad,
},
{
Name: "logsExploreTableVisualisation",
Description: "A table visualisation for logs in Explore",

View File

@ -61,7 +61,6 @@ frontendSandboxMonitorOnly,experimental,@grafana/plugins-platform-backend,false,
pluginsDetailsRightPanel,experimental,@grafana/plugins-platform-backend,false,false,true
sqlDatasourceDatabaseSelection,preview,@grafana/dataviz-squad,false,false,true
recordedQueriesMulti,GA,@grafana/observability-metrics,false,false,false
vizAndWidgetSplit,experimental,@grafana/dashboards-squad,false,false,true
logsExploreTableVisualisation,GA,@grafana/observability-logs,false,false,true
awsDatasourcesTempCredentials,experimental,@grafana/aws-datasources,false,false,false
transformationsRedesign,GA,@grafana/observability-metrics,false,false,true

1 Name Stage Owner requiresDevMode RequiresRestart FrontendOnly
61 pluginsDetailsRightPanel experimental @grafana/plugins-platform-backend false false true
62 sqlDatasourceDatabaseSelection preview @grafana/dataviz-squad false false true
63 recordedQueriesMulti GA @grafana/observability-metrics false false false
vizAndWidgetSplit experimental @grafana/dashboards-squad false false true
64 logsExploreTableVisualisation GA @grafana/observability-logs false false true
65 awsDatasourcesTempCredentials experimental @grafana/aws-datasources false false false
66 transformationsRedesign GA @grafana/observability-metrics false false true

View File

@ -255,10 +255,6 @@ const (
// Enables writing multiple items from a single query within Recorded Queries
FlagRecordedQueriesMulti = "recordedQueriesMulti"
// FlagVizAndWidgetSplit
// Split panels between visualizations and widgets
FlagVizAndWidgetSplit = "vizAndWidgetSplit"
// FlagLogsExploreTableVisualisation
// A table visualisation for logs in Explore
FlagLogsExploreTableVisualisation = "logsExploreTableVisualisation"

View File

@ -3297,7 +3297,8 @@
"metadata": {
"name": "vizAndWidgetSplit",
"resourceVersion": "1718727528075",
"creationTimestamp": "2023-06-27T10:22:13Z"
"creationTimestamp": "2023-06-27T10:22:13Z",
"deletionTimestamp": "2024-10-30T14:21:33Z"
},
"spec": {
"description": "Split panels between visualizations and widgets",

View File

@ -2,26 +2,16 @@ import { css } from '@emotion/css';
import { useCallback, useMemo, useState } from 'react';
import { GrafanaTheme2, PanelPluginMeta, SelectableValue } from '@grafana/data';
import { config } from '@grafana/runtime';
import { Icon, Button, MultiSelect, useStyles2 } from '@grafana/ui';
import { getAllPanelPluginMeta, getVizPluginMeta, getWidgetPluginMeta } from 'app/features/panel/state/util';
import { getAllPanelPluginMeta } from 'app/features/panel/state/util';
export interface Props {
onChange: (plugins: PanelPluginMeta[]) => void;
maxMenuHeight?: number;
isWidget?: boolean;
}
export const PanelTypeFilter = ({ onChange: propsOnChange, maxMenuHeight, isWidget = false }: Props): JSX.Element => {
const getPluginMetaData = (): PanelPluginMeta[] => {
if (config.featureToggles.vizAndWidgetSplit) {
return isWidget ? getWidgetPluginMeta() : getVizPluginMeta();
} else {
return getAllPanelPluginMeta();
}
};
const plugins = useMemo<PanelPluginMeta[]>(getPluginMetaData, [isWidget]);
export const PanelTypeFilter = ({ onChange: propsOnChange, maxMenuHeight }: Props): JSX.Element => {
const plugins = useMemo<PanelPluginMeta[]>(getAllPanelPluginMeta, []);
const options = useMemo(
() =>
plugins

View File

@ -17,5 +17,3 @@ export const EDIT_PANEL_ID = 23763571993;
export const DEFAULT_PER_PAGE_PAGINATION = 40;
export const LS_VISUALIZATION_SELECT_TAB_KEY = 'VisualizationSelectPane.ListMode';
export const LS_WIDGET_SELECT_TAB_KEY = 'WidgetSelectPane.ListMode';

View File

@ -8,7 +8,7 @@ import { selectors } from '@grafana/e2e-selectors';
import { reportInteraction } from '@grafana/runtime';
import { VizPanel } from '@grafana/scenes';
import { Button, CustomScrollbar, Field, FilterInput, RadioButtonGroup, useStyles2 } from '@grafana/ui';
import { LS_VISUALIZATION_SELECT_TAB_KEY, LS_WIDGET_SELECT_TAB_KEY } from 'app/core/constants';
import { LS_VISUALIZATION_SELECT_TAB_KEY } from 'app/core/constants';
import { VisualizationSelectPaneTab } from 'app/features/dashboard/components/PanelEditor/types';
import { VisualizationSuggestions } from 'app/features/panel/components/VizTypePicker/VisualizationSuggestions';
import { VizTypePicker } from 'app/features/panel/components/VizTypePicker/VizTypePicker';
@ -48,18 +48,12 @@ export function PanelVizTypePicker({ panel, data, onChange, onClose }: Props) {
setSearchQuery(value);
};
const isWidgetEnabled = false;
const tabKey = isWidgetEnabled ? LS_WIDGET_SELECT_TAB_KEY : LS_VISUALIZATION_SELECT_TAB_KEY;
const defaultTab = isWidgetEnabled ? VisualizationSelectPaneTab.Widgets : VisualizationSelectPaneTab.Visualizations;
const tabKey = LS_VISUALIZATION_SELECT_TAB_KEY;
const defaultTab = VisualizationSelectPaneTab.Visualizations;
const panelModel = useMemo(() => new PanelModelCompatibilityWrapper(panel), [panel]);
const supportedListModes = useMemo(
() =>
new Set([
VisualizationSelectPaneTab.Widgets,
VisualizationSelectPaneTab.Visualizations,
VisualizationSelectPaneTab.Suggestions,
]),
() => new Set([VisualizationSelectPaneTab.Visualizations, VisualizationSelectPaneTab.Suggestions]),
[]
);
const [listMode, setListMode] = useLocalStorage(tabKey, defaultTab);

View File

@ -3,7 +3,6 @@ import { act, fireEvent, render, screen } from '@testing-library/react';
import { PluginType } from '@grafana/data';
import { locationService, reportInteraction } from '@grafana/runtime';
import { defaultDashboard } from '@grafana/schema';
import config from 'app/core/config';
import { createDashboardModelFixture } from 'app/features/dashboard/state/__fixtures__/dashboardFixtures';
import {
onCreateNewPanel,
@ -45,7 +44,6 @@ function setup() {
}
beforeEach(() => {
config.featureToggles = { vizAndWidgetSplit: false };
jest.clearAllMocks();
});
@ -141,10 +139,3 @@ it('renders menu list without Widget button when feature flag is disabled', () =
setup();
expect(screen.queryByText('Widget')).not.toBeInTheDocument();
});
it('renders menu list with Widget button when feature flag is enabled', () => {
config.featureToggles.vizAndWidgetSplit = true;
setup();
expect(screen.getByText('Widget')).toBeInTheDocument();
});

View File

@ -1,7 +1,7 @@
import { useMemo } from 'react';
import { selectors } from '@grafana/e2e-selectors';
import { config, locationService } from '@grafana/runtime';
import { locationService } from '@grafana/runtime';
import { Menu } from '@grafana/ui';
import { t } from 'app/core/internationalization';
import { DashboardModel } from 'app/features/dashboard/state';
@ -39,17 +39,6 @@ const AddPanelMenu = ({ dashboard }: Props) => {
dispatch(setInitialDatasource(undefined));
}}
/>
{config.featureToggles.vizAndWidgetSplit && (
<Menu.Item
key="add-widget"
testId={selectors.pages.AddDashboard.itemButton('Add new widget menu item')}
label={t('dashboard.add-menu.widget', 'Widget')}
onClick={() => {
DashboardInteractions.toolbarAddButtonClicked({ item: 'add_widget' });
locationService.partial({ addWidget: true });
}}
/>
)}
<Menu.Item
key="add-row"
testId={selectors.pages.AddDashboard.itemButton('Add new row menu item')}

View File

@ -4,10 +4,9 @@ import { useLocalStorage } from 'react-use';
import { GrafanaTheme2, PanelData, SelectableValue } from '@grafana/data';
import { selectors } from '@grafana/e2e-selectors';
import { config } from '@grafana/runtime';
import { Button, CustomScrollbar, FilterInput, RadioButtonGroup, useStyles2 } from '@grafana/ui';
import { Field } from '@grafana/ui/src/components/Forms/Field';
import { LS_VISUALIZATION_SELECT_TAB_KEY, LS_WIDGET_SELECT_TAB_KEY } from 'app/core/constants';
import { LS_VISUALIZATION_SELECT_TAB_KEY } from 'app/core/constants';
import { PanelLibraryOptionsGroup } from 'app/features/library-panels/components/PanelLibraryOptionsGroup/PanelLibraryOptionsGroup';
import { VisualizationSuggestions } from 'app/features/panel/components/VizTypePicker/VisualizationSuggestions';
import { VizTypeChangeDetails } from 'app/features/panel/components/VizTypePicker/types';
@ -30,12 +29,8 @@ export const VisualizationSelectPane = ({ panel, data }: Props) => {
const plugin = useSelector(getPanelPluginWithFallback(panel.type));
const [searchQuery, setSearchQuery] = useState('');
// Add support to show widgets in the visualization picker
const isWidget = !!plugin.meta.skipDataQuery;
const isWidgetEnabled = Boolean(isWidget && config.featureToggles.vizAndWidgetSplit);
const tabKey = isWidgetEnabled ? LS_WIDGET_SELECT_TAB_KEY : LS_VISUALIZATION_SELECT_TAB_KEY;
const defaultTab = isWidgetEnabled ? VisualizationSelectPaneTab.Widgets : VisualizationSelectPaneTab.Visualizations;
const tabKey = LS_VISUALIZATION_SELECT_TAB_KEY;
const defaultTab = VisualizationSelectPaneTab.Visualizations;
const [listMode, setListMode] = useLocalStorage(tabKey, defaultTab);
@ -73,15 +68,6 @@ export const VisualizationSelectPane = ({ panel, data }: Props) => {
},
];
const radioOptionsWidgetFlow: Array<SelectableValue<VisualizationSelectPaneTab>> = [
{ label: 'Widgets', value: VisualizationSelectPaneTab.Widgets },
{
label: 'Library panels',
value: VisualizationSelectPaneTab.LibraryPanels,
description: 'Reusable panels you can share between multiple dashboards.',
},
];
return (
<div className={styles.openWrapper}>
<div className={styles.formBox}>
@ -103,12 +89,7 @@ export const VisualizationSelectPane = ({ panel, data }: Props) => {
/>
</div>
<Field className={styles.customFieldMargin}>
<RadioButtonGroup
options={isWidgetEnabled ? radioOptionsWidgetFlow : radioOptions}
value={listMode}
onChange={setListMode}
fullWidth
/>
<RadioButtonGroup options={radioOptions} value={listMode} onChange={setListMode} fullWidth />
</Field>
</div>
<div className={styles.scrollWrapper}>
@ -117,20 +98,11 @@ export const VisualizationSelectPane = ({ panel, data }: Props) => {
{listMode === VisualizationSelectPaneTab.Visualizations && (
<VizTypePicker pluginId={plugin.meta.id} onChange={onVizChange} searchQuery={searchQuery} />
)}
{listMode === VisualizationSelectPaneTab.Widgets && (
<VizTypePicker pluginId={plugin.meta.id} onChange={onVizChange} searchQuery={searchQuery} isWidget />
)}
{listMode === VisualizationSelectPaneTab.Suggestions && (
<VisualizationSuggestions onChange={onVizChange} searchQuery={searchQuery} panel={panel} data={data} />
)}
{listMode === VisualizationSelectPaneTab.LibraryPanels && (
<PanelLibraryOptionsGroup
searchQuery={searchQuery}
panel={panel}
key="Panel Library"
isWidget={isWidget}
/>
<PanelLibraryOptionsGroup searchQuery={searchQuery} panel={panel} key="Panel Library" />
)}
</div>
</CustomScrollbar>

View File

@ -72,5 +72,4 @@ export enum VisualizationSelectPaneTab {
Visualizations,
LibraryPanels,
Suggestions,
Widgets,
}

View File

@ -26,7 +26,6 @@ import { PanelEditEnteredEvent, PanelEditExitedEvent } from 'app/types/events';
import { cancelVariables, templateVarsChangedInUrl } from '../../variables/state/actions';
import { findTemplateVarChanges } from '../../variables/utils';
import { AddWidgetModal } from '../components/AddWidgetModal/AddWidgetModal';
import { DashNav } from '../components/DashNav';
import { DashboardFailed } from '../components/DashboardLoading/DashboardFailed';
import { DashboardLoading } from '../components/DashboardLoading/DashboardLoading';
@ -494,7 +493,6 @@ export class UnthemedDashboardPage extends PureComponent<Props, State> {
sectionNav={sectionNav}
/>
)}
{queryParams.addWidget && config.featureToggles.vizAndWidgetSplit && <AddWidgetModal />}
</>
);
}

View File

@ -2,7 +2,6 @@ import { act, fireEvent, render, screen } from '@testing-library/react';
import { locationService, reportInteraction } from '@grafana/runtime';
import { defaultDashboard } from '@grafana/schema';
import config from 'app/core/config';
import { createDashboardModelFixture } from '../state/__fixtures__/dashboardFixtures';
import { onCreateNewPanel, onImportDashboard, onAddLibraryPanel } from '../utils/dashboard';
@ -40,7 +39,6 @@ function setup(options?: Partial<Props>) {
}
beforeEach(() => {
config.featureToggles = { vizAndWidgetSplit: false };
jest.clearAllMocks();
});
@ -110,13 +108,3 @@ it('renders page without Add Widget button when feature flag is disabled', () =>
expect(screen.getByRole('button', { name: 'Add library panel' })).toBeInTheDocument();
expect(screen.queryByRole('button', { name: 'Add widget' })).not.toBeInTheDocument();
});
it('renders page with Add Widget button when feature flag is enabled', () => {
config.featureToggles.vizAndWidgetSplit = true;
setup();
expect(screen.getByRole('button', { name: 'Add visualization' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: 'Import dashboard' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: 'Add library panel' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: 'Add widget' })).toBeInTheDocument();
});

View File

@ -2,7 +2,7 @@ import { css } from '@emotion/css';
import { GrafanaTheme2 } from '@grafana/data';
import { selectors } from '@grafana/e2e-selectors';
import { config, locationService } from '@grafana/runtime';
import { locationService } from '@grafana/runtime';
import { Button, useStyles2, Text, Box, Stack } from '@grafana/ui';
import { Trans } from 'app/core/internationalization';
import { DashboardModel } from 'app/features/dashboard/state';
@ -83,32 +83,6 @@ const DashboardEmpty = ({ dashboard, canCreate }: Props) => {
</Stack>
</Box>
<Stack direction={{ xs: 'column', md: 'row' }} wrap="wrap" gap={4}>
{config.featureToggles.vizAndWidgetSplit && (
<Box borderColor="strong" borderStyle="dashed" padding={3} flex={1}>
<Stack direction="column" alignItems="center" gap={1}>
<Text element="h3" textAlignment="center" weight="medium">
<Trans i18nKey="dashboard.empty.add-widget-header">Add a widget</Trans>
</Text>
<Box marginBottom={2}>
<Text element="p" textAlignment="center" color="secondary">
<Trans i18nKey="dashboard.empty.add-widget-body">Create lists, markdowns and other widgets</Trans>
</Text>
</Box>
<Button
icon="plus"
fill="outline"
data-testid={selectors.pages.AddDashboard.itemButton('Create new widget button')}
onClick={() => {
DashboardInteractions.emptyDashboardButtonClicked({ item: 'add_widget' });
locationService.partial({ addWidget: true });
}}
disabled={!canCreate}
>
<Trans i18nKey="dashboard.empty.add-widget-button">Add widget</Trans>
</Button>
</Stack>
</Box>
)}
<Box borderColor="strong" borderStyle="dashed" padding={3} flex={1}>
<Stack direction="column" alignItems="center" gap={1}>
<Text element="h3" textAlignment="center" weight="medium">

View File

@ -21,7 +21,6 @@ interface LibraryPanelViewProps {
panelFilter?: string[];
folderFilter?: string[];
perPage?: number;
isWidget?: boolean;
}
export const LibraryPanelsView = ({
@ -33,7 +32,6 @@ export const LibraryPanelsView = ({
showSecondaryActions,
currentPanelId: currentPanel,
perPage: propsPerPage = 40,
isWidget,
}: LibraryPanelViewProps) => {
const styles = useStyles2(getPanelViewStyles);
const [{ libraryPanels, page, perPage, numberOfPages, loadingState, currentPanelId }, dispatch] = useReducer(
@ -56,7 +54,6 @@ export const LibraryPanelsView = ({
page,
perPage,
currentPanelId,
isWidget,
})
),
300,

View File

@ -3,11 +3,6 @@ import { Dispatch } from 'react';
import { from, merge, of, Subscription, timer } from 'rxjs';
import { catchError, finalize, mapTo, mergeMap, share, takeUntil } from 'rxjs/operators';
import { PanelPluginMeta } from '@grafana/data';
import { config } from '@grafana/runtime';
import { LibraryPanel } from '@grafana/schema';
import { getAllPanelPluginMeta } from 'app/features/panel/state/util';
import { deleteLibraryPanel as apiDeleteLibraryPanel, getLibraryPanels } from '../../state/api';
import { initialLibraryPanelsViewState, initSearch, searchCompleted } from './reducer';
@ -21,29 +16,11 @@ interface SearchArgs {
panelFilter?: string[];
folderFilterUIDs?: string[];
currentPanelId?: string;
isWidget?: boolean;
}
export function searchForLibraryPanels(args: SearchArgs): DispatchResult {
// Functions to support filtering out library panels per plugin type that have skipDataQuery set to true
const findPluginMeta = (pluginMeta: PanelPluginMeta, libraryPanel: LibraryPanel) =>
pluginMeta.id === libraryPanel.type;
const filterLibraryPanels = (libraryPanels: LibraryPanel[], isWidget: boolean) => {
const pluginMetaList = getAllPanelPluginMeta();
return libraryPanels.filter((libraryPanel) => {
const matchingPluginMeta = pluginMetaList.find((pluginMeta) => findPluginMeta(pluginMeta, libraryPanel));
// widget mode filter
if (isWidget) {
return !!matchingPluginMeta?.skipDataQuery;
}
// non-widget mode filter
return !matchingPluginMeta?.skipDataQuery;
});
};
return function (dispatch) {
const subscription = new Subscription();
const dataObservable = from(
@ -60,12 +37,6 @@ export function searchForLibraryPanels(args: SearchArgs): DispatchResult {
//filter out library panels per plugin type that have skipDataQuery set to true
mergeMap((libraryPanelsResult) => {
const { elements: libraryPanels } = libraryPanelsResult;
if (config.featureToggles.vizAndWidgetSplit && args.isWidget !== undefined) {
const filteredLibraryPanels = filterLibraryPanels(libraryPanels, args.isWidget);
return of({ ...libraryPanelsResult, elements: filteredLibraryPanels });
}
return of({ ...libraryPanelsResult, elements: libraryPanels });
}),
mergeMap(({ perPage, elements: libraryPanels, page, totalCount }) =>

View File

@ -17,10 +17,9 @@ import { LibraryPanelsView } from '../LibraryPanelsView/LibraryPanelsView';
interface Props {
panel: PanelModel;
searchQuery: string;
isWidget?: boolean;
}
export const PanelLibraryOptionsGroup = ({ panel, searchQuery, isWidget = false }: Props) => {
export const PanelLibraryOptionsGroup = ({ panel, searchQuery }: Props) => {
const [showingAddPanelModal, setShowingAddPanelModal] = useState(false);
const [changeToPanel, setChangeToPanel] = useState<LibraryElementDTO | undefined>(undefined);
const [panelFilter, setPanelFilter] = useState<string[]>([]);
@ -54,7 +53,7 @@ export const PanelLibraryOptionsGroup = ({ panel, searchQuery, isWidget = false
</VerticalGroup>
)}
<PanelTypeFilter onChange={onPanelFilterChange} isWidget={isWidget} />
<PanelTypeFilter onChange={onPanelFilterChange} />
<div className={styles.libraryPanelsView}>
<LibraryPanelsView
@ -63,7 +62,6 @@ export const PanelLibraryOptionsGroup = ({ panel, searchQuery, isWidget = false
panelFilter={panelFilter}
onClickCard={setChangeToPanel}
showSecondaryActions
isWidget={isWidget}
/>
</div>

View File

@ -2,10 +2,9 @@ import { css } from '@emotion/css';
import { useMemo } from 'react';
import { GrafanaTheme2 } from '@grafana/data';
import { config } from '@grafana/runtime';
import { EmptySearchResult, useStyles2 } from '@grafana/ui';
import { filterPluginList, getAllPanelPluginMeta, getVizPluginMeta, getWidgetPluginMeta } from '../../state/util';
import { filterPluginList, getAllPanelPluginMeta } from '../../state/util';
import { VizTypePickerPlugin } from './VizTypePickerPlugin';
import { VizTypeChangeDetails } from './types';
@ -14,18 +13,12 @@ export interface Props {
pluginId: string;
searchQuery: string;
onChange: (options: VizTypeChangeDetails) => void;
isWidget?: boolean;
trackSearch?: (q: string, count: number) => void;
}
export function VizTypePicker({ pluginId, searchQuery, onChange, isWidget = false, trackSearch }: Props) {
export function VizTypePicker({ pluginId, searchQuery, onChange, trackSearch }: Props) {
const styles = useStyles2(getStyles);
const pluginsList = useMemo(() => {
if (config.featureToggles.vizAndWidgetSplit) {
return isWidget ? getWidgetPluginMeta() : getVizPluginMeta();
}
return getAllPanelPluginMeta();
}, [isWidget]);
const pluginsList = useMemo(getAllPanelPluginMeta, []);
const filteredPluginTypes = useMemo(() => {
const result = filterPluginList(pluginsList, searchQuery, pluginId);

View File

@ -39,7 +39,7 @@ export async function getAllSuggestions(data?: PanelData, panel?: PanelModel): P
const list = builder.getList();
if (!config.featureToggles.vizAndWidgetSplit && builder.dataSummary.fieldCount === 0) {
if (builder.dataSummary.fieldCount === 0) {
for (const plugin of Object.values(config.panels)) {
if (!plugin.skipDataQuery || plugin.hideFromList) {
continue;

View File

@ -615,8 +615,7 @@
"import": "Import from library",
"paste-panel": "Paste panel",
"row": "Row",
"visualization": "Visualization",
"widget": "Widget"
"visualization": "Visualization"
},
"alert-rules-drawer": {
"redirect-link": "List in Grafana Alerting",
@ -629,9 +628,6 @@
"add-visualization-body": "Select a data source and then query and visualize your data with charts, stats and tables or create lists, markdowns and other widgets.",
"add-visualization-button": "Add visualization",
"add-visualization-header": "Start your new dashboard by adding a visualization",
"add-widget-body": "Create lists, markdowns and other widgets",
"add-widget-button": "Add widget",
"add-widget-header": "Add a widget",
"import-a-dashboard-body": "Import dashboards from files or <1>grafana.com</1>.",
"import-a-dashboard-header": "Import a dashboard",
"import-dashboard-button": "Import dashboard"

View File

@ -615,8 +615,7 @@
"import": "Ĩmpőřŧ ƒřőm ľįþřäřy",
"paste-panel": "Päşŧę päʼnęľ",
"row": "Ŗőŵ",
"visualization": "Vįşūäľįžäŧįőʼn",
"widget": "Ŵįđģęŧ"
"visualization": "Vįşūäľįžäŧįőʼn"
},
"alert-rules-drawer": {
"redirect-link": "Ŀįşŧ įʼn Ğřäƒäʼnä Åľęřŧįʼnģ",
@ -629,9 +628,6 @@
"add-visualization-body": "Ŝęľęčŧ ä đäŧä şőūřčę äʼnđ ŧĥęʼn qūęřy äʼnđ vįşūäľįžę yőūř đäŧä ŵįŧĥ čĥäřŧş, şŧäŧş äʼnđ ŧäþľęş őř čřęäŧę ľįşŧş, mäřĸđőŵʼnş äʼnđ őŧĥęř ŵįđģęŧş.",
"add-visualization-button": "Åđđ vįşūäľįžäŧįőʼn",
"add-visualization-header": "Ŝŧäřŧ yőūř ʼnęŵ đäşĥþőäřđ þy äđđįʼnģ ä vįşūäľįžäŧįőʼn",
"add-widget-body": "Cřęäŧę ľįşŧş, mäřĸđőŵʼnş äʼnđ őŧĥęř ŵįđģęŧş",
"add-widget-button": "Åđđ ŵįđģęŧ",
"add-widget-header": "Åđđ ä ŵįđģęŧ",
"import-a-dashboard-body": "Ĩmpőřŧ đäşĥþőäřđş ƒřőm ƒįľęş őř <1>ģřäƒäʼnä.čőm</1>.",
"import-a-dashboard-header": "Ĩmpőřŧ ä đäşĥþőäřđ",
"import-dashboard-button": "Ĩmpőřŧ đäşĥþőäřđ"