mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Fix url encoding, expand template vars, fix TS hacks
* moved datasource related functions to panel sub-class * expand panel template vars for url * added keybindings for x -> Explore * url encoding for explore state
This commit is contained in:
parent
05b0bfafe4
commit
8a53ec610b
@ -10,6 +10,7 @@ import Graph from './Graph';
|
|||||||
import Table from './Table';
|
import Table from './Table';
|
||||||
import { DatasourceSrv } from 'app/features/plugins/datasource_srv';
|
import { DatasourceSrv } from 'app/features/plugins/datasource_srv';
|
||||||
import { buildQueryOptions, ensureQueries, generateQueryKey, hasQuery } from './utils/query';
|
import { buildQueryOptions, ensureQueries, generateQueryKey, hasQuery } from './utils/query';
|
||||||
|
import { decodePathComponent } from 'app/core/utils/location_util';
|
||||||
|
|
||||||
function makeTimeSeriesList(dataList, options) {
|
function makeTimeSeriesList(dataList, options) {
|
||||||
return dataList.map((seriesData, index) => {
|
return dataList.map((seriesData, index) => {
|
||||||
@ -43,7 +44,7 @@ function parseInitialQueries(initial) {
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const parsed = JSON.parse(initial);
|
const parsed = JSON.parse(decodePathComponent(initial));
|
||||||
return parsed.queries.map(q => q.query);
|
return parsed.queries.map(q => q.query);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
|
@ -3,6 +3,7 @@ import _ from 'lodash';
|
|||||||
|
|
||||||
import coreModule from 'app/core/core_module';
|
import coreModule from 'app/core/core_module';
|
||||||
import appEvents from 'app/core/app_events';
|
import appEvents from 'app/core/app_events';
|
||||||
|
import { encodePathComponent } from 'app/core/utils/location_util';
|
||||||
|
|
||||||
import Mousetrap from 'mousetrap';
|
import Mousetrap from 'mousetrap';
|
||||||
import 'mousetrap-global-bind';
|
import 'mousetrap-global-bind';
|
||||||
@ -13,7 +14,7 @@ export class KeybindingSrv {
|
|||||||
timepickerOpen = false;
|
timepickerOpen = false;
|
||||||
|
|
||||||
/** @ngInject */
|
/** @ngInject */
|
||||||
constructor(private $rootScope, private $location) {
|
constructor(private $rootScope, private $location, private datasourceSrv) {
|
||||||
// clear out all shortcuts on route change
|
// clear out all shortcuts on route change
|
||||||
$rootScope.$on('$routeChangeSuccess', () => {
|
$rootScope.$on('$routeChangeSuccess', () => {
|
||||||
Mousetrap.reset();
|
Mousetrap.reset();
|
||||||
@ -176,6 +177,17 @@ export class KeybindingSrv {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.bind('x', async () => {
|
||||||
|
if (dashboard.meta.focusPanelId) {
|
||||||
|
const panel = dashboard.getPanelById(dashboard.meta.focusPanelId);
|
||||||
|
const datasource = await this.datasourceSrv.get(panel.datasource);
|
||||||
|
if (datasource && datasource.supportsExplore) {
|
||||||
|
const exploreState = encodePathComponent(JSON.stringify(datasource.getExploreState(panel)));
|
||||||
|
this.$location.url(`/explore/${exploreState}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// delete panel
|
// delete panel
|
||||||
this.bind('p r', () => {
|
this.bind('p r', () => {
|
||||||
if (dashboard.meta.focusPanelId && dashboard.meta.canEdit) {
|
if (dashboard.meta.focusPanelId && dashboard.meta.canEdit) {
|
||||||
|
@ -1,6 +1,11 @@
|
|||||||
import config from 'app/core/config';
|
import config from 'app/core/config';
|
||||||
|
|
||||||
const _stripBaseFromUrl = url => {
|
// Slash encoding for angular location provider, see https://github.com/angular/angular.js/issues/10479
|
||||||
|
const SLASH = '<SLASH>';
|
||||||
|
export const decodePathComponent = (pc: string) => decodeURIComponent(pc).replace(new RegExp(SLASH, 'g'), '/');
|
||||||
|
export const encodePathComponent = (pc: string) => encodeURIComponent(pc.replace(/\//g, SLASH));
|
||||||
|
|
||||||
|
export const stripBaseFromUrl = url => {
|
||||||
const appSubUrl = config.appSubUrl;
|
const appSubUrl = config.appSubUrl;
|
||||||
const stripExtraChars = appSubUrl.endsWith('/') ? 1 : 0;
|
const stripExtraChars = appSubUrl.endsWith('/') ? 1 : 0;
|
||||||
const urlWithoutBase =
|
const urlWithoutBase =
|
||||||
@ -9,6 +14,4 @@ const _stripBaseFromUrl = url => {
|
|||||||
return urlWithoutBase;
|
return urlWithoutBase;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default {
|
export default { stripBaseFromUrl };
|
||||||
stripBaseFromUrl: _stripBaseFromUrl,
|
|
||||||
};
|
|
||||||
|
@ -6,6 +6,7 @@ import { PanelCtrl } from 'app/features/panel/panel_ctrl';
|
|||||||
|
|
||||||
import * as rangeUtil from 'app/core/utils/rangeutil';
|
import * as rangeUtil from 'app/core/utils/rangeutil';
|
||||||
import * as dateMath from 'app/core/utils/datemath';
|
import * as dateMath from 'app/core/utils/datemath';
|
||||||
|
import { encodePathComponent } from 'app/core/utils/location_util';
|
||||||
|
|
||||||
import { metricsTabDirective } from './metrics_tab';
|
import { metricsTabDirective } from './metrics_tab';
|
||||||
|
|
||||||
@ -309,6 +310,24 @@ class MetricsPanelCtrl extends PanelCtrl {
|
|||||||
this.refresh();
|
this.refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getAdditionalMenuItems() {
|
||||||
|
const items = [];
|
||||||
|
if (this.datasource.supportsExplore) {
|
||||||
|
items.push({
|
||||||
|
text: 'Explore',
|
||||||
|
click: 'ctrl.explore();',
|
||||||
|
icon: 'fa fa-fw fa-rocket',
|
||||||
|
shortcut: 'x',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
|
||||||
|
explore() {
|
||||||
|
const exploreState = encodePathComponent(JSON.stringify(this.datasource.getExploreState(this.panel)));
|
||||||
|
this.$location.url(`/explore/${exploreState}`);
|
||||||
|
}
|
||||||
|
|
||||||
addQuery(target) {
|
addQuery(target) {
|
||||||
target.refId = this.dashboard.getNextQueryLetter(this.panel);
|
target.refId = this.dashboard.getNextQueryLetter(this.panel);
|
||||||
|
|
||||||
|
@ -99,12 +99,6 @@ export class PanelCtrl {
|
|||||||
this.changeView(false, false);
|
this.changeView(false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
explore() {
|
|
||||||
// TS hack :<
|
|
||||||
const initialState = JSON.stringify(this['datasource'].getExploreState(this.panel));
|
|
||||||
this.$location.url(`/explore/${initialState}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
initEditMode() {
|
initEditMode() {
|
||||||
this.editorTabs = [];
|
this.editorTabs = [];
|
||||||
this.addEditorTab('General', 'public/app/partials/panelgeneral.html');
|
this.addEditorTab('General', 'public/app/partials/panelgeneral.html');
|
||||||
@ -162,16 +156,6 @@ export class PanelCtrl {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// TS hack :<
|
|
||||||
if ('datasource' in this && this['datasource'].supportsExplore) {
|
|
||||||
menu.push({
|
|
||||||
text: 'Explore',
|
|
||||||
click: 'ctrl.explore();',
|
|
||||||
icon: 'fa fa-fw fa-rocket',
|
|
||||||
shortcut: 'x',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
menu.push({
|
menu.push({
|
||||||
text: 'Share',
|
text: 'Share',
|
||||||
click: 'ctrl.sharePanel();',
|
click: 'ctrl.sharePanel();',
|
||||||
@ -179,6 +163,9 @@ export class PanelCtrl {
|
|||||||
shortcut: 'p s',
|
shortcut: 'p s',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Additional items from sub-class
|
||||||
|
menu.push(...this.getAdditionalMenuItems());
|
||||||
|
|
||||||
let extendedMenu = this.getExtendedMenu();
|
let extendedMenu = this.getExtendedMenu();
|
||||||
menu.push({
|
menu.push({
|
||||||
text: 'More ...',
|
text: 'More ...',
|
||||||
@ -227,6 +214,11 @@ export class PanelCtrl {
|
|||||||
return menu;
|
return menu;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Override in sub-class to add items before extended menu
|
||||||
|
getAdditionalMenuItems() {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
otherPanelInFullscreenMode() {
|
otherPanelInFullscreenMode() {
|
||||||
return this.dashboard.meta.fullscreen && !this.fullscreen;
|
return this.dashboard.meta.fullscreen && !this.fullscreen;
|
||||||
}
|
}
|
||||||
|
@ -326,11 +326,18 @@ export class PrometheusDatasource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getExploreState(panel) {
|
getExploreState(panel) {
|
||||||
if (!panel.targets) {
|
let state = {};
|
||||||
return {};
|
if (panel.targets) {
|
||||||
|
const queries = panel.targets.map(t => ({
|
||||||
|
query: this.templateSrv.replace(t.expr, {}, this.interpolateQueryExpr),
|
||||||
|
format: t.format,
|
||||||
|
}));
|
||||||
|
state = {
|
||||||
|
...state,
|
||||||
|
queries,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
const queries = panel.targets.map(t => ({ query: t.expr, format: t.format }));
|
return state;
|
||||||
return { queries };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getPrometheusTime(date, roundUp) {
|
getPrometheusTime(date, roundUp) {
|
||||||
|
Loading…
Reference in New Issue
Block a user