mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Chore: Add type info for grafana boot data (#45322)
Co-authored-by: Levente Balogh <balogh.levente.hu@gmail.com>
This commit is contained in:
parent
6889e39526
commit
f1c3177e79
@ -200,7 +200,7 @@ exports[`no enzyme tests`] = {
|
|||||||
"public/app/features/dashboard/components/SaveDashboard/forms/SaveDashboardForm.test.tsx:1262111696": [
|
"public/app/features/dashboard/components/SaveDashboard/forms/SaveDashboardForm.test.tsx:1262111696": [
|
||||||
[1, 17, 13, "RegExp match", "2409514259"]
|
[1, 17, 13, "RegExp match", "2409514259"]
|
||||||
],
|
],
|
||||||
"public/app/features/dashboard/components/ShareModal/ShareLink.test.tsx:1044891955": [
|
"public/app/features/dashboard/components/ShareModal/ShareLink.test.tsx:809006195": [
|
||||||
[1, 35, 13, "RegExp match", "2409514259"]
|
[1, 35, 13, "RegExp match", "2409514259"]
|
||||||
],
|
],
|
||||||
"public/app/features/dashboard/dashgrid/DashboardGrid.test.tsx:1798654441": [
|
"public/app/features/dashboard/dashgrid/DashboardGrid.test.tsx:1798654441": [
|
||||||
|
@ -5,6 +5,7 @@ import { SystemDateFormatSettings } from '../datetime';
|
|||||||
import { GrafanaTheme2 } from '../themes';
|
import { GrafanaTheme2 } from '../themes';
|
||||||
import { MapLayerOptions } from '../geo/layer';
|
import { MapLayerOptions } from '../geo/layer';
|
||||||
import { FeatureToggles } from './featureToggles.gen';
|
import { FeatureToggles } from './featureToggles.gen';
|
||||||
|
import { NavLinkDTO, OrgRole } from '.';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Describes the build information that will be available via the Grafana configuration.
|
* Describes the build information that will be available via the Grafana configuration.
|
||||||
@ -85,10 +86,47 @@ export type OAuth =
|
|||||||
*/
|
*/
|
||||||
export type OAuthSettings = Partial<Record<OAuth, { name: string; icon?: string }>>;
|
export type OAuthSettings = Partial<Record<OAuth, { name: string; icon?: string }>>;
|
||||||
|
|
||||||
|
/** Current user info included in bootData
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
export interface CurrentUserDTO {
|
||||||
|
isSignedIn: boolean;
|
||||||
|
id: number;
|
||||||
|
login: string;
|
||||||
|
email: string;
|
||||||
|
name: string;
|
||||||
|
lightTheme: boolean;
|
||||||
|
orgCount: number;
|
||||||
|
orgId: number;
|
||||||
|
orgName: string;
|
||||||
|
orgRole: OrgRole | '';
|
||||||
|
isGrafanaAdmin: boolean;
|
||||||
|
gravatarUrl: string;
|
||||||
|
timezone: string;
|
||||||
|
weekStart: string;
|
||||||
|
locale: string;
|
||||||
|
permissions?: Record<string, boolean>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Contains essential user and config info
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
export interface BootData {
|
||||||
|
user: CurrentUserDTO;
|
||||||
|
settings: GrafanaConfig;
|
||||||
|
navTree: NavLinkDTO[];
|
||||||
|
themePaths: {
|
||||||
|
light: string;
|
||||||
|
dark: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Describes all the different Grafana configuration values available for an instance.
|
* Describes all the different Grafana configuration values available for an instance.
|
||||||
*
|
*
|
||||||
* @public
|
* @internal
|
||||||
*/
|
*/
|
||||||
export interface GrafanaConfig {
|
export interface GrafanaConfig {
|
||||||
datasources: { [str: string]: DataSourceInstanceSettings };
|
datasources: { [str: string]: DataSourceInstanceSettings };
|
||||||
@ -98,7 +136,7 @@ export interface GrafanaConfig {
|
|||||||
windowTitlePrefix: string;
|
windowTitlePrefix: string;
|
||||||
buildInfo: BuildInfo;
|
buildInfo: BuildInfo;
|
||||||
newPanelTitle: string;
|
newPanelTitle: string;
|
||||||
bootData: any;
|
bootData: BootData;
|
||||||
externalUserMngLinkUrl: string;
|
externalUserMngLinkUrl: string;
|
||||||
externalUserMngLinkName: string;
|
externalUserMngLinkName: string;
|
||||||
externalUserMngInfo: string;
|
externalUserMngInfo: string;
|
||||||
@ -120,9 +158,9 @@ export interface GrafanaConfig {
|
|||||||
verifyEmailEnabled: boolean;
|
verifyEmailEnabled: boolean;
|
||||||
oauth: OAuthSettings;
|
oauth: OAuthSettings;
|
||||||
disableUserSignUp: boolean;
|
disableUserSignUp: boolean;
|
||||||
loginHint: any;
|
loginHint: string;
|
||||||
passwordHint: any;
|
passwordHint: string;
|
||||||
loginError: any;
|
loginError?: string;
|
||||||
navTree: any;
|
navTree: any;
|
||||||
viewersCanEdit: boolean;
|
viewersCanEdit: boolean;
|
||||||
editorsCanAdmin: boolean;
|
editorsCanAdmin: boolean;
|
||||||
|
@ -36,7 +36,16 @@ export * from './live';
|
|||||||
export * from './variables';
|
export * from './variables';
|
||||||
export * from './geometry';
|
export * from './geometry';
|
||||||
export { isUnsignedPluginSignature } from './pluginSignature';
|
export { isUnsignedPluginSignature } from './pluginSignature';
|
||||||
export { OAuth, OAuthSettings, GrafanaConfig, BuildInfo, LicenseInfo, PreloadPlugin } from './config';
|
export {
|
||||||
|
CurrentUserDTO,
|
||||||
|
BootData,
|
||||||
|
OAuth,
|
||||||
|
OAuthSettings,
|
||||||
|
GrafanaConfig,
|
||||||
|
BuildInfo,
|
||||||
|
LicenseInfo,
|
||||||
|
PreloadPlugin,
|
||||||
|
} from './config';
|
||||||
export { FeatureToggles } from './featureToggles.gen';
|
export { FeatureToggles } from './featureToggles.gen';
|
||||||
export * from './alerts';
|
export * from './alerts';
|
||||||
export * from './slider';
|
export * from './slider';
|
||||||
|
@ -1,21 +1,28 @@
|
|||||||
import { ComponentType } from 'react';
|
import { ComponentType } from 'react';
|
||||||
|
|
||||||
export interface NavModelItem {
|
export interface NavLinkDTO {
|
||||||
|
id?: string;
|
||||||
text: string;
|
text: string;
|
||||||
url?: string;
|
description?: string;
|
||||||
|
section?: NavSection;
|
||||||
subTitle?: string;
|
subTitle?: string;
|
||||||
icon?: string;
|
icon?: string;
|
||||||
img?: string;
|
img?: string;
|
||||||
id?: string;
|
url?: string;
|
||||||
active?: boolean;
|
|
||||||
hideFromTabs?: boolean;
|
|
||||||
hideFromMenu?: boolean;
|
|
||||||
divider?: boolean;
|
|
||||||
children?: NavModelItem[];
|
|
||||||
breadcrumbs?: NavModelBreadcrumb[];
|
|
||||||
target?: string;
|
target?: string;
|
||||||
|
sortWeight?: number;
|
||||||
|
divider?: boolean;
|
||||||
|
hideFromMenu?: boolean;
|
||||||
|
hideFromTabs?: boolean;
|
||||||
|
children?: NavLinkDTO[];
|
||||||
|
highlightText?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface NavModelItem extends NavLinkDTO {
|
||||||
|
children?: NavModelItem[];
|
||||||
|
active?: boolean;
|
||||||
|
breadcrumbs?: NavModelBreadcrumb[];
|
||||||
parentItem?: NavModelItem;
|
parentItem?: NavModelItem;
|
||||||
section?: NavSection;
|
|
||||||
showOrgSwitcher?: boolean;
|
showOrgSwitcher?: boolean;
|
||||||
onClick?: () => void;
|
onClick?: () => void;
|
||||||
menuItemType?: NavMenuItemType;
|
menuItemType?: NavMenuItemType;
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { merge } from 'lodash';
|
import { merge } from 'lodash';
|
||||||
import {
|
import {
|
||||||
|
BootData,
|
||||||
BuildInfo,
|
BuildInfo,
|
||||||
createTheme,
|
createTheme,
|
||||||
DataSourceInstanceSettings,
|
DataSourceInstanceSettings,
|
||||||
@ -28,9 +29,9 @@ export class GrafanaBootConfig implements GrafanaConfig {
|
|||||||
appUrl = '';
|
appUrl = '';
|
||||||
appSubUrl = '';
|
appSubUrl = '';
|
||||||
windowTitlePrefix = '';
|
windowTitlePrefix = '';
|
||||||
buildInfo: BuildInfo = {} as BuildInfo;
|
buildInfo: BuildInfo;
|
||||||
newPanelTitle = '';
|
newPanelTitle = '';
|
||||||
bootData: any;
|
bootData: BootData;
|
||||||
externalUserMngLinkUrl = '';
|
externalUserMngLinkUrl = '';
|
||||||
externalUserMngLinkName = '';
|
externalUserMngLinkName = '';
|
||||||
externalUserMngInfo = '';
|
externalUserMngInfo = '';
|
||||||
@ -54,9 +55,9 @@ export class GrafanaBootConfig implements GrafanaConfig {
|
|||||||
verifyEmailEnabled = false;
|
verifyEmailEnabled = false;
|
||||||
oauth: OAuthSettings = {};
|
oauth: OAuthSettings = {};
|
||||||
disableUserSignUp = false;
|
disableUserSignUp = false;
|
||||||
loginHint: any;
|
loginHint = '';
|
||||||
passwordHint: any;
|
passwordHint = '';
|
||||||
loginError: any;
|
loginError = undefined;
|
||||||
navTree: any;
|
navTree: any;
|
||||||
viewersCanEdit = false;
|
viewersCanEdit = false;
|
||||||
editorsCanAdmin = false;
|
editorsCanAdmin = false;
|
||||||
@ -117,6 +118,8 @@ export class GrafanaBootConfig implements GrafanaConfig {
|
|||||||
const mode = options.bootData.user.lightTheme ? 'light' : 'dark';
|
const mode = options.bootData.user.lightTheme ? 'light' : 'dark';
|
||||||
this.theme2 = createTheme({ colors: { mode } });
|
this.theme2 = createTheme({ colors: { mode } });
|
||||||
this.theme = this.theme2.v1;
|
this.theme = this.theme2.v1;
|
||||||
|
this.bootData = options.bootData;
|
||||||
|
this.buildInfo = options.buildInfo;
|
||||||
|
|
||||||
const defaults = {
|
const defaults = {
|
||||||
datasources: {},
|
datasources: {},
|
||||||
|
@ -57,7 +57,7 @@ const (
|
|||||||
|
|
||||||
type NavLink struct {
|
type NavLink struct {
|
||||||
Id string `json:"id,omitempty"`
|
Id string `json:"id,omitempty"`
|
||||||
Text string `json:"text,omitempty"`
|
Text string `json:"text"`
|
||||||
Description string `json:"description,omitempty"`
|
Description string `json:"description,omitempty"`
|
||||||
Section string `json:"section,omitempty"`
|
Section string `json:"section,omitempty"`
|
||||||
SubTitle string `json:"subTitle,omitempty"`
|
SubTitle string `json:"subTitle,omitempty"`
|
||||||
|
@ -1,46 +1,49 @@
|
|||||||
import coreModule from 'app/angular/core_module';
|
import coreModule from 'app/angular/core_module';
|
||||||
import config from 'app/core/config';
|
import config from 'app/core/config';
|
||||||
import { find, isNumber } from 'lodash';
|
import { NavModel, NavModelItem } from '@grafana/data';
|
||||||
import { NavModel } from '@grafana/data';
|
|
||||||
|
interface Nav {
|
||||||
|
breadcrumbs: NavModelItem[];
|
||||||
|
node?: NavModelItem;
|
||||||
|
main?: NavModelItem;
|
||||||
|
}
|
||||||
|
|
||||||
export class NavModelSrv {
|
export class NavModelSrv {
|
||||||
navItems: any;
|
navItems: NavModelItem[];
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.navItems = config.bootData.navTree;
|
this.navItems = config.bootData.navTree;
|
||||||
}
|
}
|
||||||
|
|
||||||
getCfgNode() {
|
getCfgNode() {
|
||||||
return find(this.navItems, { id: 'cfg' });
|
return this.navItems.find((navItem) => navItem.id === 'cfg');
|
||||||
}
|
}
|
||||||
|
|
||||||
getNav(...args: Array<string | number>) {
|
getNav(...args: Array<string | number>) {
|
||||||
let children = this.navItems;
|
let children = this.navItems;
|
||||||
const nav = {
|
const nav: Nav = {
|
||||||
breadcrumbs: [],
|
breadcrumbs: [],
|
||||||
} as any;
|
};
|
||||||
|
|
||||||
for (const id of args) {
|
for (const id of args) {
|
||||||
// if its a number then it's the index to use for main
|
// if its a number then it's the index to use for main
|
||||||
if (isNumber(id)) {
|
if (typeof id === 'number') {
|
||||||
nav.main = nav.breadcrumbs[id];
|
nav.main = nav.breadcrumbs[id];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
const node: any = find(children, { id: id });
|
const node = children.find((child) => child.id === id);
|
||||||
nav.breadcrumbs.push(node);
|
if (node) {
|
||||||
nav.node = node;
|
nav.breadcrumbs.push(node);
|
||||||
nav.main = node;
|
nav.node = node;
|
||||||
children = node.children;
|
nav.main = node;
|
||||||
|
children = node.children ?? [];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nav.main.children) {
|
if (nav.main?.children) {
|
||||||
for (const item of nav.main.children) {
|
for (const item of nav.main.children) {
|
||||||
item.active = false;
|
item.active = item.url === nav.node?.url;
|
||||||
|
|
||||||
if (item.url === nav.node.url) {
|
|
||||||
item.active = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,25 +1,30 @@
|
|||||||
import config from '../../core/config';
|
import config from '../../core/config';
|
||||||
import { extend } from 'lodash';
|
import { extend } from 'lodash';
|
||||||
import { rangeUtil, WithAccessControlMetadata } from '@grafana/data';
|
import { OrgRole, rangeUtil, WithAccessControlMetadata } from '@grafana/data';
|
||||||
import { AccessControlAction, UserPermission } from 'app/types';
|
import { AccessControlAction, UserPermission } from 'app/types';
|
||||||
import { featureEnabled, getBackendSrv } from '@grafana/runtime';
|
import { featureEnabled, getBackendSrv } from '@grafana/runtime';
|
||||||
|
import { CurrentUserInternal } from 'app/types/config';
|
||||||
|
|
||||||
export class User {
|
export class User implements CurrentUserInternal {
|
||||||
|
isSignedIn: boolean;
|
||||||
id: number;
|
id: number;
|
||||||
isGrafanaAdmin: any;
|
login: string;
|
||||||
isSignedIn: any;
|
email: string;
|
||||||
orgRole: any;
|
name: string;
|
||||||
|
lightTheme: boolean;
|
||||||
|
orgCount: number;
|
||||||
orgId: number;
|
orgId: number;
|
||||||
orgName: string;
|
orgName: string;
|
||||||
login: string;
|
orgRole: OrgRole | '';
|
||||||
orgCount: number;
|
isGrafanaAdmin: boolean;
|
||||||
|
gravatarUrl: string;
|
||||||
timezone: string;
|
timezone: string;
|
||||||
fiscalYearStartMonth: number;
|
weekStart: string;
|
||||||
|
locale: string;
|
||||||
helpFlags1: number;
|
helpFlags1: number;
|
||||||
lightTheme: boolean;
|
|
||||||
hasEditPermissionInFolders: boolean;
|
hasEditPermissionInFolders: boolean;
|
||||||
email?: string;
|
|
||||||
permissions?: UserPermission;
|
permissions?: UserPermission;
|
||||||
|
fiscalYearStartMonth: number;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.id = 0;
|
this.id = 0;
|
||||||
@ -35,7 +40,12 @@ export class User {
|
|||||||
this.helpFlags1 = 0;
|
this.helpFlags1 = 0;
|
||||||
this.lightTheme = false;
|
this.lightTheme = false;
|
||||||
this.hasEditPermissionInFolders = false;
|
this.hasEditPermissionInFolders = false;
|
||||||
this.email = undefined;
|
this.email = '';
|
||||||
|
this.name = '';
|
||||||
|
this.locale = '';
|
||||||
|
this.weekStart = '';
|
||||||
|
this.gravatarUrl = '';
|
||||||
|
|
||||||
if (config.bootData.user) {
|
if (config.bootData.user) {
|
||||||
extend(this, config.bootData.user);
|
extend(this, config.bootData.user);
|
||||||
}
|
}
|
||||||
@ -55,7 +65,7 @@ export class ContextSrv {
|
|||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
if (!config.bootData) {
|
if (!config.bootData) {
|
||||||
config.bootData = { user: {}, settings: {} };
|
config.bootData = { user: {}, settings: {} } as any;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.user = new User();
|
this.user = new User();
|
||||||
@ -180,7 +190,7 @@ export { contextSrv };
|
|||||||
|
|
||||||
export const setContextSrv = (override: ContextSrv) => {
|
export const setContextSrv = (override: ContextSrv) => {
|
||||||
if (process.env.NODE_ENV !== 'test') {
|
if (process.env.NODE_ENV !== 'test') {
|
||||||
throw new Error('contextSrv can be only overriden in test environment');
|
throw new Error('contextSrv can be only overridden in test environment');
|
||||||
}
|
}
|
||||||
contextSrv = override;
|
contextSrv = override;
|
||||||
};
|
};
|
||||||
|
@ -53,7 +53,7 @@ describe('ShareEmbed', () => {
|
|||||||
user: {
|
user: {
|
||||||
orgId: 1,
|
orgId: 1,
|
||||||
},
|
},
|
||||||
};
|
} as any;
|
||||||
});
|
});
|
||||||
|
|
||||||
afterAll(() => {
|
afterAll(() => {
|
||||||
|
@ -110,7 +110,7 @@ describe('ShareModal', () => {
|
|||||||
user: {
|
user: {
|
||||||
orgId: 1,
|
orgId: 1,
|
||||||
},
|
},
|
||||||
};
|
} as any;
|
||||||
ctx.mount({
|
ctx.mount({
|
||||||
panel: new PanelModel({ id: 22, options: {}, fieldConfig: { defaults: {}, overrides: [] } }),
|
panel: new PanelModel({ id: 22, options: {}, fieldConfig: { defaults: {}, overrides: [] } }),
|
||||||
});
|
});
|
||||||
@ -202,7 +202,7 @@ describe('when default_home_dashboard_path is set in the grafana config', () =>
|
|||||||
user: {
|
user: {
|
||||||
orgId: 1,
|
orgId: 1,
|
||||||
},
|
},
|
||||||
};
|
} as any;
|
||||||
});
|
});
|
||||||
|
|
||||||
afterAll(() => {
|
afterAll(() => {
|
||||||
|
@ -36,7 +36,7 @@ describe('buildParams', () => {
|
|||||||
to: 2000,
|
to: 2000,
|
||||||
raw: { from: 'now-6h', to: 'now' },
|
raw: { from: 'now-6h', to: 'now' },
|
||||||
} as unknown as TimeRange;
|
} as unknown as TimeRange;
|
||||||
const orgId = '2';
|
const orgId = 2;
|
||||||
const result = buildParams({ useCurrentTimeRange, selectedTheme, panel, search, range, orgId });
|
const result = buildParams({ useCurrentTimeRange, selectedTheme, panel, search, range, orgId });
|
||||||
|
|
||||||
expect(result.toString()).toEqual(expected);
|
expect(result.toString()).toEqual(expected);
|
||||||
|
@ -9,7 +9,7 @@ export interface BuildParamsArgs {
|
|||||||
panel?: PanelModel;
|
panel?: PanelModel;
|
||||||
search?: string;
|
search?: string;
|
||||||
range?: TimeRange;
|
range?: TimeRange;
|
||||||
orgId?: string;
|
orgId?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function buildParams({
|
export function buildParams({
|
||||||
@ -24,7 +24,7 @@ export function buildParams({
|
|||||||
|
|
||||||
searchParams.set('from', String(range.from.valueOf()));
|
searchParams.set('from', String(range.from.valueOf()));
|
||||||
searchParams.set('to', String(range.to.valueOf()));
|
searchParams.set('to', String(range.to.valueOf()));
|
||||||
searchParams.set('orgId', orgId);
|
searchParams.set('orgId', String(orgId));
|
||||||
|
|
||||||
if (!useCurrentTimeRange) {
|
if (!useCurrentTimeRange) {
|
||||||
searchParams.delete('from');
|
searchParams.delete('from');
|
||||||
|
@ -44,7 +44,7 @@ describe('grafanaGraph', () => {
|
|||||||
user: {
|
user: {
|
||||||
lightTheme: false,
|
lightTheme: false,
|
||||||
},
|
},
|
||||||
};
|
} as any;
|
||||||
Object.assign(GraphCtrl.prototype, {
|
Object.assign(GraphCtrl.prototype, {
|
||||||
...MetricsPanelCtrl.prototype,
|
...MetricsPanelCtrl.prototype,
|
||||||
...PanelCtrl.prototype,
|
...PanelCtrl.prototype,
|
||||||
|
@ -1,12 +1,10 @@
|
|||||||
/**
|
/**
|
||||||
* UserPermission is a map storing permissions in a form of
|
* UserPermission is a map storing permissions in a form of
|
||||||
* {
|
* {
|
||||||
* action: { scope: scope }
|
* action: true;
|
||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
export type UserPermission = {
|
export type UserPermission = Record<string, boolean>;
|
||||||
[key: string]: { [key: string]: string };
|
|
||||||
};
|
|
||||||
|
|
||||||
// Permission actions
|
// Permission actions
|
||||||
export enum AccessControlAction {
|
export enum AccessControlAction {
|
||||||
|
9
public/app/types/config.ts
Normal file
9
public/app/types/config.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import { CurrentUserDTO } from '@grafana/data';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extends `CurrentUserDTO` with some properties meant only for internal use.
|
||||||
|
*/
|
||||||
|
export interface CurrentUserInternal extends CurrentUserDTO {
|
||||||
|
helpFlags1: number;
|
||||||
|
hasEditPermissionInFolders: boolean;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user