From 331b50dcaa1dc456e05cab2f383c66a47e939e82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Wed, 11 Oct 2017 16:32:05 +0200 Subject: [PATCH] grid: edit/view now works --- public/app/features/dashboard/PanelModel.ts | 1 + .../dashboard/dashgrid/DashboardGrid.tsx | 5 +- public/app/features/dashboard/viewStateSrv.js | 19 +- public/app/features/panel/panel_ctrl.ts | 4 +- public/app/plugins/panel/graph/graph.ts | 1 - .../plugins/panel/graph/specs/graph_specs.ts | 2 +- public/sass/components/_dashboard_grid.scss | 18 ++ public/test/specs/helpers.d.ts | 4 - public/test/specs/helpers.js | 180 ---------------- public/test/specs/helpers.ts | 195 ++++++++++++++++++ public/test/test-main.js | 130 ------------ 11 files changed, 232 insertions(+), 327 deletions(-) delete mode 100644 public/test/specs/helpers.d.ts delete mode 100644 public/test/specs/helpers.js create mode 100644 public/test/specs/helpers.ts delete mode 100644 public/test/test-main.js diff --git a/public/app/features/dashboard/PanelModel.ts b/public/app/features/dashboard/PanelModel.ts index 0bb1ada986f..8ad04f9f220 100644 --- a/public/app/features/dashboard/PanelModel.ts +++ b/public/app/features/dashboard/PanelModel.ts @@ -49,6 +49,7 @@ export class PanelModel { setViewMode(fullscreen: boolean, isEditing: boolean) { this.fullscreen = fullscreen; this.isEditing = isEditing; + this.events.emit('panel-size-changed'); } updateGridPos(newPos: GridPos) { diff --git a/public/app/features/dashboard/dashgrid/DashboardGrid.tsx b/public/app/features/dashboard/dashgrid/DashboardGrid.tsx index 7cf0cb190ea..7f1958836ff 100644 --- a/public/app/features/dashboard/dashgrid/DashboardGrid.tsx +++ b/public/app/features/dashboard/dashgrid/DashboardGrid.tsx @@ -59,7 +59,8 @@ export class DashboardGrid extends React.Component { // subscribe to dashboard events this.dashboard = this.panelContainer.getDashboard(); - this.dashboard.on('panel-added', this.panelAdded.bind(this)); + this.dashboard.on('panel-added', this.triggerForceUpdate.bind(this)); + this.dashboard.on('view-mode-changed', this.triggerForceUpdate.bind(this)); } buildLayout() { @@ -93,7 +94,7 @@ export class DashboardGrid extends React.Component { } } - panelAdded() { + triggerForceUpdate() { this.forceUpdate(); } diff --git a/public/app/features/dashboard/viewStateSrv.js b/public/app/features/dashboard/viewStateSrv.js index c9364ceb421..6820de3189f 100644 --- a/public/app/features/dashboard/viewStateSrv.js +++ b/public/app/features/dashboard/viewStateSrv.js @@ -9,7 +9,7 @@ function (angular, _, $, config) { var module = angular.module('grafana.services'); - module.factory('dashboardViewStateSrv', function($location, $timeout) { + module.factory('dashboardViewStateSrv', function($location, $timeout, $rootScope) { // represents the transient view state // like fullscreen panel & edit @@ -27,8 +27,8 @@ function (angular, _, $, config) { } }); - self.dashboard.on('view-mode-changed', function(panel) { - self.update({fullscreen: panel.fullscreen, edit: panel.isEditing}); + $scope.onAppEvent('panel-change-view', function(evt, payload) { + self.update(payload); }); $scope.onAppEvent('panel-initialized', function(evt, payload) { @@ -155,13 +155,17 @@ function (angular, _, $, config) { ctrl.editMode = false; ctrl.fullscreen = false; + this.dashboard.setViewMode(ctrl.panel, false, false); + + this.$scope.appEvent('panel-fullscreen-exit', {panelId: ctrl.panel.id}); + if (!render) { return false;} $timeout(function() { if (self.oldTimeRange !== ctrl.range) { - self.$scope.broadcastRefresh(); + $rootScope.$broadcast('refresh'); } else { - self.$scope.$broadcast('render'); + $rootScope.$broadcast('render'); } delete self.fullscreenPanel; }); @@ -176,9 +180,8 @@ function (angular, _, $, config) { this.oldTimeRange = ctrl.range; this.fullscreenPanel = panelScope; - $timeout(function() { - ctrl.render(); - }); + this.dashboard.setViewMode(ctrl.panel, true, ctrl.editMode); + this.$scope.appEvent('panel-fullscreen-enter', {panelId: ctrl.panel.id}); }; DashboardViewState.prototype.registerPanel = function(panelScope) { diff --git a/public/app/features/panel/panel_ctrl.ts b/public/app/features/panel/panel_ctrl.ts index 2d9706aa096..83d43a280f7 100644 --- a/public/app/features/panel/panel_ctrl.ts +++ b/public/app/features/panel/panel_ctrl.ts @@ -72,7 +72,9 @@ export class PanelCtrl { } changeView(fullscreen, edit) { - this.dashboard.setViewMode(this.panel, fullscreen, edit); + this.publishAppEvent('panel-change-view', { + fullscreen: fullscreen, edit: edit, panelId: this.panel.id + }); } viewPanel() { diff --git a/public/app/plugins/panel/graph/graph.ts b/public/app/plugins/panel/graph/graph.ts index 49ed254bfb1..723a92ad19b 100755 --- a/public/app/plugins/panel/graph/graph.ts +++ b/public/app/plugins/panel/graph/graph.ts @@ -54,7 +54,6 @@ function graphDirective($rootScope, timeSrv, popoverSrv, contextSrv) { }); ctrl.events.on('render', function(renderData) { - console.log('graph render'); data = renderData || data; if (!data) { return; diff --git a/public/app/plugins/panel/graph/specs/graph_specs.ts b/public/app/plugins/panel/graph/specs/graph_specs.ts index a4f74e395ae..11560e71c47 100644 --- a/public/app/plugins/panel/graph/specs/graph_specs.ts +++ b/public/app/plugins/panel/graph/specs/graph_specs.ts @@ -65,7 +65,7 @@ describe('grafanaGraph', function() { var scope = $rootScope.$new(); scope.ctrl = ctrl; - + scope.ctrl.events = ctrl.panel.events; $rootScope.onAppEvent = sinon.spy(); diff --git a/public/sass/components/_dashboard_grid.scss b/public/sass/components/_dashboard_grid.scss index 46d794e6545..5a346d443a6 100644 --- a/public/sass/components/_dashboard_grid.scss +++ b/public/sass/components/_dashboard_grid.scss @@ -3,4 +3,22 @@ .panel-in-fullscreen { + .react-grid-layout { + height: 100% !important; + } + + .react-grid-item { + display: none; + transition-property: none !important; + } + + .panel--fullscreen { + display: block !important; + position: unset !important; + width: 100% !important; + height: 100% !important; + transform: translate(0px, 0px) !important; + } } + + diff --git a/public/test/specs/helpers.d.ts b/public/test/specs/helpers.d.ts deleted file mode 100644 index 4b64bd79031..00000000000 --- a/public/test/specs/helpers.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -declare let helpers: any; -export default helpers; - - diff --git a/public/test/specs/helpers.js b/public/test/specs/helpers.js deleted file mode 100644 index 40c4a75423c..00000000000 --- a/public/test/specs/helpers.js +++ /dev/null @@ -1,180 +0,0 @@ -define([ - 'lodash', - 'app/core/config', - 'app/core/utils/datemath', -], function(_, config, dateMath) { - 'use strict'; - - function ControllerTestContext() { - var self = this; - - this.datasource = {}; - this.$element = {}; - this.annotationsSrv = {}; - this.timeSrv = new TimeSrvStub(); - this.templateSrv = new TemplateSrvStub(); - this.datasourceSrv = { - getMetricSources: function() {}, - get: function() { - return { - then: function(callback) { - callback(self.datasource); - } - }; - } - }; - - this.providePhase = function(mocks) { - return window.module(function($provide) { - $provide.value('datasourceSrv', self.datasourceSrv); - $provide.value('annotationsSrv', self.annotationsSrv); - $provide.value('timeSrv', self.timeSrv); - $provide.value('templateSrv', self.templateSrv); - $provide.value('$element', self.$element); - _.each(mocks, function(value, key) { - $provide.value(key, value); - }); - }); - }; - - this.createPanelController = function(Ctrl) { - return window.inject(function($controller, $rootScope, $q, $location, $browser) { - self.scope = $rootScope.$new(); - self.$location = $location; - self.$browser = $browser; - self.$q = $q; - self.panel = {type: 'test'}; - self.dashboard = {meta: {}}; - - $rootScope.appEvent = sinon.spy(); - $rootScope.onAppEvent = sinon.spy(); - $rootScope.colors = []; - - for (var i = 0; i < 50; i++) { $rootScope.colors.push('#' + i); } - - config.panels['test'] = {info: {}}; - self.ctrl = $controller(Ctrl, {$scope: self.scope}, { - panel: self.panel, dashboard: self.dashboard, row: {} - }); - }); - }; - - this.createControllerPhase = function(controllerName) { - return window.inject(function($controller, $rootScope, $q, $location, $browser) { - self.scope = $rootScope.$new(); - self.$location = $location; - self.$browser = $browser; - self.scope.contextSrv = {}; - self.scope.panel = {}; - self.scope.row = { panels:[] }; - self.scope.dashboard = {meta: {}}; - self.scope.dashboardMeta = {}; - self.scope.dashboardViewState = new DashboardViewStateStub(); - self.scope.appEvent = sinon.spy(); - self.scope.onAppEvent = sinon.spy(); - - $rootScope.colors = []; - for (var i = 0; i < 50; i++) { $rootScope.colors.push('#' + i); } - - self.$q = $q; - self.scope.skipDataOnInit = true; - self.scope.skipAutoInit = true; - self.controller = $controller(controllerName, { - $scope: self.scope - }); - }); - }; - } - - function ServiceTestContext() { - var self = this; - self.templateSrv = new TemplateSrvStub(); - self.timeSrv = new TimeSrvStub(); - self.datasourceSrv = {}; - self.backendSrv = {}; - self.$routeParams = {}; - - this.providePhase = function(mocks) { - return window.module(function($provide) { - _.each(mocks, function(key) { - $provide.value(key, self[key]); - }); - }); - }; - - this.createService = function(name) { - return window.inject(function($q, $rootScope, $httpBackend, $injector, $location, $timeout) { - self.$q = $q; - self.$rootScope = $rootScope; - self.$httpBackend = $httpBackend; - self.$location = $location; - - self.$rootScope.onAppEvent = function() {}; - self.$rootScope.appEvent = function() {}; - self.$timeout = $timeout; - - self.service = $injector.get(name); - }); - }; - } - - function DashboardViewStateStub() { - this.registerPanel = function() { - }; - } - - function TimeSrvStub() { - this.init = sinon.spy(); - this.time = { from:'now-1h', to: 'now'}; - this.timeRange = function(parse) { - if (parse === false) { - return this.time; - } - return { - from : dateMath.parse(this.time.from, false), - to : dateMath.parse(this.time.to, true) - }; - }; - - this.replace = function(target) { - return target; - }; - - this.setTime = function(time) { - this.time = time; - }; - } - - function ContextSrvStub() { - this.hasRole = function() { - return true; - }; - } - - function TemplateSrvStub() { - this.variables = []; - this.templateSettings = { interpolate : /\[\[([\s\S]+?)\]\]/g }; - this.data = {}; - this.replace = function(text) { - return _.template(text, this.templateSettings)(this.data); - }; - this.init = function() {}; - this.getAdhocFilters = function() { return []; }; - this.fillVariableValuesForUrl = function() {}; - this.updateTemplateData = function() { }; - this.variableExists = function() { return false; }; - this.variableInitialized = function() { }; - this.highlightVariablesAsHtml = function(str) { return str; }; - this.setGrafanaVariable = function(name, value) { - this.data[name] = value; - }; - } - - return { - ControllerTestContext: ControllerTestContext, - TimeSrvStub: TimeSrvStub, - ContextSrvStub: ContextSrvStub, - ServiceTestContext: ServiceTestContext - }; - -}); diff --git a/public/test/specs/helpers.ts b/public/test/specs/helpers.ts new file mode 100644 index 00000000000..709617a9465 --- /dev/null +++ b/public/test/specs/helpers.ts @@ -0,0 +1,195 @@ +import _ from 'lodash'; +import config from 'app/core/config'; +import * as dateMath from 'app/core/utils/datemath'; +import {angularMocks, sinon} from '../lib/common'; +import {PanelModel} from 'app/features/dashboard/PanelModel'; + +export function ControllerTestContext() { + var self = this; + + this.datasource = {}; + this.$element = {}; + this.annotationsSrv = {}; + this.timeSrv = new TimeSrvStub(); + this.templateSrv = new TemplateSrvStub(); + this.datasourceSrv = { + getMetricSources: function() {}, + get: function() { + return { + then: function(callback) { + callback(self.datasource); + }, + }; + }, + }; + + this.providePhase = function(mocks) { + return angularMocks.module(function($provide) { + $provide.value('datasourceSrv', self.datasourceSrv); + $provide.value('annotationsSrv', self.annotationsSrv); + $provide.value('timeSrv', self.timeSrv); + $provide.value('templateSrv', self.templateSrv); + $provide.value('$element', self.$element); + _.each(mocks, function(value, key) { + $provide.value(key, value); + }); + }); + }; + + this.createPanelController = function(Ctrl) { + return angularMocks.inject(function($controller, $rootScope, $q, $location, $browser) { + self.scope = $rootScope.$new(); + self.$location = $location; + self.$browser = $browser; + self.$q = $q; + self.panel = new PanelModel({type: 'test'}); + self.dashboard = {meta: {}}; + + $rootScope.appEvent = sinon.spy(); + $rootScope.onAppEvent = sinon.spy(); + $rootScope.colors = []; + + for (var i = 0; i < 50; i++) { + $rootScope.colors.push('#' + i); + } + + config.panels['test'] = {info: {}}; + self.ctrl = $controller( + Ctrl, + {$scope: self.scope}, + { + panel: self.panel, + dashboard: self.dashboard, + }, + ); + }); + }; + + this.createControllerPhase = function(controllerName) { + return angularMocks.inject(function($controller, $rootScope, $q, $location, $browser) { + self.scope = $rootScope.$new(); + self.$location = $location; + self.$browser = $browser; + self.scope.contextSrv = {}; + self.scope.panel = {}; + self.scope.dashboard = {meta: {}}; + self.scope.dashboardMeta = {}; + self.scope.dashboardViewState = new DashboardViewStateStub(); + self.scope.appEvent = sinon.spy(); + self.scope.onAppEvent = sinon.spy(); + + $rootScope.colors = []; + for (var i = 0; i < 50; i++) { + $rootScope.colors.push('#' + i); + } + + self.$q = $q; + self.scope.skipDataOnInit = true; + self.scope.skipAutoInit = true; + self.controller = $controller(controllerName, { + $scope: self.scope, + }); + }); + }; +} + +export function ServiceTestContext() { + var self = this; + self.templateSrv = new TemplateSrvStub(); + self.timeSrv = new TimeSrvStub(); + self.datasourceSrv = {}; + self.backendSrv = {}; + self.$routeParams = {}; + + this.providePhase = function(mocks) { + return angularMocks.module(function($provide) { + _.each(mocks, function(key) { + $provide.value(key, self[key]); + }); + }); + }; + + this.createService = function(name) { + return angularMocks.inject(function($q, $rootScope, $httpBackend, $injector, $location, $timeout) { + self.$q = $q; + self.$rootScope = $rootScope; + self.$httpBackend = $httpBackend; + self.$location = $location; + + self.$rootScope.onAppEvent = function() {}; + self.$rootScope.appEvent = function() {}; + self.$timeout = $timeout; + + self.service = $injector.get(name); + }); + }; +} + +export function DashboardViewStateStub() { + this.registerPanel = function() {}; +} + +export function TimeSrvStub() { + this.init = sinon.spy(); + this.time = {from: 'now-1h', to: 'now'}; + this.timeRange = function(parse) { + if (parse === false) { + return this.time; + } + return { + from: dateMath.parse(this.time.from, false), + to: dateMath.parse(this.time.to, true), + }; + }; + + this.replace = function(target) { + return target; + }; + + this.setTime = function(time) { + this.time = time; + }; +} + +export function ContextSrvStub() { + this.hasRole = function() { + return true; + }; +} + +export function TemplateSrvStub() { + this.variables = []; + this.templateSettings = {interpolate: /\[\[([\s\S]+?)\]\]/g}; + this.data = {}; + this.replace = function(text) { + return _.template(text, this.templateSettings)(this.data); + }; + this.init = function() {}; + this.getAdhocFilters = function() { + return []; + }; + this.fillVariableValuesForUrl = function() {}; + this.updateTemplateData = function() {}; + this.variableExists = function() { + return false; + }; + this.variableInitialized = function() {}; + this.highlightVariablesAsHtml = function(str) { + return str; + }; + this.setGrafanaVariable = function(name, value) { + this.data[name] = value; + }; +} + +var allDeps = { + ContextSrvStub: ContextSrvStub, + TemplateSrvStub: TemplateSrvStub, + TimeSrvStub: TimeSrvStub, + ControllerTestContext: ControllerTestContext, + ServiceTestContext: ServiceTestContext, + DashboardViewStateStub: DashboardViewStateStub +}; + +// for legacy +export default allDeps; diff --git a/public/test/test-main.js b/public/test/test-main.js deleted file mode 100644 index 1347c421a64..00000000000 --- a/public/test/test-main.js +++ /dev/null @@ -1,130 +0,0 @@ -(function() { - "use strict"; - - // Tun on full stack traces in errors to help debugging - Error.stackTraceLimit=Infinity; - - window.__karma__.loaded = function() {}; - - System.config({ - baseURL: '/base/', - defaultJSExtensions: true, - paths: { - 'mousetrap': 'vendor/npm/mousetrap/mousetrap.js', - 'eventemitter3': 'vendor/npm/eventemitter3/index.js', - 'remarkable': 'vendor/npm/remarkable/dist/remarkable.js', - 'tether': 'vendor/npm/tether/dist/js/tether.js', - 'tether-drop': 'vendor/npm/tether-drop/dist/js/drop.js', - 'moment': 'vendor/moment.js', - "jquery": "vendor/jquery/dist/jquery.js", - 'lodash-src': 'vendor/lodash/dist/lodash.js', - "lodash": 'app/core/lodash_extended.js', - "angular": 'vendor/angular/angular.js', - 'angular-mocks': 'vendor/angular-mocks/angular-mocks.js', - "bootstrap": "vendor/bootstrap/bootstrap.js", - 'angular-route': 'vendor/angular-route/angular-route.js', - 'angular-sanitize': 'vendor/angular-sanitize/angular-sanitize.js', - "angular-ui": "vendor/angular-ui/ui-bootstrap-tpls.js", - "angular-strap": "vendor/angular-other/angular-strap.js", - "angular-dragdrop": "vendor/angular-native-dragdrop/draganddrop.js", - "angular-bindonce": "vendor/angular-bindonce/bindonce.js", - "spectrum": "vendor/spectrum.js", - "bootstrap-tagsinput": "vendor/tagsinput/bootstrap-tagsinput.js", - "jquery.flot": "vendor/flot/jquery.flot", - "jquery.flot.pie": "vendor/flot/jquery.flot.pie", - "jquery.flot.selection": "vendor/flot/jquery.flot.selection", - "jquery.flot.stack": "vendor/flot/jquery.flot.stack", - "jquery.flot.stackpercent": "vendor/flot/jquery.flot.stackpercent", - "jquery.flot.time": "vendor/flot/jquery.flot.time", - "jquery.flot.crosshair": "vendor/flot/jquery.flot.crosshair", - "jquery.flot.fillbelow": "vendor/flot/jquery.flot.fillbelow", - "jquery.flot.gauge": "vendor/flot/jquery.flot.gauge", - "d3": "vendor/d3/d3.js", - "jquery.flot.dashes": "vendor/flot/jquery.flot.dashes", - "twemoji": "vendor/npm/twemoji/2/twemoji.amd.js", - "ace": "vendor/npm/ace-builds/src-noconflict/ace", - }, - - packages: { - app: { - defaultExtension: 'js', - }, - vendor: { - defaultExtension: 'js', - }, - }, - - map: { - }, - - meta: { - 'vendor/angular/angular.js': { - format: 'global', - deps: ['jquery'], - exports: 'angular', - }, - 'vendor/angular-mocks/angular-mocks.js': { - format: 'global', - deps: ['angular'], - }, - 'vendor/npm/eventemitter3/index.js': { - format: 'cjs', - exports: 'EventEmitter' - }, - 'vendor/npm/mousetrap/mousetrap.js': { - format: 'global', - exports: 'Mousetrap' - }, - 'vendor/npm/ace-builds/src-noconflict/ace.js': { - format: 'global', - exports: 'ace' - }, - } - }); - - function file2moduleName(filePath) { - return filePath.replace(/\\/g, '/') - .replace(/^\/base\//, '') - .replace(/\.\w*$/, ''); - } - - function onlySpecFiles(path) { - return /specs.*/.test(path); - } - - window.grafanaBootData = {settings: {}}; - - var modules = ['angular', 'angular-mocks', 'app/app']; - var promises = modules.map(function(name) { - return System.import(name); - }); - - Promise.all(promises).then(function(deps) { - var angular = deps[0]; - - angular.module('grafana', ['ngRoute']); - angular.module('grafana.services', ['ngRoute', '$strap.directives']); - angular.module('grafana.panels', []); - angular.module('grafana.controllers', []); - angular.module('grafana.directives', []); - angular.module('grafana.filters', []); - angular.module('grafana.routes', ['ngRoute']); - - // load specs - return Promise.all( - Object.keys(window.__karma__.files) // All files served by Karma. - .filter(onlySpecFiles) - .map(file2moduleName) - .map(function(path) { - // console.log(path); - return System.import(path); - })); - }).then(function() { - window.__karma__.start(); - }, function(error) { - window.__karma__.error(error.stack || error); - }).catch(function(error) { - window.__karma__.error(error.stack || error); - }); - -})();