From 6ad1a396a543ff488093f38f3f743f2f8ebc768d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Fri, 19 May 2017 16:00:01 +0200 Subject: [PATCH] feat: query troubleshooter --- public/app/core/components/collapse_box.ts | 58 ++++++++++ .../components/json_explorer/json_explorer.ts | 8 +- public/app/core/components/response_viewer.ts | 63 ---------- public/app/core/core.ts | 6 +- public/app/features/panel/all.js | 1 + .../app/features/panel/metrics_ds_selector.ts | 27 ----- .../features/panel/query_troubleshooter.ts | 108 ++++++++++++++++++ public/app/partials/metrics.html | 4 +- public/sass/_grafana.scss | 2 +- public/sass/components/_collapse_box.scss | 29 +++++ public/sass/components/_json_explorer.scss | 2 +- public/sass/components/_response_viewer.scss | 6 - 12 files changed, 210 insertions(+), 104 deletions(-) create mode 100644 public/app/core/components/collapse_box.ts delete mode 100644 public/app/core/components/response_viewer.ts create mode 100644 public/app/features/panel/query_troubleshooter.ts create mode 100644 public/sass/components/_collapse_box.scss delete mode 100644 public/sass/components/_response_viewer.scss diff --git a/public/app/core/components/collapse_box.ts b/public/app/core/components/collapse_box.ts new file mode 100644 index 00000000000..05fac27904a --- /dev/null +++ b/public/app/core/components/collapse_box.ts @@ -0,0 +1,58 @@ +/// + +import coreModule from 'app/core/core_module'; + +const template = ` + +`; + +export class CollapseBoxCtrl { + isOpen: boolean; + onOpen: () => void; + + /** @ngInject **/ + constructor() { + this.isOpen = false; + } + + toggle() { + this.isOpen = !this.isOpen; + if (this.isOpen) { + this.onOpen(); + } + } +} + +export function collapseBox() { + return { + restrict: 'E', + template: template, + controller: CollapseBoxCtrl, + bindToController: true, + controllerAs: 'ctrl', + scope: { + "title": "@", + "isOpen": "=?", + "onOpen": "&" + }, + transclude: { + 'actions': '?collapseBoxActions', + 'body': 'collapseBoxBody', + }, + link: function(scope, elem, attrs) { + } + }; +} + +coreModule.directive('collapseBox', collapseBox); diff --git a/public/app/core/components/json_explorer/json_explorer.ts b/public/app/core/components/json_explorer/json_explorer.ts index 3f460968b77..4b57268c663 100644 --- a/public/app/core/components/json_explorer/json_explorer.ts +++ b/public/app/core/components/json_explorer/json_explorer.ts @@ -45,7 +45,7 @@ const _defaultConfig: JsonExplorerConfig = { * JsonExplorer allows you to render JSON objects in HTML with a * **collapsible** navigation. */ -export default class JsonExplorer { +export class JsonExplorer { // Hold the open state after the toggler is used private _isOpen: boolean = null; @@ -273,7 +273,7 @@ export default class JsonExplorer { * * @returns {HTMLDivElement} */ - render(): HTMLDivElement { + render(skipRoot = false): HTMLDivElement { // construct the root element and assign it to this.element this.element = createElement('div', 'row'); @@ -371,7 +371,9 @@ export default class JsonExplorer { } // append toggler and children elements to root element - this.element.appendChild(togglerLink); + if (!skipRoot) { + this.element.appendChild(togglerLink); + } this.element.appendChild(children); // if formatter is set to be open call appendChildren diff --git a/public/app/core/components/response_viewer.ts b/public/app/core/components/response_viewer.ts deleted file mode 100644 index fe332f070ec..00000000000 --- a/public/app/core/components/response_viewer.ts +++ /dev/null @@ -1,63 +0,0 @@ -/// - -import coreModule from 'app/core/core_module'; -import JsonExplorer from './json_explorer/json_explorer'; - - -const template = ` -
-
-
-`; - -export function responseViewer() { - return { - restrict: 'E', - template: template, - scope: {response: "="}, - link: function(scope, elem) { - var jsonElem = elem.find('.response-viewer-json'); - - scope.$watch("response", newVal => { - if (!newVal) { - elem.empty(); - return; - } - - if (scope.response.headers) { - delete scope.response.headers; - } - - if (scope.response.data) { - scope.response.response = scope.response.data; - delete scope.response.data; - } - - if (scope.response.config) { - scope.response.request = scope.response.config; - delete scope.response.config; - delete scope.response.request.transformRequest; - delete scope.response.request.transformResponse; - delete scope.response.request.paramSerializer; - delete scope.response.request.jsonpCallbackParam; - delete scope.response.request.headers; - delete scope.response.request.requestId; - delete scope.response.request.inspect; - delete scope.response.request.retry; - delete scope.response.request.timeout; - } - - - const formatter = new JsonExplorer(scope.response, 2, { - theme: 'dark', - }); - - const html = formatter.render(); - jsonElem.html(html); - }); - - } - }; -} - -coreModule.directive('responseViewer', responseViewer); diff --git a/public/app/core/core.ts b/public/app/core/core.ts index 4c5fa429677..f6b5046c3fc 100644 --- a/public/app/core/core.ts +++ b/public/app/core/core.ts @@ -45,7 +45,8 @@ import {assignModelProperties} from './utils/model_utils'; import {contextSrv} from './services/context_srv'; import {KeybindingSrv} from './services/keybindingSrv'; import {helpModal} from './components/help/help'; -import {responseViewer} from './components/response_viewer'; +import {collapseBox} from './components/collapse_box'; +import {JsonExplorer} from './components/json_explorer/json_explorer'; export { arrayJoin, @@ -69,5 +70,6 @@ export { contextSrv, KeybindingSrv, helpModal, - responseViewer, + collapseBox, + JsonExplorer, }; diff --git a/public/app/features/panel/all.js b/public/app/features/panel/all.js index 2f978e65345..b4afba4da1b 100644 --- a/public/app/features/panel/all.js +++ b/public/app/features/panel/all.js @@ -6,4 +6,5 @@ define([ './panel_editor_tab', './query_editor_row', './metrics_ds_selector', + './query_troubleshooter', ], function () {}); diff --git a/public/app/features/panel/metrics_ds_selector.ts b/public/app/features/panel/metrics_ds_selector.ts index 2a9137e6aa5..523268953a0 100644 --- a/public/app/features/panel/metrics_ds_selector.ts +++ b/public/app/features/panel/metrics_ds_selector.ts @@ -8,10 +8,6 @@ var module = angular.module('grafana.directives'); var template = ` -
- -
-
@@ -40,13 +36,6 @@ var template = `
-
- -
-
`; @@ -81,24 +70,8 @@ export class MetricsDsSelectorCtrl { this.dsSegment = uiSegmentSrv.newSegment({value: this.current.name, selectMode: true}); this.mixedDsSegment = uiSegmentSrv.newSegment({value: 'Add Query', selectMode: true}); - - appEvents.on('ds-request-response', this.onRequestResponse.bind(this), $scope); - appEvents.on('ds-request-error', this.onRequestError.bind(this), $scope); } - onRequestResponse(data) { - this.responseData = data; - } - - toggleShowResponse() { - this.showResponse = !this.showResponse; - } - - onRequestError(err) { - this.responseData = err; - this.responseData.isError = true; - this.showResponse = true; - } getOptions(includeBuiltin) { return Promise.resolve(this.datasources.filter(value => { diff --git a/public/app/features/panel/query_troubleshooter.ts b/public/app/features/panel/query_troubleshooter.ts new file mode 100644 index 00000000000..0c9dabb3ac1 --- /dev/null +++ b/public/app/features/panel/query_troubleshooter.ts @@ -0,0 +1,108 @@ +/// + +import _ from 'lodash'; +import appEvents from 'app/core/app_events'; +import {coreModule, JsonExplorer} from 'app/core/core'; + +const template = ` + + + Copy to clipboard + + +
+
+
+`; + +export class QueryTroubleshooterCtrl { + responseData: any; + showResponse: boolean; + panelCtrl: any; + renderJsonExplorer: (data) => void; + + /** @ngInject **/ + constructor($scope, private $timeout) { + appEvents.on('ds-request-response', this.onRequestResponse.bind(this), $scope); + appEvents.on('ds-request-error', this.onRequestError.bind(this), $scope); + } + + onRequestResponse(data) { + this.responseData = data; + } + + toggleShowResponse() { + this.showResponse = !this.showResponse; + } + + onRequestError(err) { + this.responseData = err; + this.responseData.isError = true; + this.showResponse = true; + } + + onOpen() { + if (!this.responseData) { + console.log('no data'); + return; + } + + var data = this.responseData; + if (data.headers) { + delete data.headers; + } + + if (data.config) { + data.request = data.config; + delete data.config; + delete data.request.transformRequest; + delete data.request.transformResponse; + delete data.request.paramSerializer; + delete data.request.jsonpCallbackParam; + delete data.request.headers; + delete data.request.requestId; + delete data.request.inspect; + delete data.request.retry; + delete data.request.timeout; + } + + if (data.data) { + data.response = data.data; + + delete data.data; + delete data.status; + delete data.statusText; + delete data.$$config; + } + + this.$timeout(_.partial(this.renderJsonExplorer, data), 10); + } +} + +export function queryTroubleshooter() { + return { + restrict: 'E', + template: template, + controller: QueryTroubleshooterCtrl, + bindToController: true, + controllerAs: 'ctrl', + scope: { + panelCtrl: "=" + }, + link: function(scope, elem, attrs, ctrl) { + + ctrl.renderJsonExplorer = function(data) { + var jsonElem = elem.find('.query-troubleshooter-json'); + + const formatter = new JsonExplorer(data, 2, { + theme: 'dark', + }); + + const html = formatter.render(true); + jsonElem.html(html); + }; + } + }; +} + +coreModule.directive('queryTroubleshooter', queryTroubleshooter); diff --git a/public/app/partials/metrics.html b/public/app/partials/metrics.html index 39c471eabd1..d3c6e6bcfc4 100644 --- a/public/app/partials/metrics.html +++ b/public/app/partials/metrics.html @@ -1,4 +1,6 @@ + +
@@ -8,7 +10,7 @@
- +
diff --git a/public/sass/_grafana.scss b/public/sass/_grafana.scss index c8f82ad845a..63ff5c6fe02 100644 --- a/public/sass/_grafana.scss +++ b/public/sass/_grafana.scss @@ -75,8 +75,8 @@ @import "components/jsontree"; @import "components/edit_sidemenu.scss"; @import "components/row.scss"; -@import "components/response_viewer.scss"; @import "components/json_explorer.scss"; +@import "components/collapse_box.scss"; // PAGES @import "pages/login"; diff --git a/public/sass/components/_collapse_box.scss b/public/sass/components/_collapse_box.scss new file mode 100644 index 00000000000..61abebaf634 --- /dev/null +++ b/public/sass/components/_collapse_box.scss @@ -0,0 +1,29 @@ +.collapse-box { + margin-bottom: $spacer; +} + +.collapse-box__header { + display: flex; + flex-direction: row; + padding: $input-padding-y $input-padding-x; + margin-right: $gf-form-margin; + background-color: $input-bg; + font-size: $font-size-sm; + margin-right: $gf-form-margin; + + border: $input-btn-border-width solid transparent; + @include border-radius($label-border-radius-sm); +} + +.collapse-box__header-title { + flex-grow: 1; +} + +.collapse-box__body { + padding: $input-padding-y*2 $input-padding-x; + background-color: $input-label-bg; + display: block; + margin-right: $gf-form-margin; + border: $input-btn-border-width solid transparent; + @include border-radius($label-border-radius-sm); +} diff --git a/public/sass/components/_json_explorer.scss b/public/sass/components/_json_explorer.scss index 3c4c19eceb7..d372c332176 100644 --- a/public/sass/components/_json_explorer.scss +++ b/public/sass/components/_json_explorer.scss @@ -36,7 +36,7 @@ .json-formatter-string { color: $string-color; - white-space: pre; + white-space: normal; word-wrap: break-word; } .json-formatter-number { color: $number-color; } diff --git a/public/sass/components/_response_viewer.scss b/public/sass/components/_response_viewer.scss deleted file mode 100644 index f554f98e382..00000000000 --- a/public/sass/components/_response_viewer.scss +++ /dev/null @@ -1,6 +0,0 @@ -.response-viewer { - background: $card-background; - box-shadow: $card-shadow; - padding: 1rem; - border-radius: 4px; -}