mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Plugins: Allow disabling angular deprecation UI for specific plugins (#77026)
* Plugins:Allow disabling angular deprecation UI for specific plugins * add backend test * changed test names * lint * Removed angular properties from DataSourceDTO * Update tests * Move angularDetected and hideAngularDeprecation in angularMeta property * Fix angular property name in AppPluginConfig * Fix reference to angularMeta.detected * Fix hide_angular_deprecation not working for core plugins * lint
This commit is contained in:
@@ -674,8 +674,6 @@ export interface DataSourceInstanceSettings<T extends DataSourceJsonData = DataS
|
|||||||
|
|
||||||
/** When the name+uid are based on template variables, maintain access to the real values */
|
/** When the name+uid are based on template variables, maintain access to the real values */
|
||||||
rawRef?: DataSourceRef;
|
rawRef?: DataSourceRef;
|
||||||
|
|
||||||
angularDetected?: boolean;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -52,6 +52,11 @@ export interface PluginError {
|
|||||||
pluginType?: PluginType;
|
pluginType?: PluginType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface AngularMeta {
|
||||||
|
detected: boolean;
|
||||||
|
hideDeprecation: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
export interface PluginMeta<T extends KeyValue = {}> {
|
export interface PluginMeta<T extends KeyValue = {}> {
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
@@ -82,7 +87,7 @@ export interface PluginMeta<T extends KeyValue = {}> {
|
|||||||
signatureType?: PluginSignatureType;
|
signatureType?: PluginSignatureType;
|
||||||
signatureOrg?: string;
|
signatureOrg?: string;
|
||||||
live?: boolean;
|
live?: boolean;
|
||||||
angularDetected?: boolean;
|
angular?: AngularMeta;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface PluginDependencyInfo {
|
interface PluginDependencyInfo {
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import {
|
|||||||
systemDateFormats,
|
systemDateFormats,
|
||||||
SystemDateFormatSettings,
|
SystemDateFormatSettings,
|
||||||
getThemeById,
|
getThemeById,
|
||||||
|
AngularMeta,
|
||||||
} from '@grafana/data';
|
} from '@grafana/data';
|
||||||
|
|
||||||
export interface AzureSettings {
|
export interface AzureSettings {
|
||||||
@@ -30,7 +31,7 @@ export type AppPluginConfig = {
|
|||||||
path: string;
|
path: string;
|
||||||
version: string;
|
version: string;
|
||||||
preload: boolean;
|
preload: boolean;
|
||||||
angularDetected?: boolean;
|
angular: AngularMeta;
|
||||||
};
|
};
|
||||||
|
|
||||||
export class GrafanaBootConfig implements GrafanaConfig {
|
export class GrafanaBootConfig implements GrafanaConfig {
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ func (hs *HTTPServer) getFrontendSettings(c *contextmodel.ReqContext) (*dtos.Fro
|
|||||||
ReleaseState: string(panel.State),
|
ReleaseState: string(panel.State),
|
||||||
Signature: string(panel.Signature),
|
Signature: string(panel.Signature),
|
||||||
Sort: getPanelSort(panel.ID),
|
Sort: getPanelSort(panel.ID),
|
||||||
AngularDetected: panel.AngularDetected,
|
Angular: panel.Angular,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -336,8 +336,8 @@ func (hs *HTTPServer) getFSDataSources(c *contextmodel.ReqContext, availablePlug
|
|||||||
Signature: plugin.Signature,
|
Signature: plugin.Signature,
|
||||||
Module: plugin.Module,
|
Module: plugin.Module,
|
||||||
BaseURL: plugin.BaseURL,
|
BaseURL: plugin.BaseURL,
|
||||||
|
Angular: plugin.Angular,
|
||||||
}
|
}
|
||||||
dsDTO.AngularDetected = plugin.AngularDetected
|
|
||||||
|
|
||||||
if ds.JsonData == nil {
|
if ds.JsonData == nil {
|
||||||
dsDTO.JSONData = make(map[string]any)
|
dsDTO.JSONData = make(map[string]any)
|
||||||
@@ -419,8 +419,8 @@ func (hs *HTTPServer) getFSDataSources(c *contextmodel.ReqContext, availablePlug
|
|||||||
Signature: ds.Signature,
|
Signature: ds.Signature,
|
||||||
Module: ds.Module,
|
Module: ds.Module,
|
||||||
BaseURL: ds.BaseURL,
|
BaseURL: ds.BaseURL,
|
||||||
|
Angular: ds.Angular,
|
||||||
},
|
},
|
||||||
AngularDetected: ds.AngularDetected,
|
|
||||||
}
|
}
|
||||||
if ds.Name == grafanads.DatasourceName {
|
if ds.Name == grafanads.DatasourceName {
|
||||||
dto.ID = grafanads.DatasourceID
|
dto.ID = grafanads.DatasourceID
|
||||||
@@ -439,7 +439,7 @@ func newAppDTO(plugin pluginstore.Plugin, settings pluginsettings.InfoDTO) *plug
|
|||||||
Version: plugin.Info.Version,
|
Version: plugin.Info.Version,
|
||||||
Path: plugin.Module,
|
Path: plugin.Module,
|
||||||
Preload: false,
|
Preload: false,
|
||||||
AngularDetected: plugin.AngularDetected,
|
Angular: plugin.Angular,
|
||||||
}
|
}
|
||||||
|
|
||||||
if settings.Enabled {
|
if settings.Enabled {
|
||||||
|
|||||||
@@ -295,7 +295,7 @@ func TestHTTPServer_GetFrontendSettings_apps(t *testing.T) {
|
|||||||
Type: plugins.TypeApp,
|
Type: plugins.TypeApp,
|
||||||
Preload: true,
|
Preload: true,
|
||||||
},
|
},
|
||||||
AngularDetected: true,
|
Angular: plugins.AngularMeta{Detected: true},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -312,7 +312,7 @@ func TestHTTPServer_GetFrontendSettings_apps(t *testing.T) {
|
|||||||
Preload: true,
|
Preload: true,
|
||||||
Path: "/test-app/module.js",
|
Path: "/test-app/module.js",
|
||||||
Version: "0.5.0",
|
Version: "0.5.0",
|
||||||
AngularDetected: true,
|
Angular: plugins.AngularMeta{Detected: true},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -139,7 +139,7 @@ func (hs *HTTPServer) GetPluginList(c *contextmodel.ReqContext) response.Respons
|
|||||||
SignatureType: pluginDef.SignatureType,
|
SignatureType: pluginDef.SignatureType,
|
||||||
SignatureOrg: pluginDef.SignatureOrg,
|
SignatureOrg: pluginDef.SignatureOrg,
|
||||||
AccessControl: pluginsMetadata[pluginDef.ID],
|
AccessControl: pluginsMetadata[pluginDef.ID],
|
||||||
AngularDetected: pluginDef.AngularDetected,
|
AngularDetected: pluginDef.Angular.Detected,
|
||||||
}
|
}
|
||||||
|
|
||||||
update, exists := hs.pluginsUpdateChecker.HasUpdate(c.Req.Context(), pluginDef.ID)
|
update, exists := hs.pluginsUpdateChecker.HasUpdate(c.Req.Context(), pluginDef.ID)
|
||||||
@@ -196,7 +196,7 @@ func (hs *HTTPServer) GetPluginSettingByID(c *contextmodel.ReqContext) response.
|
|||||||
SignatureType: plugin.SignatureType,
|
SignatureType: plugin.SignatureType,
|
||||||
SignatureOrg: plugin.SignatureOrg,
|
SignatureOrg: plugin.SignatureOrg,
|
||||||
SecureJsonFields: map[string]bool{},
|
SecureJsonFields: map[string]bool{},
|
||||||
AngularDetected: plugin.AngularDetected,
|
AngularDetected: plugin.Angular.Detected,
|
||||||
}
|
}
|
||||||
|
|
||||||
if plugin.IsApp() {
|
if plugin.IsApp() {
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ func (a *AngularDetector) Validate(ctx context.Context, p *plugins.Plugin) error
|
|||||||
var err error
|
var err error
|
||||||
|
|
||||||
cctx, canc := context.WithTimeout(ctx, time.Second*10)
|
cctx, canc := context.WithTimeout(ctx, time.Second*10)
|
||||||
p.AngularDetected, err = a.angularInspector.Inspect(cctx, p)
|
p.Angular.Detected, err = a.angularInspector.Inspect(cctx, p)
|
||||||
canc()
|
canc()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -103,11 +103,11 @@ func (a *AngularDetector) Validate(ctx context.Context, p *plugins.Plugin) error
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Do not initialize plugins if they're using Angular and Angular support is disabled
|
// Do not initialize plugins if they're using Angular and Angular support is disabled
|
||||||
if p.AngularDetected && !a.cfg.AngularSupportEnabled {
|
if p.Angular.Detected && !a.cfg.AngularSupportEnabled {
|
||||||
a.log.Error("Refusing to initialize plugin because it's using Angular, which has been disabled", "pluginId", p.ID)
|
a.log.Error("Refusing to initialize plugin because it's using Angular, which has been disabled", "pluginId", p.ID)
|
||||||
return errors.New("angular plugins are not supported")
|
return errors.New("angular plugins are not supported")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
p.Angular.HideDeprecation = a.cfg.PluginSettings[p.ID]["hide_angular_deprecation"] == "true"
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -208,6 +208,8 @@ type PluginMetaDTO struct {
|
|||||||
|
|
||||||
Module string `json:"module"`
|
Module string `json:"module"`
|
||||||
BaseURL string `json:"baseUrl"`
|
BaseURL string `json:"baseUrl"`
|
||||||
|
|
||||||
|
Angular AngularMeta `json:"angular"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type DataSourceDTO struct {
|
type DataSourceDTO struct {
|
||||||
@@ -223,7 +225,6 @@ type DataSourceDTO struct {
|
|||||||
Module string `json:"module,omitempty"`
|
Module string `json:"module,omitempty"`
|
||||||
JSONData map[string]any `json:"jsonData"`
|
JSONData map[string]any `json:"jsonData"`
|
||||||
ReadOnly bool `json:"readOnly"`
|
ReadOnly bool `json:"readOnly"`
|
||||||
AngularDetected bool `json:"angularDetected"`
|
|
||||||
|
|
||||||
BasicAuth string `json:"basicAuth,omitempty"`
|
BasicAuth string `json:"basicAuth,omitempty"`
|
||||||
WithCredentials bool `json:"withCredentials,omitempty"`
|
WithCredentials bool `json:"withCredentials,omitempty"`
|
||||||
@@ -254,7 +255,8 @@ type PanelDTO struct {
|
|||||||
BaseURL string `json:"baseUrl"`
|
BaseURL string `json:"baseUrl"`
|
||||||
Signature string `json:"signature"`
|
Signature string `json:"signature"`
|
||||||
Module string `json:"module"`
|
Module string `json:"module"`
|
||||||
AngularDetected bool `json:"angularDetected"`
|
|
||||||
|
Angular AngularMeta `json:"angular"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type AppDTO struct {
|
type AppDTO struct {
|
||||||
@@ -262,7 +264,8 @@ type AppDTO struct {
|
|||||||
Path string `json:"path"`
|
Path string `json:"path"`
|
||||||
Version string `json:"version"`
|
Version string `json:"version"`
|
||||||
Preload bool `json:"preload"`
|
Preload bool `json:"preload"`
|
||||||
AngularDetected bool `json:"angularDetected"`
|
|
||||||
|
Angular AngularMeta `json:"angular"`
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ type Plugin struct {
|
|||||||
Module string
|
Module string
|
||||||
BaseURL string
|
BaseURL string
|
||||||
|
|
||||||
AngularDetected bool
|
Angular AngularMeta
|
||||||
|
|
||||||
ExternalService *auth.ExternalService
|
ExternalService *auth.ExternalService
|
||||||
|
|
||||||
@@ -67,6 +67,11 @@ type Plugin struct {
|
|||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type AngularMeta struct {
|
||||||
|
Detected bool `json:"detected"`
|
||||||
|
HideDeprecation bool `json:"hideDeprecation"`
|
||||||
|
}
|
||||||
|
|
||||||
// JSONData represents the plugin's plugin.json
|
// JSONData represents the plugin's plugin.json
|
||||||
type JSONData struct {
|
type JSONData struct {
|
||||||
// Common settings
|
// Common settings
|
||||||
|
|||||||
@@ -1221,9 +1221,9 @@ func TestLoader_AngularClass(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Len(t, p, 1, "should load 1 plugin")
|
require.Len(t, p, 1, "should load 1 plugin")
|
||||||
if tc.expAngularDetectionRun {
|
if tc.expAngularDetectionRun {
|
||||||
require.True(t, p[0].AngularDetected, "angular detection should run")
|
require.True(t, p[0].Angular.Detected, "angular detection should run")
|
||||||
} else {
|
} else {
|
||||||
require.False(t, p[0].AngularDetected, "angular detection should not run")
|
require.False(t, p[0].Angular.Detected, "angular detection should not run")
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -1279,6 +1279,49 @@ func TestLoader_Load_Angular(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestLoader_HideAngularDeprecation(t *testing.T) {
|
||||||
|
fakePluginSource := &fakes.FakePluginSource{
|
||||||
|
PluginClassFunc: func(ctx context.Context) plugins.Class {
|
||||||
|
return plugins.ClassExternal
|
||||||
|
},
|
||||||
|
PluginURIsFunc: func(ctx context.Context) []string {
|
||||||
|
return []string{filepath.Join(testDataDir(t), "valid-v2-signature")}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tc := range []struct {
|
||||||
|
name string
|
||||||
|
cfg *config.Cfg
|
||||||
|
expHideAngularDeprecation bool
|
||||||
|
}{
|
||||||
|
{name: `without "hide_angular_deprecation" setting`, cfg: &config.Cfg{
|
||||||
|
AngularSupportEnabled: true,
|
||||||
|
PluginSettings: setting.PluginSettings{},
|
||||||
|
}},
|
||||||
|
{name: `with "hide_angular_deprecation" = true`, cfg: &config.Cfg{
|
||||||
|
AngularSupportEnabled: true,
|
||||||
|
PluginSettings: setting.PluginSettings{
|
||||||
|
"plugin-id": map[string]string{"hide_angular_deprecation": "true"},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
{name: `with "hide_angular_deprecation" = false`, cfg: &config.Cfg{
|
||||||
|
AngularSupportEnabled: true,
|
||||||
|
PluginSettings: setting.PluginSettings{
|
||||||
|
"plugin-id": map[string]string{"hide_angular_deprecation": "false"},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
l := newLoaderWithOpts(t, tc.cfg, loaderDepOpts{
|
||||||
|
angularInspector: angularinspector.AlwaysAngularFakeInspector,
|
||||||
|
})
|
||||||
|
p, err := l.Load(context.Background(), fakePluginSource)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Len(t, p, 1, "should load 1 plugin")
|
||||||
|
require.Equal(t, tc.expHideAngularDeprecation, p[0].Angular.HideDeprecation)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestLoader_Load_NestedPlugins(t *testing.T) {
|
func TestLoader_Load_NestedPlugins(t *testing.T) {
|
||||||
parent := &plugins.Plugin{
|
parent := &plugins.Plugin{
|
||||||
JSONData: plugins.JSONData{
|
JSONData: plugins.JSONData{
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ type Plugin struct {
|
|||||||
Module string
|
Module string
|
||||||
BaseURL string
|
BaseURL string
|
||||||
|
|
||||||
AngularDetected bool
|
Angular plugins.AngularMeta
|
||||||
|
|
||||||
ExternalService *auth.ExternalService
|
ExternalService *auth.ExternalService
|
||||||
}
|
}
|
||||||
@@ -72,7 +72,8 @@ func ToGrafanaDTO(p *plugins.Plugin) Plugin {
|
|||||||
SignatureError: p.SignatureError,
|
SignatureError: p.SignatureError,
|
||||||
Module: p.Module,
|
Module: p.Module,
|
||||||
BaseURL: p.BaseURL,
|
BaseURL: p.BaseURL,
|
||||||
AngularDetected: p.AngularDetected,
|
|
||||||
ExternalService: p.ExternalService,
|
ExternalService: p.ExternalService,
|
||||||
|
|
||||||
|
Angular: p.Angular,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ export const OptionsPaneOptions = (props: OptionPaneRenderProps) => {
|
|||||||
return (
|
return (
|
||||||
<div className={styles.wrapper}>
|
<div className={styles.wrapper}>
|
||||||
<div className={styles.formBox}>
|
<div className={styles.formBox}>
|
||||||
{panel.isAngularPlugin() && (
|
{panel.isAngularPlugin() && !plugin.meta.angular?.hideDeprecation && (
|
||||||
<AngularDeprecationPluginNotice
|
<AngularDeprecationPluginNotice
|
||||||
className={styles.angularDeprecationWrapper}
|
className={styles.angularDeprecationWrapper}
|
||||||
showPluginDetailsLink={true}
|
showPluginDetailsLink={true}
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ import { DEFAULT_ANNOTATION_COLOR } from '@grafana/ui';
|
|||||||
import { GRID_CELL_HEIGHT, GRID_CELL_VMARGIN, GRID_COLUMN_COUNT, REPEAT_DIR_VERTICAL } from 'app/core/constants';
|
import { GRID_CELL_HEIGHT, GRID_CELL_VMARGIN, GRID_COLUMN_COUNT, REPEAT_DIR_VERTICAL } from 'app/core/constants';
|
||||||
import { contextSrv } from 'app/core/services/context_srv';
|
import { contextSrv } from 'app/core/services/context_srv';
|
||||||
import { sortedDeepCloneWithoutNulls } from 'app/core/utils/object';
|
import { sortedDeepCloneWithoutNulls } from 'app/core/utils/object';
|
||||||
import { isAngularDatasourcePlugin } from 'app/features/plugins/angularDeprecation/utils';
|
import { isAngularDatasourcePluginAndNotHidden } from 'app/features/plugins/angularDeprecation/utils';
|
||||||
import { variableAdapters } from 'app/features/variables/adapters';
|
import { variableAdapters } from 'app/features/variables/adapters';
|
||||||
import { onTimeRangeUpdated } from 'app/features/variables/state/actions';
|
import { onTimeRangeUpdated } from 'app/features/variables/state/actions';
|
||||||
import { GetVariables, getVariablesByKey } from 'app/features/variables/state/selectors';
|
import { GetVariables, getVariablesByKey } from 'app/features/variables/state/selectors';
|
||||||
@@ -1293,10 +1293,15 @@ export class DashboardModel implements TimeModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
hasAngularPlugins(): boolean {
|
hasAngularPlugins(): boolean {
|
||||||
return this.panels.some(
|
return this.panels.some((panel) => {
|
||||||
(panel) =>
|
// Return false for plugins that are angular but have angular.hideDeprecation = false
|
||||||
panel.isAngularPlugin() || (panel.datasource?.uid ? isAngularDatasourcePlugin(panel.datasource?.uid) : false)
|
const isAngularPanel = panel.isAngularPlugin() && !panel.plugin?.meta.angular?.hideDeprecation;
|
||||||
);
|
let isAngularDs = false;
|
||||||
|
if (panel.datasource?.uid) {
|
||||||
|
isAngularDs = isAngularDatasourcePluginAndNotHidden(panel.datasource?.uid);
|
||||||
|
}
|
||||||
|
return isAngularPanel || isAngularDs;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -620,7 +620,9 @@ export class PanelModel implements DataConfigSource, IPanelModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
isAngularPlugin(): boolean {
|
isAngularPlugin(): boolean {
|
||||||
return (this.plugin && this.plugin.angularPanelCtrl) !== undefined || (this.plugin?.meta?.angularDetected ?? false);
|
return (
|
||||||
|
(this.plugin && this.plugin.angularPanelCtrl) !== undefined || (this.plugin?.meta?.angular?.detected ?? false)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
destroy() {
|
destroy() {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { config, getTemplateSrv, locationService, reportInteraction } from '@gra
|
|||||||
import { PanelPadding } from '@grafana/ui';
|
import { PanelPadding } from '@grafana/ui';
|
||||||
import { InspectTab } from 'app/features/inspector/types';
|
import { InspectTab } from 'app/features/inspector/types';
|
||||||
import { getPanelLinksSupplier } from 'app/features/panel/panellinks/linkSuppliers';
|
import { getPanelLinksSupplier } from 'app/features/panel/panellinks/linkSuppliers';
|
||||||
import { isAngularDatasourcePlugin } from 'app/features/plugins/angularDeprecation/utils';
|
import { isAngularDatasourcePluginAndNotHidden } from 'app/features/plugins/angularDeprecation/utils';
|
||||||
|
|
||||||
import { PanelHeaderTitleItems } from '../dashgrid/PanelHeader/PanelHeaderTitleItems';
|
import { PanelHeaderTitleItems } from '../dashgrid/PanelHeader/PanelHeaderTitleItems';
|
||||||
import { DashboardModel, PanelModel } from '../state';
|
import { DashboardModel, PanelModel } from '../state';
|
||||||
@@ -85,9 +85,9 @@ export function getPanelChromeProps(props: CommonProps) {
|
|||||||
const alertState = props.data.alertState?.state;
|
const alertState = props.data.alertState?.state;
|
||||||
|
|
||||||
const isAngularDatasource = props.panel.datasource?.uid
|
const isAngularDatasource = props.panel.datasource?.uid
|
||||||
? isAngularDatasourcePlugin(props.panel.datasource?.uid)
|
? isAngularDatasourcePluginAndNotHidden(props.panel.datasource?.uid)
|
||||||
: false;
|
: false;
|
||||||
const isAngularPanel = props.panel.isAngularPlugin();
|
const isAngularPanel = props.panel.isAngularPlugin() && !props.plugin.meta.angular?.hideDeprecation;
|
||||||
const showAngularNotice =
|
const showAngularNotice =
|
||||||
(config.featureToggles.angularDeprecationUI ?? false) && (isAngularDatasource || isAngularPanel);
|
(config.featureToggles.angularDeprecationUI ?? false) && (isAngularDatasource || isAngularPanel);
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,16 @@
|
|||||||
|
import { DataSourceInstanceSettings } from '@grafana/data';
|
||||||
import { config } from '@grafana/runtime';
|
import { config } from '@grafana/runtime';
|
||||||
|
import { DataSourceJsonData } from '@grafana/schema';
|
||||||
|
|
||||||
|
function getDsInstanceSettingsByUid(dsUid: string): DataSourceInstanceSettings<DataSourceJsonData> | null {
|
||||||
|
return Object.values(config.datasources).find((ds) => ds.uid === dsUid) ?? null;
|
||||||
|
}
|
||||||
|
|
||||||
export function isAngularDatasourcePlugin(dsUid: string): boolean {
|
export function isAngularDatasourcePlugin(dsUid: string): boolean {
|
||||||
return Object.entries(config.datasources).some(([_, ds]) => {
|
return getDsInstanceSettingsByUid(dsUid)?.meta.angular?.detected ?? false;
|
||||||
return ds.uid === dsUid && ds.angularDetected;
|
}
|
||||||
});
|
|
||||||
|
export function isAngularDatasourcePluginAndNotHidden(dsUid: string): boolean {
|
||||||
|
const settings = getDsInstanceSettingsByUid(dsUid);
|
||||||
|
return (settings?.meta.angular?.detected && !settings?.meta.angular.hideDeprecation) ?? false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ function getPanelPlugin(meta: PanelPluginMeta): Promise<PanelPlugin> {
|
|||||||
return importPluginModule({
|
return importPluginModule({
|
||||||
path: meta.module,
|
path: meta.module,
|
||||||
version: meta.info?.version,
|
version: meta.info?.version,
|
||||||
isAngular: meta.angularDetected,
|
isAngular: meta.angular?.detected,
|
||||||
pluginId: meta.id,
|
pluginId: meta.id,
|
||||||
})
|
})
|
||||||
.then((pluginExports) => {
|
.then((pluginExports) => {
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ async function preload(config: AppPluginConfig): Promise<PluginPreloadResult> {
|
|||||||
const { plugin } = await pluginLoader.importPluginModule({
|
const { plugin } = await pluginLoader.importPluginModule({
|
||||||
path,
|
path,
|
||||||
version,
|
version,
|
||||||
isAngular: config.angularDetected,
|
isAngular: config.angular.detected,
|
||||||
pluginId,
|
pluginId,
|
||||||
});
|
});
|
||||||
const { extensionConfigs = [] } = plugin;
|
const { extensionConfigs = [] } = plugin;
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ export function importDataSourcePlugin(meta: DataSourcePluginMeta): Promise<Gene
|
|||||||
return importPluginModule({
|
return importPluginModule({
|
||||||
path: meta.module,
|
path: meta.module,
|
||||||
version: meta.info?.version,
|
version: meta.info?.version,
|
||||||
isAngular: meta.angularDetected,
|
isAngular: meta.angular?.detected,
|
||||||
pluginId: meta.id,
|
pluginId: meta.id,
|
||||||
}).then((pluginExports) => {
|
}).then((pluginExports) => {
|
||||||
if (pluginExports.plugin) {
|
if (pluginExports.plugin) {
|
||||||
@@ -107,7 +107,7 @@ export function importAppPlugin(meta: PluginMeta): Promise<AppPlugin> {
|
|||||||
return importPluginModule({
|
return importPluginModule({
|
||||||
path: meta.module,
|
path: meta.module,
|
||||||
version: meta.info?.version,
|
version: meta.info?.version,
|
||||||
isAngular: meta.angularDetected,
|
isAngular: meta.angular?.detected,
|
||||||
pluginId: meta.id,
|
pluginId: meta.id,
|
||||||
}).then((pluginExports) => {
|
}).then((pluginExports) => {
|
||||||
const plugin: AppPlugin = pluginExports.plugin ? pluginExports.plugin : new AppPlugin();
|
const plugin: AppPlugin = pluginExports.plugin ? pluginExports.plugin : new AppPlugin();
|
||||||
|
|||||||
@@ -127,16 +127,16 @@ describe('QueryGroup', () => {
|
|||||||
describe('Angular deprecation', () => {
|
describe('Angular deprecation', () => {
|
||||||
const deprecationText = /legacy platform based on AngularJS/i;
|
const deprecationText = /legacy platform based on AngularJS/i;
|
||||||
|
|
||||||
const oldAngularDetected = mockDS.angularDetected;
|
const oldAngularDetected = mockDS.meta.angular?.detected ?? false;
|
||||||
const oldDatasources = config.datasources;
|
const oldDatasources = config.datasources;
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
mockDS.angularDetected = oldAngularDetected;
|
mockDS.meta.angular = { detected: oldAngularDetected, hideDeprecation: false };
|
||||||
config.datasources = oldDatasources;
|
config.datasources = oldDatasources;
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Should render angular deprecation notice for angular plugins', async () => {
|
it('Should render angular deprecation notice for angular plugins', async () => {
|
||||||
mockDS.angularDetected = true;
|
mockDS.meta.angular = { detected: true, hideDeprecation: false };
|
||||||
config.datasources[mockDS.name] = mockDS;
|
config.datasources[mockDS.name] = mockDS;
|
||||||
renderScenario({});
|
renderScenario({});
|
||||||
await waitFor(async () => {
|
await waitFor(async () => {
|
||||||
@@ -145,7 +145,7 @@ describe('QueryGroup', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Should not render angular deprecation notice for non-angular plugins', async () => {
|
it('Should not render angular deprecation notice for non-angular plugins', async () => {
|
||||||
mockDS.angularDetected = false;
|
mockDS.meta.angular = { detected: false, hideDeprecation: false };
|
||||||
config.datasources[mockDS.name] = mockDS;
|
config.datasources[mockDS.name] = mockDS;
|
||||||
renderScenario({});
|
renderScenario({});
|
||||||
await waitFor(async () => {
|
await waitFor(async () => {
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ import { DashboardQueryEditor, isSharedDashboardQuery } from 'app/plugins/dataso
|
|||||||
import { GrafanaQuery } from 'app/plugins/datasource/grafana/types';
|
import { GrafanaQuery } from 'app/plugins/datasource/grafana/types';
|
||||||
import { QueryGroupOptions } from 'app/types';
|
import { QueryGroupOptions } from 'app/types';
|
||||||
|
|
||||||
import { isAngularDatasourcePlugin } from '../../plugins/angularDeprecation/utils';
|
import { isAngularDatasourcePluginAndNotHidden } from '../../plugins/angularDeprecation/utils';
|
||||||
import { PanelQueryRunner } from '../state/PanelQueryRunner';
|
import { PanelQueryRunner } from '../state/PanelQueryRunner';
|
||||||
import { updateQueries } from '../state/updateQueries';
|
import { updateQueries } from '../state/updateQueries';
|
||||||
|
|
||||||
@@ -255,7 +255,7 @@ export class QueryGroup extends PureComponent<Props, State> {
|
|||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
{dataSource && isAngularDatasourcePlugin(dataSource.uid) && (
|
{dataSource && isAngularDatasourcePluginAndNotHidden(dataSource.uid) && (
|
||||||
<AngularDeprecationPluginNotice
|
<AngularDeprecationPluginNotice
|
||||||
pluginId={dataSource.type}
|
pluginId={dataSource.type}
|
||||||
pluginType={PluginType.datasource}
|
pluginType={PluginType.datasource}
|
||||||
|
|||||||
Reference in New Issue
Block a user