diff --git a/.betterer.results b/.betterer.results index 329a99932a2..eab4907dff3 100644 --- a/.betterer.results +++ b/.betterer.results @@ -2747,17 +2747,7 @@ exports[`better eslint`] = { [0, 0, 0, "Unexpected any. Specify a different type.", "4"] ], "public/app/features/org/state/reducers.ts:5381": [ - [0, 0, 0, "Do not use any type assertions.", "0"], - [0, 0, 0, "Do not use any type assertions.", "1"] - ], - "public/app/features/panel/components/PanelPluginError.tsx:5381": [ - [0, 0, 0, "Unexpected any. Specify a different type.", "0"] - ], - "public/app/features/panel/components/PanelRenderer.tsx:5381": [ - [0, 0, 0, "Unexpected any. Specify a different type.", "0"], - [0, 0, 0, "Unexpected any. Specify a different type.", "1"], - [0, 0, 0, "Unexpected any. Specify a different type.", "2"], - [0, 0, 0, "Unexpected any. Specify a different type.", "3"] + [0, 0, 0, "Do not use any type assertions.", "0"] ], "public/app/features/panel/components/VizTypePicker/PanelTypeCard.tsx:5381": [ [0, 0, 0, "Use data-testid for E2E selectors instead of aria-label", "0"] @@ -2766,8 +2756,7 @@ exports[`better eslint`] = { [0, 0, 0, "Unexpected any. Specify a different type.", "0"] ], "public/app/features/panel/panellinks/linkSuppliers.ts:5381": [ - [0, 0, 0, "Unexpected any. Specify a different type.", "0"], - [0, 0, 0, "Do not use any type assertions.", "1"] + [0, 0, 0, "Unexpected any. Specify a different type.", "0"] ], "public/app/features/panel/panellinks/link_srv.ts:5381": [ [0, 0, 0, "Do not use any type assertions.", "0"], @@ -2775,9 +2764,7 @@ exports[`better eslint`] = { [0, 0, 0, "Unexpected any. Specify a different type.", "2"], [0, 0, 0, "Unexpected any. Specify a different type.", "3"], [0, 0, 0, "Unexpected any. Specify a different type.", "4"], - [0, 0, 0, "Unexpected any. Specify a different type.", "5"], - [0, 0, 0, "Unexpected any. Specify a different type.", "6"], - [0, 0, 0, "Unexpected any. Specify a different type.", "7"] + [0, 0, 0, "Unexpected any. Specify a different type.", "5"] ], "public/app/features/panel/state/actions.ts:5381": [ [0, 0, 0, "Unexpected any. Specify a different type.", "0"] @@ -2797,17 +2784,9 @@ exports[`better eslint`] = { [0, 0, 0, "Unexpected any. Specify a different type.", "3"], [0, 0, 0, "Unexpected any. Specify a different type.", "4"] ], - "public/app/features/plugins/admin/components/AppConfigWrapper.tsx:5381": [ - [0, 0, 0, "Unexpected any. Specify a different type.", "0"], - [0, 0, 0, "Unexpected any. Specify a different type.", "1"] - ], "public/app/features/plugins/admin/components/GetStartedWithPlugin/GetStartedWithDataSource.tsx:5381": [ [0, 0, 0, "Do not use any type assertions.", "0"] ], - "public/app/features/plugins/admin/components/PluginDashboards.tsx:5381": [ - [0, 0, 0, "Unexpected any. Specify a different type.", "0"], - [0, 0, 0, "Unexpected any. Specify a different type.", "1"] - ], "public/app/features/plugins/admin/components/PluginDetailsBody.tsx:5381": [ [0, 0, 0, "Do not use any type assertions.", "0"] ], @@ -2823,25 +2802,14 @@ exports[`better eslint`] = { "public/app/features/plugins/admin/components/SearchField.tsx:5381": [ [0, 0, 0, "Unexpected any. Specify a different type.", "0"] ], - "public/app/features/plugins/admin/helpers.ts:5381": [ - [0, 0, 0, "Do not use any type assertions.", "0"] - ], "public/app/features/plugins/admin/hooks/useHistory.tsx:5381": [ [0, 0, 0, "Unexpected any. Specify a different type.", "0"] ], "public/app/features/plugins/admin/pages/Browse.tsx:5381": [ [0, 0, 0, "Do not use any type assertions.", "0"], - [0, 0, 0, "Do not use any type assertions.", "1"], - [0, 0, 0, "Do not use any type assertions.", "2"], - [0, 0, 0, "Do not use any type assertions.", "3"] + [0, 0, 0, "Do not use any type assertions.", "1"] ], "public/app/features/plugins/admin/state/actions.ts:5381": [ - [0, 0, 0, "Do not use any type assertions.", "0"], - [0, 0, 0, "Do not use any type assertions.", "1"], - [0, 0, 0, "Do not use any type assertions.", "2"], - [0, 0, 0, "Do not use any type assertions.", "3"] - ], - "public/app/features/plugins/admin/state/selectors.ts:5381": [ [0, 0, 0, "Do not use any type assertions.", "0"] ], "public/app/features/plugins/admin/types.ts:5381": [ @@ -2929,18 +2897,13 @@ exports[`better eslint`] = { [0, 0, 0, "Use data-testid for E2E selectors instead of aria-label", "4"] ], "public/app/features/query/components/QueryEditorRowHeader.tsx:5381": [ - [0, 0, 0, "Do not use any type assertions.", "0"], - [0, 0, 0, "Unexpected any. Specify a different type.", "1"], - [0, 0, 0, "Use data-testid for E2E selectors instead of aria-label", "2"] + [0, 0, 0, "Use data-testid for E2E selectors instead of aria-label", "0"] ], "public/app/features/query/components/QueryGroup.tsx:5381": [ [0, 0, 0, "Use data-testid for E2E selectors instead of aria-label", "0"], [0, 0, 0, "Use data-testid for E2E selectors instead of aria-label", "1"], [0, 0, 0, "Use data-testid for E2E selectors instead of aria-label", "2"] ], - "public/app/features/query/components/QueryGroupOptions.tsx:5381": [ - [0, 0, 0, "Do not use any type assertions.", "0"] - ], "public/app/features/query/state/DashboardQueryRunner/AlertStatesWorker.test.ts:5381": [ [0, 0, 0, "Unexpected any. Specify a different type.", "0"], [0, 0, 0, "Unexpected any. Specify a different type.", "1"], diff --git a/public/app/features/org/state/reducers.ts b/public/app/features/org/state/reducers.ts index 9ce9f058cd6..d43850ffb2b 100644 --- a/public/app/features/org/state/reducers.ts +++ b/public/app/features/org/state/reducers.ts @@ -4,7 +4,7 @@ import { Organization, OrganizationState, UserOrg } from 'app/types'; export const initialState: OrganizationState = { organization: {} as Organization, - userOrgs: [] as UserOrg[], + userOrgs: [], }; const organizationSlice = createSlice({ diff --git a/public/app/features/panel/components/PanelPluginError.tsx b/public/app/features/panel/components/PanelPluginError.tsx index 0ce26af720f..168f5e1bd5e 100644 --- a/public/app/features/panel/components/PanelPluginError.tsx +++ b/public/app/features/panel/components/PanelPluginError.tsx @@ -32,7 +32,7 @@ class PanelPluginError extends PureComponent { } } -export function getPanelPluginLoadError(meta: PanelPluginMeta, err: any): PanelPlugin { +export function getPanelPluginLoadError(meta: PanelPluginMeta, err: unknown): PanelPlugin { const LoadError = class LoadError extends PureComponent { render() { const text = ( diff --git a/public/app/features/panel/components/PanelRenderer.tsx b/public/app/features/panel/components/PanelRenderer.tsx index 01217f1b5e1..b8cb634c1dc 100644 --- a/public/app/features/panel/components/PanelRenderer.tsx +++ b/public/app/features/panel/components/PanelRenderer.tsx @@ -17,7 +17,7 @@ import { importPanelPlugin, syncGetPanelPlugin } from '../../plugins/importPanel const defaultFieldConfig = { defaults: {}, overrides: [] }; -export function PanelRenderer

(props: PanelRendererProps) { +export function PanelRenderer

(props: PanelRendererProps) { const { pluginId, data, @@ -107,7 +107,7 @@ export function PanelRenderer

(pr ); } -function useOptionDefaults

( +function useOptionDefaults

( plugin: PanelPlugin | undefined, options: P, fieldConfig: FieldConfigSource diff --git a/public/app/features/panel/panellinks/linkSuppliers.ts b/public/app/features/panel/panellinks/linkSuppliers.ts index f3057cd3b51..ddadc88d044 100644 --- a/public/app/features/panel/panellinks/linkSuppliers.ts +++ b/public/app/features/panel/panellinks/linkSuppliers.ts @@ -126,7 +126,7 @@ export const getFieldLinksSupplier = (value: FieldDisplay): LinkModelSupplier { const finalVars: ScopedVars = { - ...(scopedVars as ScopedVars), + ...scopedVars, ...vars, }; return replaceVariables(value, finalVars, fmt); diff --git a/public/app/features/panel/panellinks/link_srv.ts b/public/app/features/panel/panellinks/link_srv.ts index 538b4e4f1fb..2fc1e764325 100644 --- a/public/app/features/panel/panellinks/link_srv.ts +++ b/public/app/features/panel/panellinks/link_srv.ts @@ -245,7 +245,11 @@ export const getCalculationValueDataLinksVariableSuggestions = (dataFrames: Data export interface LinkService { getDataLinkUIModel: (link: DataLink, replaceVariables: InterpolateFunction | undefined, origin: T) => LinkModel; - getAnchorInfo: (link: any) => any; + getAnchorInfo: (link: any) => { + href: string; + title: string; + tooltip: string; + }; getLinkUrl: (link: any) => string; } @@ -273,11 +277,11 @@ export class LinkSrv implements LinkService { getAnchorInfo(link: any) { const templateSrv = getTemplateSrv(); - const info: any = {}; - info.href = this.getLinkUrl(link); - info.title = templateSrv.replace(link.title || ''); - info.tooltip = templateSrv.replace(link.tooltip || ''); - return info; + return { + href: this.getLinkUrl(link), + title: templateSrv.replace(link.title || ''), + tooltip: templateSrv.replace(link.tooltip || ''), + }; } /** diff --git a/public/app/features/plugins/admin/components/AppConfigWrapper.tsx b/public/app/features/plugins/admin/components/AppConfigWrapper.tsx index f2f71509e88..4d97a8faa01 100644 --- a/public/app/features/plugins/admin/components/AppConfigWrapper.tsx +++ b/public/app/features/plugins/admin/components/AppConfigWrapper.tsx @@ -119,11 +119,11 @@ export class AppConfigCtrlWrapper extends PureComponent { }); }; - setPreUpdateHook = (callback: () => any) => { + setPreUpdateHook = (callback: () => Promise) => { this.preUpdateHook = callback; }; - setPostUpdateHook = (callback: () => any) => { + setPostUpdateHook = (callback: () => Promise) => { this.postUpdateHook = callback; }; diff --git a/public/app/features/plugins/admin/components/PluginDashboards.tsx b/public/app/features/plugins/admin/components/PluginDashboards.tsx index 8abc3bc6177..10e39ef7bd3 100644 --- a/public/app/features/plugins/admin/components/PluginDashboards.tsx +++ b/public/app/features/plugins/admin/components/PluginDashboards.tsx @@ -30,7 +30,7 @@ export class PluginDashboards extends PureComponent { const pluginId = this.props.plugin.id; getBackendSrv() .get(`/api/plugins/${pluginId}/dashboards`) - .then((dashboards: any) => { + .then((dashboards) => { this.setState({ dashboards, loading: false }); }); } @@ -59,22 +59,22 @@ export class PluginDashboards extends PureComponent { import = (dash: PluginDashboard, overwrite: boolean) => { const { plugin, datasource } = this.props; - const installCmd: any = { + const installCmd = { pluginId: plugin.id, path: dash.path, overwrite: overwrite, - inputs: [], + inputs: datasource + ? [ + { + name: '*', + type: 'datasource', + pluginId: datasource.meta.id, + value: datasource.name, + }, + ] + : [], }; - if (datasource) { - installCmd.inputs.push({ - name: '*', - type: 'datasource', - pluginId: datasource.meta.id, - value: datasource.name, - }); - } - return getBackendSrv() .post(`/api/dashboards/import`, installCmd) .then((res: PluginDashboard) => { diff --git a/public/app/features/plugins/admin/helpers.ts b/public/app/features/plugins/admin/helpers.ts index e9460d2ded4..2aef24cb1e7 100644 --- a/public/app/features/plugins/admin/helpers.ts +++ b/public/app/features/plugins/admin/helpers.ts @@ -223,13 +223,10 @@ export const sortPlugins = (plugins: CatalogPlugin[], sortBy: Sorters) => { }; function groupErrorsByPluginId(errors: PluginError[] = []): Record { - return errors.reduce( - (byId, error) => { - byId[error.pluginId] = error; - return byId; - }, - {} as Record - ); + return errors.reduce>((byId, error) => { + byId[error.pluginId] = error; + return byId; + }, {}); } function getPluginSignature(options: { diff --git a/public/app/features/plugins/admin/pages/Browse.tsx b/public/app/features/plugins/admin/pages/Browse.tsx index b1495278d52..3db73e36650 100644 --- a/public/app/features/plugins/admin/pages/Browse.tsx +++ b/public/app/features/plugins/admin/pages/Browse.tsx @@ -27,8 +27,8 @@ export default function Browse({ route }: GrafanaRouteComponentProps): ReactElem const styles = useStyles2(getStyles); const history = useHistory(); const remotePluginsAvailable = useIsRemotePluginsAvailable(); - const keyword = (locationSearch.q as string) || ''; - const filterBy = (locationSearch.filterBy as string) || 'installed'; + const keyword = locationSearch.q?.toString() || ''; + const filterBy = locationSearch.filterBy?.toString() || 'installed'; const filterByType = (locationSearch.filterByType as PluginType | 'all') || 'all'; const sortBy = (locationSearch.sortBy as Sorters) || Sorters.nameAsc; const { isLoading, error, plugins } = useGetAll( diff --git a/public/app/features/plugins/admin/state/actions.ts b/public/app/features/plugins/admin/state/actions.ts index 3b604ee5d55..fb5cac89dbc 100644 --- a/public/app/features/plugins/admin/state/actions.ts +++ b/public/app/features/plugins/admin/state/actions.ts @@ -56,66 +56,76 @@ export const fetchRemotePlugins = createAsyncThunk { - try { - const details = await getPluginDetails(id); - - return { - id, - changes: { details }, - } as Update; - } catch (e) { - return thunkApi.rejectWithValue('Unknown error.'); - } -}); - -// We are also using the install API endpoint to update the plugin -export const install = createAsyncThunk( - `${STATE_PREFIX}/install`, - async ({ id, version, isUpdating = false }: { id: string; version?: string; isUpdating?: boolean }, thunkApi) => { - const changes = isUpdating - ? { isInstalled: true, installedVersion: version, hasUpdate: false } - : { isInstalled: true, installedVersion: version }; +export const fetchDetails = createAsyncThunk, string>( + `${STATE_PREFIX}/fetchDetails`, + async (id: string, thunkApi) => { try { - await installPlugin(id); - await updatePanels(); + const details = await getPluginDetails(id); - if (isUpdating) { - invalidatePluginInCache(id); - } - - return { id, changes } as Update; + return { + id, + changes: { details }, + }; } catch (e) { - console.error(e); - if (isFetchError(e)) { - return thunkApi.rejectWithValue(e.data); - } - return thunkApi.rejectWithValue('Unknown error.'); } } ); -export const unsetInstall = createAsyncThunk(`${STATE_PREFIX}/install`, async () => ({})); - -export const uninstall = createAsyncThunk(`${STATE_PREFIX}/uninstall`, async (id: string, thunkApi) => { +// We are also using the install API endpoint to update the plugin +export const install = createAsyncThunk< + Update, + { + id: string; + version?: string; + isUpdating?: boolean; + } +>(`${STATE_PREFIX}/install`, async ({ id, version, isUpdating = false }, thunkApi) => { + const changes = isUpdating + ? { isInstalled: true, installedVersion: version, hasUpdate: false } + : { isInstalled: true, installedVersion: version }; try { - await uninstallPlugin(id); + await installPlugin(id); await updatePanels(); - invalidatePluginInCache(id); + if (isUpdating) { + invalidatePluginInCache(id); + } - return { - id, - changes: { isInstalled: false, installedVersion: undefined }, - } as Update; + return { id, changes }; } catch (e) { console.error(e); + if (isFetchError(e)) { + return thunkApi.rejectWithValue(e.data); + } return thunkApi.rejectWithValue('Unknown error.'); } }); +export const unsetInstall = createAsyncThunk(`${STATE_PREFIX}/install`, async () => ({})); + +export const uninstall = createAsyncThunk, string>( + `${STATE_PREFIX}/uninstall`, + async (id, thunkApi) => { + try { + await uninstallPlugin(id); + await updatePanels(); + + invalidatePluginInCache(id); + + return { + id, + changes: { isInstalled: false, installedVersion: undefined }, + }; + } catch (e) { + console.error(e); + + return thunkApi.rejectWithValue('Unknown error.'); + } + } +); + // We need this to be backwards-compatible with other parts of Grafana. // (Originally in "public/app/features/plugins/state/actions.ts") // TODO diff --git a/public/app/features/plugins/admin/state/selectors.ts b/public/app/features/plugins/admin/state/selectors.ts index c8360328d17..c794296fa43 100644 --- a/public/app/features/plugins/admin/state/selectors.ts +++ b/public/app/features/plugins/admin/state/selectors.ts @@ -1,6 +1,6 @@ import { createSelector } from '@reduxjs/toolkit'; -import { PluginError, PluginErrorCode, PluginType, unEscapeStringFromRegex } from '@grafana/data'; +import { PluginError, PluginType, unEscapeStringFromRegex } from '@grafana/data'; import { RequestStatus, PluginCatalogStoreState } from '../types'; @@ -63,18 +63,19 @@ export const selectPlugins = (filters: PluginFilters) => }); }); -export const selectPluginErrors = createSelector(selectAll, (plugins) => - plugins - ? plugins - .filter((p) => Boolean(p.error)) - .map( - (p): PluginError => ({ - pluginId: p.id, - errorCode: p!.error as PluginErrorCode, - }) - ) - : [] -); +export const selectPluginErrors = createSelector(selectAll, (plugins) => { + const pluginErrors: PluginError[] = []; + for (const plugin of plugins) { + if (plugin.error) { + pluginErrors.push({ + pluginId: plugin.id, + errorCode: plugin.error, + }); + } + } + + return pluginErrors; +}); // The following selectors are used to get information about the outstanding or completed plugins-related network requests. export const selectRequest = (actionType: string) => diff --git a/public/app/features/query/components/QueryEditorRowHeader.tsx b/public/app/features/query/components/QueryEditorRowHeader.tsx index ded3cc44677..5aeb7397493 100644 --- a/public/app/features/query/components/QueryEditorRowHeader.tsx +++ b/public/app/features/query/components/QueryEditorRowHeader.tsx @@ -71,9 +71,9 @@ export const QueryEditorRowHeader = (props: Props { + const onKeyDown = (event: React.KeyboardEvent) => { if (event.key === 'Enter') { - onEndEditName((event.target as any).value); + onEndEditName(event.currentTarget.value); } }; diff --git a/public/app/features/query/components/QueryGroupOptions.tsx b/public/app/features/query/components/QueryGroupOptions.tsx index c450821d32b..c10da8f313d 100644 --- a/public/app/features/query/components/QueryGroupOptions.tsx +++ b/public/app/features/query/components/QueryGroupOptions.tsx @@ -129,7 +129,7 @@ export class QueryGroupOptionsEditor extends PureComponent { onMaxDataPointsBlur = (event: ChangeEvent) => { const { options, onChange } = this.props; - let maxDataPoints: number | null = parseInt(event.target.value as string, 10); + let maxDataPoints: number | null = parseInt(event.currentTarget.value, 10); if (isNaN(maxDataPoints) || maxDataPoints === 0) { maxDataPoints = null;