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": [
|
||||
[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"]
|
||||
],
|
||||
"public/app/features/dashboard/dashgrid/DashboardGrid.test.tsx:1798654441": [
|
||||
|
@ -5,6 +5,7 @@ import { SystemDateFormatSettings } from '../datetime';
|
||||
import { GrafanaTheme2 } from '../themes';
|
||||
import { MapLayerOptions } from '../geo/layer';
|
||||
import { FeatureToggles } from './featureToggles.gen';
|
||||
import { NavLinkDTO, OrgRole } from '.';
|
||||
|
||||
/**
|
||||
* 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 }>>;
|
||||
|
||||
/** 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.
|
||||
*
|
||||
* @public
|
||||
* @internal
|
||||
*/
|
||||
export interface GrafanaConfig {
|
||||
datasources: { [str: string]: DataSourceInstanceSettings };
|
||||
@ -98,7 +136,7 @@ export interface GrafanaConfig {
|
||||
windowTitlePrefix: string;
|
||||
buildInfo: BuildInfo;
|
||||
newPanelTitle: string;
|
||||
bootData: any;
|
||||
bootData: BootData;
|
||||
externalUserMngLinkUrl: string;
|
||||
externalUserMngLinkName: string;
|
||||
externalUserMngInfo: string;
|
||||
@ -120,9 +158,9 @@ export interface GrafanaConfig {
|
||||
verifyEmailEnabled: boolean;
|
||||
oauth: OAuthSettings;
|
||||
disableUserSignUp: boolean;
|
||||
loginHint: any;
|
||||
passwordHint: any;
|
||||
loginError: any;
|
||||
loginHint: string;
|
||||
passwordHint: string;
|
||||
loginError?: string;
|
||||
navTree: any;
|
||||
viewersCanEdit: boolean;
|
||||
editorsCanAdmin: boolean;
|
||||
|
@ -36,7 +36,16 @@ export * from './live';
|
||||
export * from './variables';
|
||||
export * from './geometry';
|
||||
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 * from './alerts';
|
||||
export * from './slider';
|
||||
|
@ -1,21 +1,28 @@
|
||||
import { ComponentType } from 'react';
|
||||
|
||||
export interface NavModelItem {
|
||||
export interface NavLinkDTO {
|
||||
id?: string;
|
||||
text: string;
|
||||
url?: string;
|
||||
description?: string;
|
||||
section?: NavSection;
|
||||
subTitle?: string;
|
||||
icon?: string;
|
||||
img?: string;
|
||||
id?: string;
|
||||
active?: boolean;
|
||||
hideFromTabs?: boolean;
|
||||
hideFromMenu?: boolean;
|
||||
divider?: boolean;
|
||||
children?: NavModelItem[];
|
||||
breadcrumbs?: NavModelBreadcrumb[];
|
||||
url?: 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;
|
||||
section?: NavSection;
|
||||
showOrgSwitcher?: boolean;
|
||||
onClick?: () => void;
|
||||
menuItemType?: NavMenuItemType;
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { merge } from 'lodash';
|
||||
import {
|
||||
BootData,
|
||||
BuildInfo,
|
||||
createTheme,
|
||||
DataSourceInstanceSettings,
|
||||
@ -28,9 +29,9 @@ export class GrafanaBootConfig implements GrafanaConfig {
|
||||
appUrl = '';
|
||||
appSubUrl = '';
|
||||
windowTitlePrefix = '';
|
||||
buildInfo: BuildInfo = {} as BuildInfo;
|
||||
buildInfo: BuildInfo;
|
||||
newPanelTitle = '';
|
||||
bootData: any;
|
||||
bootData: BootData;
|
||||
externalUserMngLinkUrl = '';
|
||||
externalUserMngLinkName = '';
|
||||
externalUserMngInfo = '';
|
||||
@ -54,9 +55,9 @@ export class GrafanaBootConfig implements GrafanaConfig {
|
||||
verifyEmailEnabled = false;
|
||||
oauth: OAuthSettings = {};
|
||||
disableUserSignUp = false;
|
||||
loginHint: any;
|
||||
passwordHint: any;
|
||||
loginError: any;
|
||||
loginHint = '';
|
||||
passwordHint = '';
|
||||
loginError = undefined;
|
||||
navTree: any;
|
||||
viewersCanEdit = false;
|
||||
editorsCanAdmin = false;
|
||||
@ -117,6 +118,8 @@ export class GrafanaBootConfig implements GrafanaConfig {
|
||||
const mode = options.bootData.user.lightTheme ? 'light' : 'dark';
|
||||
this.theme2 = createTheme({ colors: { mode } });
|
||||
this.theme = this.theme2.v1;
|
||||
this.bootData = options.bootData;
|
||||
this.buildInfo = options.buildInfo;
|
||||
|
||||
const defaults = {
|
||||
datasources: {},
|
||||
|
@ -57,7 +57,7 @@ const (
|
||||
|
||||
type NavLink struct {
|
||||
Id string `json:"id,omitempty"`
|
||||
Text string `json:"text,omitempty"`
|
||||
Text string `json:"text"`
|
||||
Description string `json:"description,omitempty"`
|
||||
Section string `json:"section,omitempty"`
|
||||
SubTitle string `json:"subTitle,omitempty"`
|
||||
|
@ -1,46 +1,49 @@
|
||||
import coreModule from 'app/angular/core_module';
|
||||
import config from 'app/core/config';
|
||||
import { find, isNumber } from 'lodash';
|
||||
import { NavModel } from '@grafana/data';
|
||||
import { NavModel, NavModelItem } from '@grafana/data';
|
||||
|
||||
interface Nav {
|
||||
breadcrumbs: NavModelItem[];
|
||||
node?: NavModelItem;
|
||||
main?: NavModelItem;
|
||||
}
|
||||
|
||||
export class NavModelSrv {
|
||||
navItems: any;
|
||||
navItems: NavModelItem[];
|
||||
|
||||
constructor() {
|
||||
this.navItems = config.bootData.navTree;
|
||||
}
|
||||
|
||||
getCfgNode() {
|
||||
return find(this.navItems, { id: 'cfg' });
|
||||
return this.navItems.find((navItem) => navItem.id === 'cfg');
|
||||
}
|
||||
|
||||
getNav(...args: Array<string | number>) {
|
||||
let children = this.navItems;
|
||||
const nav = {
|
||||
const nav: Nav = {
|
||||
breadcrumbs: [],
|
||||
} as any;
|
||||
};
|
||||
|
||||
for (const id of args) {
|
||||
// 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];
|
||||
break;
|
||||
}
|
||||
|
||||
const node: any = find(children, { id: id });
|
||||
nav.breadcrumbs.push(node);
|
||||
nav.node = node;
|
||||
nav.main = node;
|
||||
children = node.children;
|
||||
const node = children.find((child) => child.id === id);
|
||||
if (node) {
|
||||
nav.breadcrumbs.push(node);
|
||||
nav.node = node;
|
||||
nav.main = node;
|
||||
children = node.children ?? [];
|
||||
}
|
||||
}
|
||||
|
||||
if (nav.main.children) {
|
||||
if (nav.main?.children) {
|
||||
for (const item of nav.main.children) {
|
||||
item.active = false;
|
||||
|
||||
if (item.url === nav.node.url) {
|
||||
item.active = true;
|
||||
}
|
||||
item.active = item.url === nav.node?.url;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,25 +1,30 @@
|
||||
import config from '../../core/config';
|
||||
import { extend } from 'lodash';
|
||||
import { rangeUtil, WithAccessControlMetadata } from '@grafana/data';
|
||||
import { OrgRole, rangeUtil, WithAccessControlMetadata } from '@grafana/data';
|
||||
import { AccessControlAction, UserPermission } from 'app/types';
|
||||
import { featureEnabled, getBackendSrv } from '@grafana/runtime';
|
||||
import { CurrentUserInternal } from 'app/types/config';
|
||||
|
||||
export class User {
|
||||
export class User implements CurrentUserInternal {
|
||||
isSignedIn: boolean;
|
||||
id: number;
|
||||
isGrafanaAdmin: any;
|
||||
isSignedIn: any;
|
||||
orgRole: any;
|
||||
login: string;
|
||||
email: string;
|
||||
name: string;
|
||||
lightTheme: boolean;
|
||||
orgCount: number;
|
||||
orgId: number;
|
||||
orgName: string;
|
||||
login: string;
|
||||
orgCount: number;
|
||||
orgRole: OrgRole | '';
|
||||
isGrafanaAdmin: boolean;
|
||||
gravatarUrl: string;
|
||||
timezone: string;
|
||||
fiscalYearStartMonth: number;
|
||||
weekStart: string;
|
||||
locale: string;
|
||||
helpFlags1: number;
|
||||
lightTheme: boolean;
|
||||
hasEditPermissionInFolders: boolean;
|
||||
email?: string;
|
||||
permissions?: UserPermission;
|
||||
fiscalYearStartMonth: number;
|
||||
|
||||
constructor() {
|
||||
this.id = 0;
|
||||
@ -35,7 +40,12 @@ export class User {
|
||||
this.helpFlags1 = 0;
|
||||
this.lightTheme = false;
|
||||
this.hasEditPermissionInFolders = false;
|
||||
this.email = undefined;
|
||||
this.email = '';
|
||||
this.name = '';
|
||||
this.locale = '';
|
||||
this.weekStart = '';
|
||||
this.gravatarUrl = '';
|
||||
|
||||
if (config.bootData.user) {
|
||||
extend(this, config.bootData.user);
|
||||
}
|
||||
@ -55,7 +65,7 @@ export class ContextSrv {
|
||||
|
||||
constructor() {
|
||||
if (!config.bootData) {
|
||||
config.bootData = { user: {}, settings: {} };
|
||||
config.bootData = { user: {}, settings: {} } as any;
|
||||
}
|
||||
|
||||
this.user = new User();
|
||||
@ -180,7 +190,7 @@ export { contextSrv };
|
||||
|
||||
export const setContextSrv = (override: ContextSrv) => {
|
||||
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;
|
||||
};
|
||||
|
@ -53,7 +53,7 @@ describe('ShareEmbed', () => {
|
||||
user: {
|
||||
orgId: 1,
|
||||
},
|
||||
};
|
||||
} as any;
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
|
@ -110,7 +110,7 @@ describe('ShareModal', () => {
|
||||
user: {
|
||||
orgId: 1,
|
||||
},
|
||||
};
|
||||
} as any;
|
||||
ctx.mount({
|
||||
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: {
|
||||
orgId: 1,
|
||||
},
|
||||
};
|
||||
} as any;
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
|
@ -36,7 +36,7 @@ describe('buildParams', () => {
|
||||
to: 2000,
|
||||
raw: { from: 'now-6h', to: 'now' },
|
||||
} as unknown as TimeRange;
|
||||
const orgId = '2';
|
||||
const orgId = 2;
|
||||
const result = buildParams({ useCurrentTimeRange, selectedTheme, panel, search, range, orgId });
|
||||
|
||||
expect(result.toString()).toEqual(expected);
|
||||
|
@ -9,7 +9,7 @@ export interface BuildParamsArgs {
|
||||
panel?: PanelModel;
|
||||
search?: string;
|
||||
range?: TimeRange;
|
||||
orgId?: string;
|
||||
orgId?: number;
|
||||
}
|
||||
|
||||
export function buildParams({
|
||||
@ -24,7 +24,7 @@ export function buildParams({
|
||||
|
||||
searchParams.set('from', String(range.from.valueOf()));
|
||||
searchParams.set('to', String(range.to.valueOf()));
|
||||
searchParams.set('orgId', orgId);
|
||||
searchParams.set('orgId', String(orgId));
|
||||
|
||||
if (!useCurrentTimeRange) {
|
||||
searchParams.delete('from');
|
||||
|
@ -44,7 +44,7 @@ describe('grafanaGraph', () => {
|
||||
user: {
|
||||
lightTheme: false,
|
||||
},
|
||||
};
|
||||
} as any;
|
||||
Object.assign(GraphCtrl.prototype, {
|
||||
...MetricsPanelCtrl.prototype,
|
||||
...PanelCtrl.prototype,
|
||||
|
@ -1,12 +1,10 @@
|
||||
/**
|
||||
* UserPermission is a map storing permissions in a form of
|
||||
* {
|
||||
* action: { scope: scope }
|
||||
* action: true;
|
||||
* }
|
||||
*/
|
||||
export type UserPermission = {
|
||||
[key: string]: { [key: string]: string };
|
||||
};
|
||||
export type UserPermission = Record<string, boolean>;
|
||||
|
||||
// Permission actions
|
||||
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