mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Plugin extensions: Make sure core features use new hooks (#92723)
* use new extensions APIs across grafana core * setup setPluginLinksHook * fix tests * fix mock * fix more broken tests * use plugin components hook * remove unused func * fix tests * remove unused import
This commit is contained in:
parent
01a4e6b9af
commit
8c702d4a6b
@ -16,7 +16,7 @@ import { AppChrome } from './AppChrome';
|
|||||||
|
|
||||||
jest.mock('@grafana/runtime', () => ({
|
jest.mock('@grafana/runtime', () => ({
|
||||||
...jest.requireActual('@grafana/runtime'),
|
...jest.requireActual('@grafana/runtime'),
|
||||||
usePluginLinkExtensions: jest.fn().mockReturnValue({ extensions: [] }),
|
usePluginLinks: jest.fn().mockReturnValue({ links: [] }),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const searchData: DataFrame = {
|
const searchData: DataFrame = {
|
||||||
|
@ -3,7 +3,7 @@ import { byTestId, byText } from 'testing-library-selector';
|
|||||||
|
|
||||||
import { DataSourceApi } from '@grafana/data';
|
import { DataSourceApi } from '@grafana/data';
|
||||||
import { PromOptions, PrometheusDatasource } from '@grafana/prometheus';
|
import { PromOptions, PrometheusDatasource } from '@grafana/prometheus';
|
||||||
import { setDataSourceSrv, setPluginExtensionsHook } from '@grafana/runtime';
|
import { setDataSourceSrv, setPluginLinksHook } from '@grafana/runtime';
|
||||||
import * as ruleActionButtons from 'app/features/alerting/unified/components/rules/RuleActionsButtons';
|
import * as ruleActionButtons from 'app/features/alerting/unified/components/rules/RuleActionsButtons';
|
||||||
import { DashboardModel, PanelModel } from 'app/features/dashboard/state';
|
import { DashboardModel, PanelModel } from 'app/features/dashboard/state';
|
||||||
import { getDatasourceSrv } from 'app/features/plugins/datasource_srv';
|
import { getDatasourceSrv } from 'app/features/plugins/datasource_srv';
|
||||||
@ -191,8 +191,8 @@ describe('PanelAlertTabContent', () => {
|
|||||||
AccessControlAction.AlertingRuleExternalWrite,
|
AccessControlAction.AlertingRuleExternalWrite,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
setPluginExtensionsHook(() => ({
|
setPluginLinksHook(() => ({
|
||||||
extensions: [],
|
links: [],
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ import {
|
|||||||
locationService,
|
locationService,
|
||||||
setAppEvents,
|
setAppEvents,
|
||||||
setDataSourceSrv,
|
setDataSourceSrv,
|
||||||
usePluginLinkExtensions,
|
usePluginLinks,
|
||||||
} from '@grafana/runtime';
|
} from '@grafana/runtime';
|
||||||
import appEvents from 'app/core/app_events';
|
import appEvents from 'app/core/app_events';
|
||||||
import * as ruleActionButtons from 'app/features/alerting/unified/components/rules/RuleActionsButtons';
|
import * as ruleActionButtons from 'app/features/alerting/unified/components/rules/RuleActionsButtons';
|
||||||
@ -52,7 +52,7 @@ import { DataSourceType, GRAFANA_RULES_SOURCE_NAME } from './utils/datasource';
|
|||||||
jest.mock('@grafana/runtime', () => ({
|
jest.mock('@grafana/runtime', () => ({
|
||||||
...jest.requireActual('@grafana/runtime'),
|
...jest.requireActual('@grafana/runtime'),
|
||||||
getPluginLinkExtensions: jest.fn(),
|
getPluginLinkExtensions: jest.fn(),
|
||||||
usePluginLinkExtensions: jest.fn(),
|
usePluginLinks: jest.fn(),
|
||||||
useReturnToPrevious: jest.fn(),
|
useReturnToPrevious: jest.fn(),
|
||||||
}));
|
}));
|
||||||
jest.mock('./api/buildInfo');
|
jest.mock('./api/buildInfo');
|
||||||
@ -72,7 +72,7 @@ setupPluginsExtensionsHook();
|
|||||||
const mocks = {
|
const mocks = {
|
||||||
getAllDataSourcesMock: jest.mocked(config.getAllDataSources),
|
getAllDataSourcesMock: jest.mocked(config.getAllDataSources),
|
||||||
getPluginLinkExtensionsMock: jest.mocked(getPluginLinkExtensions),
|
getPluginLinkExtensionsMock: jest.mocked(getPluginLinkExtensions),
|
||||||
usePluginLinkExtensionsMock: jest.mocked(usePluginLinkExtensions),
|
usePluginLinksMock: jest.mocked(usePluginLinks),
|
||||||
rulesInSameGroupHaveInvalidForMock: jest.mocked(actions.rulesInSameGroupHaveInvalidFor),
|
rulesInSameGroupHaveInvalidForMock: jest.mocked(actions.rulesInSameGroupHaveInvalidFor),
|
||||||
|
|
||||||
api: {
|
api: {
|
||||||
@ -168,8 +168,8 @@ describe('RuleList', () => {
|
|||||||
AccessControlAction.AlertingRuleExternalWrite,
|
AccessControlAction.AlertingRuleExternalWrite,
|
||||||
]);
|
]);
|
||||||
mocks.rulesInSameGroupHaveInvalidForMock.mockReturnValue([]);
|
mocks.rulesInSameGroupHaveInvalidForMock.mockReturnValue([]);
|
||||||
mocks.usePluginLinkExtensionsMock.mockReturnValue({
|
mocks.usePluginLinksMock.mockReturnValue({
|
||||||
extensions: [
|
links: [
|
||||||
{
|
{
|
||||||
pluginId: 'grafana-ml-app',
|
pluginId: 'grafana-ml-app',
|
||||||
id: '1',
|
id: '1',
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { ReactElement, useMemo, useState } from 'react';
|
import { ReactElement, useMemo, useState } from 'react';
|
||||||
|
|
||||||
import { PluginExtensionLink, PluginExtensionPoints } from '@grafana/data';
|
import { PluginExtensionLink, PluginExtensionPoints } from '@grafana/data';
|
||||||
import { usePluginLinkExtensions } from '@grafana/runtime';
|
import { usePluginLinks } from '@grafana/runtime';
|
||||||
import { Dropdown, IconButton } from '@grafana/ui';
|
import { Dropdown, IconButton } from '@grafana/ui';
|
||||||
import { ConfirmNavigationModal } from 'app/features/explore/extensions/ConfirmNavigationModal';
|
import { ConfirmNavigationModal } from 'app/features/explore/extensions/ConfirmNavigationModal';
|
||||||
import { Alert, CombinedRule } from 'app/types/unified-alerting';
|
import { Alert, CombinedRule } from 'app/types/unified-alerting';
|
||||||
@ -21,13 +21,13 @@ export const AlertInstanceExtensionPoint = ({
|
|||||||
}: AlertInstanceExtensionPointProps): ReactElement | null => {
|
}: AlertInstanceExtensionPointProps): ReactElement | null => {
|
||||||
const [selectedExtension, setSelectedExtension] = useState<PluginExtensionLink | undefined>();
|
const [selectedExtension, setSelectedExtension] = useState<PluginExtensionLink | undefined>();
|
||||||
const context = useMemo(() => ({ instance, rule }), [instance, rule]);
|
const context = useMemo(() => ({ instance, rule }), [instance, rule]);
|
||||||
const { extensions } = usePluginLinkExtensions({ context, extensionPointId, limitPerPlugin: 3 });
|
const { links } = usePluginLinks({ context, extensionPointId, limitPerPlugin: 3 });
|
||||||
|
|
||||||
if (extensions.length === 0) {
|
if (links.length === 0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const menu = <AlertExtensionPointMenu extensions={extensions} onSelect={setSelectedExtension} />;
|
const menu = <AlertExtensionPointMenu extensions={links} onSelect={setSelectedExtension} />;
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Dropdown placement="bottom-start" overlay={menu}>
|
<Dropdown placement="bottom-start" overlay={menu}>
|
||||||
|
@ -2,7 +2,7 @@ import { within } from '@testing-library/react';
|
|||||||
import { render, waitFor, screen, userEvent } from 'test/test-utils';
|
import { render, waitFor, screen, userEvent } from 'test/test-utils';
|
||||||
import { byText, byRole } from 'testing-library-selector';
|
import { byText, byRole } from 'testing-library-selector';
|
||||||
|
|
||||||
import { setPluginExtensionsHook } from '@grafana/runtime';
|
import { setPluginLinksHook } from '@grafana/runtime';
|
||||||
import { setupMswServer } from 'app/features/alerting/unified/mockApi';
|
import { setupMswServer } from 'app/features/alerting/unified/mockApi';
|
||||||
import { setFolderAccessControl } from 'app/features/alerting/unified/mocks/server/configure';
|
import { setFolderAccessControl } from 'app/features/alerting/unified/mocks/server/configure';
|
||||||
import { AlertManagerDataSourceJsonData } from 'app/plugins/datasource/alertmanager/types';
|
import { AlertManagerDataSourceJsonData } from 'app/plugins/datasource/alertmanager/types';
|
||||||
@ -66,8 +66,8 @@ const ELEMENTS = {
|
|||||||
|
|
||||||
setupMswServer();
|
setupMswServer();
|
||||||
setupDataSources(mockDataSource({ type: DataSourceType.Prometheus, name: 'mimir-1' }));
|
setupDataSources(mockDataSource({ type: DataSourceType.Prometheus, name: 'mimir-1' }));
|
||||||
setPluginExtensionsHook(() => ({
|
setPluginLinksHook(() => ({
|
||||||
extensions: [
|
links: [
|
||||||
mockPluginLinkExtension({ pluginId: 'grafana-slo-app', title: 'SLO dashboard', path: '/a/grafana-slo-app' }),
|
mockPluginLinkExtension({ pluginId: 'grafana-slo-app', title: 'SLO dashboard', path: '/a/grafana-slo-app' }),
|
||||||
mockPluginLinkExtension({
|
mockPluginLinkExtension({
|
||||||
pluginId: 'grafana-asserts-app',
|
pluginId: 'grafana-asserts-app',
|
||||||
|
@ -404,8 +404,8 @@ const helpStyles = (theme: GrafanaTheme2) => ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
function usePluginsFilterStatus() {
|
function usePluginsFilterStatus() {
|
||||||
const { extensions } = useAlertingHomePageExtensions();
|
const { components } = useAlertingHomePageExtensions();
|
||||||
return { pluginsFilterEnabled: extensions.length > 0 };
|
return { pluginsFilterEnabled: components.length > 0 };
|
||||||
}
|
}
|
||||||
|
|
||||||
export default RulesFilter;
|
export default RulesFilter;
|
||||||
|
@ -2,7 +2,7 @@ import { produce } from 'immer';
|
|||||||
import { render, screen, userEvent } from 'test/test-utils';
|
import { render, screen, userEvent } from 'test/test-utils';
|
||||||
import { byLabelText, byRole } from 'testing-library-selector';
|
import { byLabelText, byRole } from 'testing-library-selector';
|
||||||
|
|
||||||
import { config, setPluginExtensionsHook } from '@grafana/runtime';
|
import { config, setPluginLinksHook } from '@grafana/runtime';
|
||||||
import { contextSrv } from 'app/core/services/context_srv';
|
import { contextSrv } from 'app/core/services/context_srv';
|
||||||
import { RuleActionsButtons } from 'app/features/alerting/unified/components/rules/RuleActionsButtons';
|
import { RuleActionsButtons } from 'app/features/alerting/unified/components/rules/RuleActionsButtons';
|
||||||
import { setupMswServer } from 'app/features/alerting/unified/mockApi';
|
import { setupMswServer } from 'app/features/alerting/unified/mockApi';
|
||||||
@ -53,8 +53,8 @@ const getMenuContents = async () => {
|
|||||||
return [...allMenuItems, ...allLinkItems];
|
return [...allMenuItems, ...allLinkItems];
|
||||||
};
|
};
|
||||||
|
|
||||||
setPluginExtensionsHook(() => ({
|
setPluginLinksHook(() => ({
|
||||||
extensions: [],
|
links: [],
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ import { render } from 'test/test-utils';
|
|||||||
import { byRole } from 'testing-library-selector';
|
import { byRole } from 'testing-library-selector';
|
||||||
|
|
||||||
import { PluginExtensionTypes } from '@grafana/data';
|
import { PluginExtensionTypes } from '@grafana/data';
|
||||||
import { usePluginLinkExtensions } from '@grafana/runtime';
|
import { usePluginLinks } from '@grafana/runtime';
|
||||||
import { setupMswServer } from 'app/features/alerting/unified/mockApi';
|
import { setupMswServer } from 'app/features/alerting/unified/mockApi';
|
||||||
|
|
||||||
import { useIsRuleEditable } from '../../hooks/useIsRuleEditable';
|
import { useIsRuleEditable } from '../../hooks/useIsRuleEditable';
|
||||||
@ -12,14 +12,14 @@ import { RuleDetails } from './RuleDetails';
|
|||||||
|
|
||||||
jest.mock('@grafana/runtime', () => ({
|
jest.mock('@grafana/runtime', () => ({
|
||||||
...jest.requireActual('@grafana/runtime'),
|
...jest.requireActual('@grafana/runtime'),
|
||||||
usePluginLinkExtensions: jest.fn(),
|
usePluginLinks: jest.fn(),
|
||||||
useReturnToPrevious: jest.fn(),
|
useReturnToPrevious: jest.fn(),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
jest.mock('../../hooks/useIsRuleEditable');
|
jest.mock('../../hooks/useIsRuleEditable');
|
||||||
|
|
||||||
const mocks = {
|
const mocks = {
|
||||||
usePluginLinkExtensionsMock: jest.mocked(usePluginLinkExtensions),
|
usePluginLinksMock: jest.mocked(usePluginLinks),
|
||||||
useIsRuleEditable: jest.mocked(useIsRuleEditable),
|
useIsRuleEditable: jest.mocked(useIsRuleEditable),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -37,8 +37,8 @@ beforeAll(() => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
mocks.usePluginLinkExtensionsMock.mockReturnValue({
|
mocks.usePluginLinksMock.mockReturnValue({
|
||||||
extensions: [
|
links: [
|
||||||
{
|
{
|
||||||
pluginId: 'grafana-ml-app',
|
pluginId: 'grafana-ml-app',
|
||||||
id: '1',
|
id: '1',
|
||||||
|
@ -4,7 +4,7 @@ import { times } from 'lodash';
|
|||||||
import { byLabelText, byRole, byTestId } from 'testing-library-selector';
|
import { byLabelText, byRole, byTestId } from 'testing-library-selector';
|
||||||
|
|
||||||
import { PluginExtensionTypes } from '@grafana/data';
|
import { PluginExtensionTypes } from '@grafana/data';
|
||||||
import { usePluginLinkExtensions } from '@grafana/runtime';
|
import { usePluginLinks } from '@grafana/runtime';
|
||||||
|
|
||||||
import { CombinedRuleNamespace } from '../../../../../types/unified-alerting';
|
import { CombinedRuleNamespace } from '../../../../../types/unified-alerting';
|
||||||
import { GrafanaAlertState, PromAlertingRuleState } from '../../../../../types/unified-alerting-dto';
|
import { GrafanaAlertState, PromAlertingRuleState } from '../../../../../types/unified-alerting-dto';
|
||||||
@ -16,11 +16,11 @@ import { RuleDetailsMatchingInstances } from './RuleDetailsMatchingInstances';
|
|||||||
jest.mock('@grafana/runtime', () => ({
|
jest.mock('@grafana/runtime', () => ({
|
||||||
...jest.requireActual('@grafana/runtime'),
|
...jest.requireActual('@grafana/runtime'),
|
||||||
getPluginLinkExtensions: jest.fn(),
|
getPluginLinkExtensions: jest.fn(),
|
||||||
usePluginLinkExtensions: jest.fn(),
|
usePluginLinks: jest.fn(),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const mocks = {
|
const mocks = {
|
||||||
usePluginLinkExtensionsMock: jest.mocked(usePluginLinkExtensions),
|
usePluginLinksMock: jest.mocked(usePluginLinks),
|
||||||
};
|
};
|
||||||
|
|
||||||
const ui = {
|
const ui = {
|
||||||
@ -43,8 +43,8 @@ const ui = {
|
|||||||
|
|
||||||
describe('RuleDetailsMatchingInstances', () => {
|
describe('RuleDetailsMatchingInstances', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
mocks.usePluginLinkExtensionsMock.mockReturnValue({
|
mocks.usePluginLinksMock.mockReturnValue({
|
||||||
extensions: [
|
links: [
|
||||||
{
|
{
|
||||||
pluginId: 'grafana-ml-app',
|
pluginId: 'grafana-ml-app',
|
||||||
id: '1',
|
id: '1',
|
||||||
|
@ -2,7 +2,7 @@ import { waitFor } from '@testing-library/react';
|
|||||||
import { render } from 'test/test-utils';
|
import { render } from 'test/test-utils';
|
||||||
import { byRole } from 'testing-library-selector';
|
import { byRole } from 'testing-library-selector';
|
||||||
|
|
||||||
import { setPluginExtensionsHook } from '@grafana/runtime';
|
import { setPluginLinksHook } from '@grafana/runtime';
|
||||||
import { contextSrv } from 'app/core/services/context_srv';
|
import { contextSrv } from 'app/core/services/context_srv';
|
||||||
import { AccessControlAction } from 'app/types';
|
import { AccessControlAction } from 'app/types';
|
||||||
import { CombinedRuleNamespace } from 'app/types/unified-alerting';
|
import { CombinedRuleNamespace } from 'app/types/unified-alerting';
|
||||||
@ -20,8 +20,8 @@ const ui = {
|
|||||||
cloudRulesHeading: byRole('heading', { name: 'Data source-managed' }),
|
cloudRulesHeading: byRole('heading', { name: 'Data source-managed' }),
|
||||||
};
|
};
|
||||||
|
|
||||||
setPluginExtensionsHook(() => ({
|
setPluginLinksHook(() => ({
|
||||||
extensions: [],
|
links: [],
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { render, screen } from 'test/test-utils';
|
import { render, screen } from 'test/test-utils';
|
||||||
|
|
||||||
import { setPluginExtensionsHook } from '@grafana/runtime';
|
import { setPluginLinksHook } from '@grafana/runtime';
|
||||||
import { RuleListStateView } from 'app/features/alerting/unified/components/rules/RuleListStateView';
|
import { RuleListStateView } from 'app/features/alerting/unified/components/rules/RuleListStateView';
|
||||||
import {
|
import {
|
||||||
mockCombinedRule,
|
mockCombinedRule,
|
||||||
@ -10,8 +10,8 @@ import {
|
|||||||
} from 'app/features/alerting/unified/mocks';
|
} from 'app/features/alerting/unified/mocks';
|
||||||
import { PromAlertingRuleState } from 'app/types/unified-alerting-dto';
|
import { PromAlertingRuleState } from 'app/types/unified-alerting-dto';
|
||||||
|
|
||||||
setPluginExtensionsHook(() => ({
|
setPluginLinksHook(() => ({
|
||||||
extensions: [],
|
links: [],
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { render, userEvent, screen } from 'test/test-utils';
|
import { render, userEvent, screen } from 'test/test-utils';
|
||||||
import { byRole } from 'testing-library-selector';
|
import { byRole } from 'testing-library-selector';
|
||||||
|
|
||||||
import { setPluginExtensionsHook } from '@grafana/runtime';
|
import { setPluginLinksHook } from '@grafana/runtime';
|
||||||
import { setupMswServer } from 'app/features/alerting/unified/mockApi';
|
import { setupMswServer } from 'app/features/alerting/unified/mockApi';
|
||||||
|
|
||||||
import { AlertRuleAction, useAlertRuleAbility } from '../../hooks/useAbilities';
|
import { AlertRuleAction, useAlertRuleAbility } from '../../hooks/useAbilities';
|
||||||
@ -15,8 +15,8 @@ const mocks = {
|
|||||||
useAlertRuleAbility: jest.mocked(useAlertRuleAbility),
|
useAlertRuleAbility: jest.mocked(useAlertRuleAbility),
|
||||||
};
|
};
|
||||||
|
|
||||||
setPluginExtensionsHook(() => ({
|
setPluginLinksHook(() => ({
|
||||||
extensions: [],
|
links: [],
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -9,9 +9,9 @@ import { useAlertingHomePageExtensions } from '../plugins/useAlertingHomePageExt
|
|||||||
export function PluginIntegrations() {
|
export function PluginIntegrations() {
|
||||||
const styles = useStyles2(getStyles);
|
const styles = useStyles2(getStyles);
|
||||||
|
|
||||||
const { extensions } = useAlertingHomePageExtensions();
|
const { components } = useAlertingHomePageExtensions();
|
||||||
|
|
||||||
if (extensions.length === 0) {
|
if (components.length === 0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -21,9 +21,9 @@ export function PluginIntegrations() {
|
|||||||
Speed up your alerts creation now by using one of our tailored apps
|
Speed up your alerts creation now by using one of our tailored apps
|
||||||
</Text>
|
</Text>
|
||||||
<Stack gap={2} wrap="wrap" direction="row">
|
<Stack gap={2} wrap="wrap" direction="row">
|
||||||
{extensions.map((extension) => (
|
{components.map((Component, i) => (
|
||||||
<div key={extension.id} className={styles.box}>
|
<div key={i} className={styles.box}>
|
||||||
<extension.component />
|
<Component />
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</Stack>
|
</Stack>
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import { PluginExtensionPoints } from '@grafana/data';
|
import { PluginExtensionPoints } from '@grafana/data';
|
||||||
import { usePluginComponentExtensions } from '@grafana/runtime';
|
import { usePluginComponents } from '@grafana/runtime';
|
||||||
|
|
||||||
export function useAlertingHomePageExtensions() {
|
export function useAlertingHomePageExtensions() {
|
||||||
return usePluginComponentExtensions({
|
return usePluginComponents({
|
||||||
extensionPointId: PluginExtensionPoints.AlertingHomePage,
|
extensionPointId: PluginExtensionPoints.AlertingHomePage,
|
||||||
limitPerPlugin: 1,
|
limitPerPlugin: 1,
|
||||||
});
|
});
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
|
|
||||||
import { PluginExtensionPoints } from '@grafana/data';
|
import { PluginExtensionPoints } from '@grafana/data';
|
||||||
import { usePluginLinkExtensions } from '@grafana/runtime';
|
import { usePluginLinks } from '@grafana/runtime';
|
||||||
import { CombinedRule } from 'app/types/unified-alerting';
|
import { CombinedRule } from 'app/types/unified-alerting';
|
||||||
import { PromRuleType } from 'app/types/unified-alerting-dto';
|
import { PromRuleType } from 'app/types/unified-alerting-dto';
|
||||||
|
|
||||||
@ -23,7 +23,7 @@ export interface RecordingRuleExtensionContext extends BaseRuleExtensionContext
|
|||||||
|
|
||||||
export function useRulePluginLinkExtension(rule: CombinedRule) {
|
export function useRulePluginLinkExtension(rule: CombinedRule) {
|
||||||
const ruleExtensionPoint = useRuleExtensionPoint(rule);
|
const ruleExtensionPoint = useRuleExtensionPoint(rule);
|
||||||
const { extensions } = usePluginLinkExtensions(ruleExtensionPoint);
|
const { links } = usePluginLinks(ruleExtensionPoint);
|
||||||
|
|
||||||
const ruleOrigin = getRulePluginOrigin(rule);
|
const ruleOrigin = getRulePluginOrigin(rule);
|
||||||
const ruleType = rule.promRule?.type;
|
const ruleType = rule.promRule?.type;
|
||||||
@ -33,7 +33,7 @@ export function useRulePluginLinkExtension(rule: CombinedRule) {
|
|||||||
|
|
||||||
const { pluginId } = ruleOrigin;
|
const { pluginId } = ruleOrigin;
|
||||||
|
|
||||||
return extensions.filter((extension) => extension.pluginId === pluginId);
|
return links.filter((link) => link.pluginId === pluginId);
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PluginRuleExtensionParam {
|
export interface PluginRuleExtensionParam {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { PluginMeta, PluginType } from '@grafana/data';
|
import { PluginMeta, PluginType } from '@grafana/data';
|
||||||
import { setPluginExtensionsHook } from '@grafana/runtime';
|
import { setPluginComponentsHook, setPluginExtensionsHook } from '@grafana/runtime';
|
||||||
import { SupportedPlugin } from 'app/features/alerting/unified/types/pluginBridges';
|
import { SupportedPlugin } from 'app/features/alerting/unified/types/pluginBridges';
|
||||||
|
|
||||||
import { mockPluginLinkExtension } from '../mocks';
|
import { mockPluginLinkExtension } from '../mocks';
|
||||||
@ -15,6 +15,10 @@ export function setupPluginsExtensionsHook() {
|
|||||||
),
|
),
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
}));
|
}));
|
||||||
|
setPluginComponentsHook(() => ({
|
||||||
|
components: [],
|
||||||
|
isLoading: false,
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
export const plugins: PluginMeta[] = [
|
export const plugins: PluginMeta[] = [
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
|
|
||||||
import { PluginExtensionCommandPaletteContext, PluginExtensionPoints } from '@grafana/data';
|
import { PluginExtensionCommandPaletteContext, PluginExtensionPoints } from '@grafana/data';
|
||||||
import { usePluginLinkExtensions } from '@grafana/runtime';
|
import { usePluginLinks } from '@grafana/runtime';
|
||||||
|
|
||||||
import { CommandPaletteAction } from '../types';
|
import { CommandPaletteAction } from '../types';
|
||||||
import { EXTENSIONS_PRIORITY } from '../values';
|
import { EXTENSIONS_PRIORITY } from '../values';
|
||||||
@ -10,20 +10,20 @@ import { EXTENSIONS_PRIORITY } from '../values';
|
|||||||
const context: PluginExtensionCommandPaletteContext = {};
|
const context: PluginExtensionCommandPaletteContext = {};
|
||||||
|
|
||||||
export default function useExtensionActions(): CommandPaletteAction[] {
|
export default function useExtensionActions(): CommandPaletteAction[] {
|
||||||
const { extensions } = usePluginLinkExtensions({
|
const { links } = usePluginLinks({
|
||||||
extensionPointId: PluginExtensionPoints.CommandPalette,
|
extensionPointId: PluginExtensionPoints.CommandPalette,
|
||||||
context,
|
context,
|
||||||
limitPerPlugin: 3,
|
limitPerPlugin: 3,
|
||||||
});
|
});
|
||||||
|
|
||||||
return useMemo(() => {
|
return useMemo(() => {
|
||||||
return extensions.map((extension) => ({
|
return links.map((link) => ({
|
||||||
section: extension.category ?? 'Extensions',
|
section: link.category ?? 'Extensions',
|
||||||
priority: EXTENSIONS_PRIORITY,
|
priority: EXTENSIONS_PRIORITY,
|
||||||
id: extension.id,
|
id: link.id,
|
||||||
name: extension.title,
|
name: link.title,
|
||||||
target: extension.path,
|
target: link.path,
|
||||||
perform: () => extension.onClick && extension.onClick(),
|
perform: () => link.onClick && link.onClick(),
|
||||||
}));
|
}));
|
||||||
}, [extensions]);
|
}, [links]);
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ import { byTestId } from 'testing-library-selector';
|
|||||||
|
|
||||||
import { DataSourceApi } from '@grafana/data';
|
import { DataSourceApi } from '@grafana/data';
|
||||||
import { PromOptions, PrometheusDatasource } from '@grafana/prometheus';
|
import { PromOptions, PrometheusDatasource } from '@grafana/prometheus';
|
||||||
import { locationService, setDataSourceSrv, setPluginExtensionsHook } from '@grafana/runtime';
|
import { locationService, setDataSourceSrv, setPluginLinksHook } from '@grafana/runtime';
|
||||||
import { backendSrv } from 'app/core/services/backend_srv';
|
import { backendSrv } from 'app/core/services/backend_srv';
|
||||||
import * as ruler from 'app/features/alerting/unified/api/ruler';
|
import * as ruler from 'app/features/alerting/unified/api/ruler';
|
||||||
import * as ruleActionButtons from 'app/features/alerting/unified/components/rules/RuleActionsButtons';
|
import * as ruleActionButtons from 'app/features/alerting/unified/components/rules/RuleActionsButtons';
|
||||||
@ -50,8 +50,8 @@ jest.spyOn(ruleActionButtons, 'matchesWidth').mockReturnValue(false);
|
|||||||
jest.spyOn(ruler, 'rulerUrlBuilder');
|
jest.spyOn(ruler, 'rulerUrlBuilder');
|
||||||
jest.spyOn(alertingAbilities, 'useAlertRuleAbility');
|
jest.spyOn(alertingAbilities, 'useAlertRuleAbility');
|
||||||
|
|
||||||
setPluginExtensionsHook(() => ({
|
setPluginLinksHook(() => ({
|
||||||
extensions: [],
|
links: [],
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -63,7 +63,7 @@ jest.mock('app/core/core', () => ({
|
|||||||
jest.mock('@grafana/runtime', () => ({
|
jest.mock('@grafana/runtime', () => ({
|
||||||
...jest.requireActual('@grafana/runtime'),
|
...jest.requireActual('@grafana/runtime'),
|
||||||
getPluginLinkExtensions: jest.fn().mockReturnValue({ extensions: [] }),
|
getPluginLinkExtensions: jest.fn().mockReturnValue({ extensions: [] }),
|
||||||
usePluginLinkExtensions: jest.fn().mockReturnValue({ extensions: [] }),
|
usePluginLinks: jest.fn().mockReturnValue({ links: [] }),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
function getTestDashboard(overrides?: Partial<Dashboard>, metaOverrides?: Partial<DashboardMeta>): DashboardModel {
|
function getTestDashboard(overrides?: Partial<Dashboard>, metaOverrides?: Partial<DashboardMeta>): DashboardModel {
|
||||||
|
@ -7,7 +7,7 @@ import {
|
|||||||
PluginExtensionPoints,
|
PluginExtensionPoints,
|
||||||
getTimeZone,
|
getTimeZone,
|
||||||
} from '@grafana/data';
|
} from '@grafana/data';
|
||||||
import { usePluginLinkExtensions } from '@grafana/runtime';
|
import { usePluginLinks } from '@grafana/runtime';
|
||||||
import { getPanelStateForModel } from 'app/features/panel/state/selectors';
|
import { getPanelStateForModel } from 'app/features/panel/state/selectors';
|
||||||
import { useSelector } from 'app/types';
|
import { useSelector } from 'app/types';
|
||||||
|
|
||||||
@ -29,15 +29,15 @@ export function PanelHeaderMenuProvider({ panel, dashboard, loadingState, childr
|
|||||||
const [items, setItems] = useState<PanelMenuItem[]>([]);
|
const [items, setItems] = useState<PanelMenuItem[]>([]);
|
||||||
const angularComponent = useSelector((state) => getPanelStateForModel(state, panel)?.angularComponent);
|
const angularComponent = useSelector((state) => getPanelStateForModel(state, panel)?.angularComponent);
|
||||||
const context = useMemo(() => createExtensionContext(panel, dashboard), [panel, dashboard]);
|
const context = useMemo(() => createExtensionContext(panel, dashboard), [panel, dashboard]);
|
||||||
const { extensions } = usePluginLinkExtensions({
|
const { links } = usePluginLinks({
|
||||||
extensionPointId: PluginExtensionPoints.DashboardPanelMenu,
|
extensionPointId: PluginExtensionPoints.DashboardPanelMenu,
|
||||||
context,
|
context,
|
||||||
limitPerPlugin: 3,
|
limitPerPlugin: 3,
|
||||||
});
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setItems(getPanelMenu(dashboard, panel, extensions, angularComponent));
|
setItems(getPanelMenu(dashboard, panel, links, angularComponent));
|
||||||
}, [dashboard, panel, angularComponent, loadingState, setItems, extensions]);
|
}, [dashboard, panel, angularComponent, loadingState, setItems, links]);
|
||||||
|
|
||||||
return children({ items });
|
return children({ items });
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { Store } from 'redux';
|
import { Store } from 'redux';
|
||||||
|
|
||||||
import { PanelMenuItem, PluginExtensionLink, PluginExtensionTypes } from '@grafana/data';
|
import { PanelMenuItem, PluginExtensionLink, PluginExtensionTypes } from '@grafana/data';
|
||||||
import { AngularComponent, usePluginLinkExtensions } from '@grafana/runtime';
|
import { AngularComponent, usePluginLinks } from '@grafana/runtime';
|
||||||
import config from 'app/core/config';
|
import config from 'app/core/config';
|
||||||
import { grantUserPermissions } from 'app/features/alerting/unified/mocks';
|
import { grantUserPermissions } from 'app/features/alerting/unified/mocks';
|
||||||
import * as actions from 'app/features/explore/state/main';
|
import * as actions from 'app/features/explore/state/main';
|
||||||
@ -22,16 +22,16 @@ jest.mock('app/core/services/context_srv', () => ({
|
|||||||
|
|
||||||
jest.mock('@grafana/runtime', () => ({
|
jest.mock('@grafana/runtime', () => ({
|
||||||
...jest.requireActual('@grafana/runtime'),
|
...jest.requireActual('@grafana/runtime'),
|
||||||
setPluginExtensionsHook: jest.fn(),
|
setPluginLinksHook: jest.fn(),
|
||||||
usePluginLinkExtensions: jest.fn(),
|
usePluginLinks: jest.fn(),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const usePluginLinkExtensionsMock = jest.mocked(usePluginLinkExtensions);
|
const usePluginLinksMock = jest.mocked(usePluginLinks);
|
||||||
|
|
||||||
describe('getPanelMenu()', () => {
|
describe('getPanelMenu()', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
usePluginLinkExtensionsMock.mockRestore();
|
usePluginLinksMock.mockRestore();
|
||||||
usePluginLinkExtensionsMock.mockReturnValue({ extensions: [], isLoading: false });
|
usePluginLinksMock.mockReturnValue({ links: [], isLoading: false });
|
||||||
grantUserPermissions([AccessControlAction.AlertingRuleRead, AccessControlAction.AlertingRuleUpdate]);
|
grantUserPermissions([AccessControlAction.AlertingRuleRead, AccessControlAction.AlertingRuleUpdate]);
|
||||||
config.unifiedAlertingEnabled = false;
|
config.unifiedAlertingEnabled = false;
|
||||||
});
|
});
|
||||||
|
@ -12,7 +12,7 @@ import {
|
|||||||
store,
|
store,
|
||||||
} from '@grafana/data';
|
} from '@grafana/data';
|
||||||
import { selectors } from '@grafana/e2e-selectors';
|
import { selectors } from '@grafana/e2e-selectors';
|
||||||
import { usePluginLinkExtensions } from '@grafana/runtime';
|
import { usePluginLinks } from '@grafana/runtime';
|
||||||
import { configureStore } from 'app/store/configureStore';
|
import { configureStore } from 'app/store/configureStore';
|
||||||
|
|
||||||
import { ContentOutlineContextProvider } from './ContentOutline/ContentOutlineContext';
|
import { ContentOutlineContextProvider } from './ContentOutline/ContentOutlineContext';
|
||||||
@ -124,7 +124,7 @@ jest.mock('app/core/core', () => ({
|
|||||||
|
|
||||||
jest.mock('@grafana/runtime', () => ({
|
jest.mock('@grafana/runtime', () => ({
|
||||||
...jest.requireActual('@grafana/runtime'),
|
...jest.requireActual('@grafana/runtime'),
|
||||||
usePluginLinkExtensions: jest.fn(() => ({ extensions: [] })),
|
usePluginLinks: jest.fn(() => ({ links: [] })),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// for the AutoSizer component to have a width
|
// for the AutoSizer component to have a width
|
||||||
@ -138,7 +138,7 @@ jest.mock('react-virtualized-auto-sizer', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
const usePluginLinkExtensionsMock = jest.mocked(usePluginLinkExtensions);
|
const usePluginLinksMock = jest.mocked(usePluginLinks);
|
||||||
|
|
||||||
const setup = (overrideProps?: Partial<Props>) => {
|
const setup = (overrideProps?: Partial<Props>) => {
|
||||||
const store = configureStore({
|
const store = configureStore({
|
||||||
@ -180,8 +180,8 @@ describe('Explore', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should render toolbar extension point if extensions is available', async () => {
|
it('should render toolbar extension point if extensions is available', async () => {
|
||||||
usePluginLinkExtensionsMock.mockReturnValueOnce({
|
usePluginLinksMock.mockReturnValueOnce({
|
||||||
extensions: [
|
links: [
|
||||||
{
|
{
|
||||||
id: '1',
|
id: '1',
|
||||||
pluginId: 'grafana',
|
pluginId: 'grafana',
|
||||||
|
@ -4,7 +4,7 @@ import { ReactNode } from 'react';
|
|||||||
import { Provider } from 'react-redux';
|
import { Provider } from 'react-redux';
|
||||||
|
|
||||||
import { PluginExtensionPoints, PluginExtensionTypes } from '@grafana/data';
|
import { PluginExtensionPoints, PluginExtensionTypes } from '@grafana/data';
|
||||||
import { usePluginLinkExtensions } from '@grafana/runtime';
|
import { usePluginLinks } from '@grafana/runtime';
|
||||||
import { DataQuery } from '@grafana/schema';
|
import { DataQuery } from '@grafana/schema';
|
||||||
import { contextSrv } from 'app/core/services/context_srv';
|
import { contextSrv } from 'app/core/services/context_srv';
|
||||||
import { configureStore } from 'app/store/configureStore';
|
import { configureStore } from 'app/store/configureStore';
|
||||||
@ -16,13 +16,13 @@ import { ToolbarExtensionPoint } from './ToolbarExtensionPoint';
|
|||||||
|
|
||||||
jest.mock('@grafana/runtime', () => ({
|
jest.mock('@grafana/runtime', () => ({
|
||||||
...jest.requireActual('@grafana/runtime'),
|
...jest.requireActual('@grafana/runtime'),
|
||||||
usePluginLinkExtensions: jest.fn(),
|
usePluginLinks: jest.fn(),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
jest.mock('app/core/services/context_srv');
|
jest.mock('app/core/services/context_srv');
|
||||||
|
|
||||||
const contextSrvMock = jest.mocked(contextSrv);
|
const contextSrvMock = jest.mocked(contextSrv);
|
||||||
const usePluginLinkExtensionsMock = jest.mocked(usePluginLinkExtensions);
|
const usePluginLinksMock = jest.mocked(usePluginLinks);
|
||||||
|
|
||||||
type storeOptions = {
|
type storeOptions = {
|
||||||
targets: DataQuery[];
|
targets: DataQuery[];
|
||||||
@ -54,8 +54,8 @@ function renderWithExploreStore(
|
|||||||
describe('ToolbarExtensionPoint', () => {
|
describe('ToolbarExtensionPoint', () => {
|
||||||
describe('with extension points', () => {
|
describe('with extension points', () => {
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
usePluginLinkExtensionsMock.mockReturnValue({
|
usePluginLinksMock.mockReturnValue({
|
||||||
extensions: [
|
links: [
|
||||||
{
|
{
|
||||||
pluginId: 'grafana',
|
pluginId: 'grafana',
|
||||||
id: '1',
|
id: '1',
|
||||||
@ -100,10 +100,10 @@ describe('ToolbarExtensionPoint', () => {
|
|||||||
await userEvent.click(screen.getByRole('button', { name: 'Add' }));
|
await userEvent.click(screen.getByRole('button', { name: 'Add' }));
|
||||||
await userEvent.click(screen.getByRole('menuitem', { name: 'Add to dashboard' }));
|
await userEvent.click(screen.getByRole('menuitem', { name: 'Add to dashboard' }));
|
||||||
|
|
||||||
const { extensions } = usePluginLinkExtensionsMock({
|
const { links } = usePluginLinksMock({
|
||||||
extensionPointId: PluginExtensionPoints.ExploreToolbarAction,
|
extensionPointId: PluginExtensionPoints.ExploreToolbarAction,
|
||||||
});
|
});
|
||||||
const [extension] = extensions;
|
const [extension] = links;
|
||||||
|
|
||||||
expect(jest.mocked(extension.onClick)).toBeCalledTimes(1);
|
expect(jest.mocked(extension.onClick)).toBeCalledTimes(1);
|
||||||
});
|
});
|
||||||
@ -128,7 +128,7 @@ describe('ToolbarExtensionPoint', () => {
|
|||||||
data,
|
data,
|
||||||
});
|
});
|
||||||
|
|
||||||
const [options] = usePluginLinkExtensionsMock.mock.calls[0];
|
const [options] = usePluginLinksMock.mock.calls[0];
|
||||||
const { context } = options;
|
const { context } = options;
|
||||||
|
|
||||||
expect(context).toEqual({
|
expect(context).toEqual({
|
||||||
@ -153,7 +153,7 @@ describe('ToolbarExtensionPoint', () => {
|
|||||||
data,
|
data,
|
||||||
});
|
});
|
||||||
|
|
||||||
const [options] = usePluginLinkExtensionsMock.mock.calls[0];
|
const [options] = usePluginLinksMock.mock.calls[0];
|
||||||
const { context } = options;
|
const { context } = options;
|
||||||
|
|
||||||
expect(context).toHaveProperty('timeZone', 'browser');
|
expect(context).toHaveProperty('timeZone', 'browser');
|
||||||
@ -162,7 +162,7 @@ describe('ToolbarExtensionPoint', () => {
|
|||||||
it('should correct extension point id when fetching extensions', async () => {
|
it('should correct extension point id when fetching extensions', async () => {
|
||||||
renderWithExploreStore(<ToolbarExtensionPoint exploreId="left" timeZone="browser" />);
|
renderWithExploreStore(<ToolbarExtensionPoint exploreId="left" timeZone="browser" />);
|
||||||
|
|
||||||
const [options] = usePluginLinkExtensionsMock.mock.calls[0];
|
const [options] = usePluginLinksMock.mock.calls[0];
|
||||||
const { extensionPointId } = options;
|
const { extensionPointId } = options;
|
||||||
|
|
||||||
expect(extensionPointId).toBe(PluginExtensionPoints.ExploreToolbarAction);
|
expect(extensionPointId).toBe(PluginExtensionPoints.ExploreToolbarAction);
|
||||||
@ -171,8 +171,8 @@ describe('ToolbarExtensionPoint', () => {
|
|||||||
|
|
||||||
describe('with extension points without categories', () => {
|
describe('with extension points without categories', () => {
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
usePluginLinkExtensionsMock.mockReturnValue({
|
usePluginLinksMock.mockReturnValue({
|
||||||
extensions: [
|
links: [
|
||||||
{
|
{
|
||||||
pluginId: 'grafana',
|
pluginId: 'grafana',
|
||||||
id: '1',
|
id: '1',
|
||||||
@ -215,7 +215,7 @@ describe('ToolbarExtensionPoint', () => {
|
|||||||
describe('without extension points', () => {
|
describe('without extension points', () => {
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
contextSrvMock.hasPermission.mockReturnValue(true);
|
contextSrvMock.hasPermission.mockReturnValue(true);
|
||||||
usePluginLinkExtensionsMock.mockReturnValue({ extensions: [], isLoading: false });
|
usePluginLinksMock.mockReturnValue({ links: [], isLoading: false });
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should render "add to dashboard" action button if one pane is visible', async () => {
|
it('should render "add to dashboard" action button if one pane is visible', async () => {
|
||||||
@ -233,7 +233,7 @@ describe('ToolbarExtensionPoint', () => {
|
|||||||
describe('with insufficient permissions', () => {
|
describe('with insufficient permissions', () => {
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
contextSrvMock.hasPermission.mockReturnValue(false);
|
contextSrvMock.hasPermission.mockReturnValue(false);
|
||||||
usePluginLinkExtensionsMock.mockReturnValue({ extensions: [], isLoading: false });
|
usePluginLinksMock.mockReturnValue({ links: [], isLoading: false });
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not render "add to dashboard" action button', async () => {
|
it('should not render "add to dashboard" action button', async () => {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { lazy, ReactElement, Suspense, useMemo, useState } from 'react';
|
import { lazy, ReactElement, Suspense, useMemo, useState } from 'react';
|
||||||
|
|
||||||
import { type PluginExtensionLink, PluginExtensionPoints, RawTimeRange, getTimeZone } from '@grafana/data';
|
import { type PluginExtensionLink, PluginExtensionPoints, RawTimeRange, getTimeZone } from '@grafana/data';
|
||||||
import { config, usePluginLinkExtensions } from '@grafana/runtime';
|
import { config, usePluginLinks } from '@grafana/runtime';
|
||||||
import { DataQuery, TimeZone } from '@grafana/schema';
|
import { DataQuery, TimeZone } from '@grafana/schema';
|
||||||
import { Dropdown, ToolbarButton } from '@grafana/ui';
|
import { Dropdown, ToolbarButton } from '@grafana/ui';
|
||||||
import { contextSrv } from 'app/core/services/context_srv';
|
import { contextSrv } from 'app/core/services/context_srv';
|
||||||
@ -26,7 +26,7 @@ export function ToolbarExtensionPoint(props: Props): ReactElement | null {
|
|||||||
const [selectedExtension, setSelectedExtension] = useState<PluginExtensionLink | undefined>();
|
const [selectedExtension, setSelectedExtension] = useState<PluginExtensionLink | undefined>();
|
||||||
const [isOpen, setIsOpen] = useState<boolean>(false);
|
const [isOpen, setIsOpen] = useState<boolean>(false);
|
||||||
const context = useExtensionPointContext(props);
|
const context = useExtensionPointContext(props);
|
||||||
const { extensions } = usePluginLinkExtensions({
|
const { links } = usePluginLinks({
|
||||||
extensionPointId: PluginExtensionPoints.ExploreToolbarAction,
|
extensionPointId: PluginExtensionPoints.ExploreToolbarAction,
|
||||||
context: context,
|
context: context,
|
||||||
limitPerPlugin: 3,
|
limitPerPlugin: 3,
|
||||||
@ -36,7 +36,7 @@ export function ToolbarExtensionPoint(props: Props): ReactElement | null {
|
|||||||
|
|
||||||
// If we only have the explore core extension point registered we show the old way of
|
// If we only have the explore core extension point registered we show the old way of
|
||||||
// adding a query to a dashboard.
|
// adding a query to a dashboard.
|
||||||
if (extensions.length <= 1) {
|
if (links.length <= 1) {
|
||||||
const canAddPanelToDashboard =
|
const canAddPanelToDashboard =
|
||||||
contextSrv.hasPermission(AccessControlAction.DashboardsCreate) ||
|
contextSrv.hasPermission(AccessControlAction.DashboardsCreate) ||
|
||||||
contextSrv.hasPermission(AccessControlAction.DashboardsWrite);
|
contextSrv.hasPermission(AccessControlAction.DashboardsWrite);
|
||||||
@ -52,7 +52,7 @@ export function ToolbarExtensionPoint(props: Props): ReactElement | null {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const menu = <ToolbarExtensionPointMenu extensions={extensions} onSelect={setSelectedExtension} />;
|
const menu = <ToolbarExtensionPointMenu extensions={links} onSelect={setSelectedExtension} />;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
@ -21,12 +21,12 @@ import {
|
|||||||
locationService,
|
locationService,
|
||||||
HistoryWrapper,
|
HistoryWrapper,
|
||||||
LocationService,
|
LocationService,
|
||||||
setPluginExtensionsHook,
|
|
||||||
setBackendSrv,
|
setBackendSrv,
|
||||||
getBackendSrv,
|
getBackendSrv,
|
||||||
getDataSourceSrv,
|
getDataSourceSrv,
|
||||||
getEchoSrv,
|
getEchoSrv,
|
||||||
setLocationService,
|
setLocationService,
|
||||||
|
setPluginLinksHook,
|
||||||
} from '@grafana/runtime';
|
} from '@grafana/runtime';
|
||||||
import { DataSourceRef } from '@grafana/schema';
|
import { DataSourceRef } from '@grafana/schema';
|
||||||
import { GrafanaContext } from 'app/core/context/GrafanaContext';
|
import { GrafanaContext } from 'app/core/context/GrafanaContext';
|
||||||
@ -89,7 +89,7 @@ export function setupExplore(options?: SetupOptions): {
|
|||||||
request: jest.fn().mockRejectedValue(undefined),
|
request: jest.fn().mockRejectedValue(undefined),
|
||||||
});
|
});
|
||||||
|
|
||||||
setPluginExtensionsHook(() => ({ extensions: [], isLoading: false }));
|
setPluginLinksHook(() => ({ links: [], isLoading: false }));
|
||||||
|
|
||||||
// Clear this up otherwise it persists data source selection
|
// Clear this up otherwise it persists data source selection
|
||||||
// TODO: probably add test for that too
|
// TODO: probably add test for that too
|
||||||
|
@ -11,7 +11,7 @@ jest.mock('@grafana/runtime', () => ({
|
|||||||
useChromeHeaderHeight: jest.fn(),
|
useChromeHeaderHeight: jest.fn(),
|
||||||
getBackendSrv: () => ({ get: getMock }),
|
getBackendSrv: () => ({ get: getMock }),
|
||||||
getDataSourceSrv: () => ({ get: getDatasource, getInstanceSettings }),
|
getDataSourceSrv: () => ({ get: getDatasource, getInstanceSettings }),
|
||||||
usePluginLinkExtensions: jest.fn().mockReturnValue({ extensions: [] }),
|
usePluginLinks: jest.fn().mockReturnValue({ links: [] }),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
describe('Dashboard reload', () => {
|
describe('Dashboard reload', () => {
|
||||||
|
@ -12,7 +12,7 @@ jest.mock('@grafana/runtime', () => ({
|
|||||||
useChromeHeaderHeight: jest.fn(),
|
useChromeHeaderHeight: jest.fn(),
|
||||||
getBackendSrv: () => ({ get: getMock }),
|
getBackendSrv: () => ({ get: getMock }),
|
||||||
getDataSourceSrv: () => ({ get: getDatasource, getInstanceSettings }),
|
getDataSourceSrv: () => ({ get: getDatasource, getInstanceSettings }),
|
||||||
usePluginLinkExtensions: jest.fn().mockReturnValue({ extensions: [] }),
|
usePluginLinks: jest.fn().mockReturnValue({ links: [] }),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const runTest = async (passScopes: boolean, kubernetesApi: boolean) => {
|
const runTest = async (passScopes: boolean, kubernetesApi: boolean) => {
|
||||||
|
@ -28,7 +28,7 @@ jest.mock('@grafana/runtime', () => ({
|
|||||||
useChromeHeaderHeight: jest.fn(),
|
useChromeHeaderHeight: jest.fn(),
|
||||||
getBackendSrv: () => ({ get: getMock }),
|
getBackendSrv: () => ({ get: getMock }),
|
||||||
getDataSourceSrv: () => ({ get: getDatasource, getInstanceSettings }),
|
getDataSourceSrv: () => ({ get: getDatasource, getInstanceSettings }),
|
||||||
usePluginLinkExtensions: jest.fn().mockReturnValue({ extensions: [] }),
|
usePluginLinks: jest.fn().mockReturnValue({ links: [] }),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
describe('Dashboards list', () => {
|
describe('Dashboards list', () => {
|
||||||
|
@ -11,7 +11,7 @@ jest.mock('@grafana/runtime', () => ({
|
|||||||
useChromeHeaderHeight: jest.fn(),
|
useChromeHeaderHeight: jest.fn(),
|
||||||
getBackendSrv: () => ({ get: getMock }),
|
getBackendSrv: () => ({ get: getMock }),
|
||||||
getDataSourceSrv: () => ({ get: getDatasource, getInstanceSettings }),
|
getDataSourceSrv: () => ({ get: getDatasource, getInstanceSettings }),
|
||||||
usePluginLinkExtensions: jest.fn().mockReturnValue({ extensions: [] }),
|
usePluginLinks: jest.fn().mockReturnValue({ links: [] }),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
describe('Feature flag off', () => {
|
describe('Feature flag off', () => {
|
||||||
|
@ -15,7 +15,7 @@ jest.mock('@grafana/runtime', () => ({
|
|||||||
useChromeHeaderHeight: jest.fn(),
|
useChromeHeaderHeight: jest.fn(),
|
||||||
getBackendSrv: () => ({ get: getMock }),
|
getBackendSrv: () => ({ get: getMock }),
|
||||||
getDataSourceSrv: () => ({ get: getDatasource, getInstanceSettings }),
|
getDataSourceSrv: () => ({ get: getDatasource, getInstanceSettings }),
|
||||||
usePluginLinkExtensions: jest.fn().mockReturnValue({ extensions: [] }),
|
usePluginLinks: jest.fn().mockReturnValue({ links: [] }),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
describe('Selector', () => {
|
describe('Selector', () => {
|
||||||
|
@ -46,7 +46,7 @@ jest.mock('@grafana/runtime', () => ({
|
|||||||
useChromeHeaderHeight: jest.fn(),
|
useChromeHeaderHeight: jest.fn(),
|
||||||
getBackendSrv: () => ({ get: getMock }),
|
getBackendSrv: () => ({ get: getMock }),
|
||||||
getDataSourceSrv: () => ({ get: getDatasource, getInstanceSettings }),
|
getDataSourceSrv: () => ({ get: getDatasource, getInstanceSettings }),
|
||||||
usePluginLinkExtensions: jest.fn().mockReturnValue({ extensions: [] }),
|
usePluginLinks: jest.fn().mockReturnValue({ links: [] }),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
describe('Tree', () => {
|
describe('Tree', () => {
|
||||||
|
@ -14,7 +14,7 @@ jest.mock('@grafana/runtime', () => ({
|
|||||||
useChromeHeaderHeight: jest.fn(),
|
useChromeHeaderHeight: jest.fn(),
|
||||||
getBackendSrv: () => ({ get: getMock }),
|
getBackendSrv: () => ({ get: getMock }),
|
||||||
getDataSourceSrv: () => ({ get: getDatasource, getInstanceSettings }),
|
getDataSourceSrv: () => ({ get: getDatasource, getInstanceSettings }),
|
||||||
usePluginLinkExtensions: jest.fn().mockReturnValue({ extensions: [] }),
|
usePluginLinks: jest.fn().mockReturnValue({ links: [] }),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
describe('View mode', () => {
|
describe('View mode', () => {
|
||||||
|
@ -4,7 +4,7 @@ import { Provider } from 'react-redux';
|
|||||||
import { byRole, byText } from 'testing-library-selector';
|
import { byRole, byText } from 'testing-library-selector';
|
||||||
|
|
||||||
import { FieldConfigSource, getDefaultTimeRange, LoadingState, PanelProps, PluginExtensionTypes } from '@grafana/data';
|
import { FieldConfigSource, getDefaultTimeRange, LoadingState, PanelProps, PluginExtensionTypes } from '@grafana/data';
|
||||||
import { TimeRangeUpdatedEvent, usePluginLinkExtensions } from '@grafana/runtime';
|
import { TimeRangeUpdatedEvent, usePluginLinks } from '@grafana/runtime';
|
||||||
import { setupMswServer } from 'app/features/alerting/unified/mockApi';
|
import { setupMswServer } from 'app/features/alerting/unified/mockApi';
|
||||||
import { mockPromRulesApiResponse } from 'app/features/alerting/unified/mocks/grafanaRulerApi';
|
import { mockPromRulesApiResponse } from 'app/features/alerting/unified/mocks/grafanaRulerApi';
|
||||||
import { mockRulerRulesApiResponse } from 'app/features/alerting/unified/mocks/rulerApi';
|
import { mockRulerRulesApiResponse } from 'app/features/alerting/unified/mocks/rulerApi';
|
||||||
@ -56,12 +56,12 @@ const grafanaRuleMock = {
|
|||||||
|
|
||||||
jest.mock('@grafana/runtime', () => ({
|
jest.mock('@grafana/runtime', () => ({
|
||||||
...jest.requireActual('@grafana/runtime'),
|
...jest.requireActual('@grafana/runtime'),
|
||||||
usePluginLinkExtensions: jest.fn(),
|
usePluginLinks: jest.fn(),
|
||||||
}));
|
}));
|
||||||
jest.mock('app/features/alerting/unified/api/alertmanager');
|
jest.mock('app/features/alerting/unified/api/alertmanager');
|
||||||
|
|
||||||
const mocks = {
|
const mocks = {
|
||||||
usePluginLinkExtensionsMock: jest.mocked(usePluginLinkExtensions),
|
usePluginLinksMock: jest.mocked(usePluginLinks),
|
||||||
};
|
};
|
||||||
|
|
||||||
const fakeResponse: PromRulesResponse = {
|
const fakeResponse: PromRulesResponse = {
|
||||||
@ -84,8 +84,8 @@ beforeEach(() => {
|
|||||||
mockRulerRulesApiResponse(server, 'grafana', {
|
mockRulerRulesApiResponse(server, 'grafana', {
|
||||||
'folder-one': [{ name: 'group1', interval: '20s', rules: [originRule] }],
|
'folder-one': [{ name: 'group1', interval: '20s', rules: [originRule] }],
|
||||||
});
|
});
|
||||||
mocks.usePluginLinkExtensionsMock.mockReturnValue({
|
mocks.usePluginLinksMock.mockReturnValue({
|
||||||
extensions: [
|
links: [
|
||||||
{
|
{
|
||||||
pluginId: 'grafana-ml-app',
|
pluginId: 'grafana-ml-app',
|
||||||
id: '1',
|
id: '1',
|
||||||
|
Loading…
Reference in New Issue
Block a user