Kaynağa Gözat

ux: row collapse / expand starting to work

Torkel Ödegaard 8 yıl önce
ebeveyn
işleme
15024e96e4

+ 14 - 1
public/app/features/dashboard/dashboard_model.ts

@@ -215,7 +215,7 @@ export class DashboardModel {
     this.events.emit('panel-added', panel);
   }
 
-  private sortPanelsByGridPos() {
+  sortPanelsByGridPos() {
     this.panels.sort(function(panelA, panelB) {
       if (panelA.gridPos.y === panelB.gridPos.y) {
         return panelA.gridPos.x - panelB.gridPos.x;
@@ -415,15 +415,28 @@ export class DashboardModel {
         // Use first panel to figure out if it was moved or pushed
         let firstPanel = row.panels[0];
         let yDiff = firstPanel.gridPos.y - (row.gridPos.y + row.gridPos.h);
+
         // start inserting after row
         let insertPos = rowIndex+1;
+        // y max will represent the bottom y pos after all panels have been added
+        // needed to know home much panels below should be pushed down
+        let yMax = row.gridPos.y;
 
         for (let panel of row.panels) {
           // make sure y is adjusted (in case row moved while collapsed)
           panel.gridPos.y -= yDiff;
           // insert after row
           this.panels.splice(insertPos, 0, new PanelModel(panel));
+          // update insert post and y max
           insertPos += 1;
+          yMax = Math.max(yMax, panel.gridPos.y + panel.gridPos.h);
+        }
+
+        const pushDownAmount = yMax - row.gridPos.y;
+
+        // push panels below down
+        for (let panelIndex = insertPos; panelIndex < this.panels.length; panelIndex++) {
+          this.panels[panelIndex].gridPos.y += pushDownAmount;
         }
 
         row.panels = [];

+ 2 - 0
public/app/features/dashboard/dashgrid/DashboardGrid.tsx

@@ -112,6 +112,8 @@ export class DashboardGrid extends React.Component<DashboardGridProps, any> {
     for (const newPos of newLayout) {
       this.panelMap[newPos.i].updateGridPos(newPos);
     }
+
+    this.dashboard.sortPanelsByGridPos();
   }
 
   triggerForceUpdate() {

+ 27 - 26
public/app/features/dashboard/dashnav/dashnav.html

@@ -23,32 +23,33 @@
 		</ul>
 
 		<ul class="nav dashnav-action-icons">
-		<!-- 	<li ng&#45;show="::ctrl.dashboard.meta.canShare" class="dropdown"> -->
-		<!-- 		<a class="pointer" ng&#45;click="ctrl.hideTooltip($event)" bs&#45;tooltip="'Share dashboard'" data&#45;placement="bottom" data&#45;toggle="dropdown"><i class="fa fa&#45;share&#45;square&#45;o"></i></a> -->
-		<!-- 		<ul class="dropdown&#45;menu"> -->
-		<!-- 			<li> -->
-		<!-- 				<a class="pointer" ng&#45;click="ctrl.shareDashboard(0)"> -->
-		<!-- 					<i class="fa fa&#45;link"></i> Link to Dashboard -->
-		<!-- 					<div class="dropdown&#45;desc">Share an internal link to the current dashboard. Some configuration options available.</div> -->
-		<!-- 				</a> -->
-		<!-- 			</li> -->
-		<!-- 			<li> -->
-		<!-- 				<a class="pointer" ng&#45;click="ctrl.shareDashboard(1)"> -->
-		<!-- 					<i class="icon&#45;gf icon&#45;gf&#45;snapshot"></i>Snapshot -->
-		<!-- 					<div class="dropdown&#45;desc">Interactive, publically accessible dashboard. Sensitive data is stripped out.</div> -->
-		<!-- 				</a> -->
-		<!-- 			</li> -->
-		<!-- 			<li> -->
-		<!-- 				<a class="pointer" ng&#45;click="ctrl.shareDashboard(2)"> -->
-		<!-- 					<i class="fa fa&#45;cloud&#45;upload"></i>Export -->
-		<!-- 					<div class="dropdown&#45;desc">Export the dashboard to a JSON file for others and to share on Grafana.com</div> -->
-		<!-- 				</a> -->
-		<!-- 			</li> -->
-		<!-- 		</ul> -->
-		<!-- 	</li> -->
-		<!-- 	<li ng&#45;show="::ctrl.dashboard.meta.canSave"> -->
-		<!-- 		<a ng&#45;click="ctrl.saveDashboard()" bs&#45;tooltip="'Save dashboard <br> CTRL+S'" data&#45;placement="bottom"><i class="fa fa&#45;save"></i></a> -->
-		<!-- 	</li> -->
+			<li ng-show="::ctrl.dashboard.meta.canShare" class="dropdown">
+				<a class="pointer" ng-click="ctrl.hideTooltip($event)" bs-tooltip="'Share dashboard'" data-placement="bottom" data-toggle="dropdown"><i class="fa fa-share-square-o"></i></a>
+				<ul class="dropdown-menu">
+					<li>
+						<a class="pointer" ng-click="ctrl.shareDashboard(0)">
+							<i class="fa fa-link"></i> Link to Dashboard
+							<div class="dropdown-desc">Share an internal link to the current dashboard. Some configuration options available.</div>
+						</a>
+					</li>
+					<li>
+						<a class="pointer" ng-click="ctrl.shareDashboard(1)">
+							<i class="icon-gf icon-gf-snapshot"></i>Snapshot
+							<div class="dropdown-desc">Interactive, publically accessible dashboard. Sensitive data is stripped out.</div>
+						</a>
+					</li>
+					<li>
+						<a class="pointer" ng-click="ctrl.shareDashboard(2)">
+							<i class="fa fa-cloud-upload"></i>Export
+							<div class="dropdown-desc">Export the dashboard to a JSON file for others and to share on Grafana.com</div>
+						</a>
+					</li>
+				</ul>
+			</li>
+
+			<li ng-show="::ctrl.dashboard.meta.canSave">
+				<a ng-click="ctrl.saveDashboard()" bs-tooltip="'Save dashboard <br> CTRL+S'" data-placement="bottom"><i class="fa fa-save"></i></a>
+			</li>
 
 			<li ng-if="::ctrl.dashboard.snapshot.originalUrl">
 				<a ng-href="{{ctrl.dashboard.snapshot.originalUrl}}" bs-tooltip="'Open original dashboard'" data-placement="bottom"><i class="fa fa-link"></i></a>

+ 1 - 1
public/app/features/dashboard/panel_model.ts

@@ -1,4 +1,4 @@
-import {Emitter} from 'app/core/core';
+import {Emitter} from 'app/core/utils/emitter';
 import _ from 'lodash';
 
 export interface GridPos {

+ 25 - 18
public/app/features/dashboard/specs/dashboard_model.jest.ts

@@ -2,6 +2,10 @@ import _ from 'lodash';
 import {DashboardModel} from '../dashboard_model';
 import {PanelModel} from '../panel_model';
 
+jest.mock('app/core/services/context_srv', () => ({
+
+}));
+
 describe('DashboardModel', function() {
 
   describe('when creating new dashboard model defaults only', function() {
@@ -69,7 +73,7 @@ describe('DashboardModel', function() {
       dashboard.addPanel(panel);
       dashboard.duplicatePanel(dashboard.panels[0]);
 
-      expect(dashboard.panels[1].gridPos).to.eql({x: 6, y: 0, h: 2, w: 6});
+      expect(dashboard.panels[1].gridPos).toMatchObject({x: 6, y: 0, h: 2, w: 6});
     });
 
     it('duplicate panel should remove repeat data', function() {
@@ -414,7 +418,7 @@ describe('DashboardModel', function() {
     });
   });
 
-  describe('given dashboard with panel repeat in horizontal direction', function(ctx) {
+  describe('given dashboard with panel repeat in horizontal direction', function() {
     var dashboard;
 
     beforeEach(function() {
@@ -455,9 +459,9 @@ describe('DashboardModel', function() {
     });
 
     it('should place on first row and adjust width so all fit', function() {
-      expect(dashboard.panels[0].gridPos).to.eql({x: 0, y: 0, h: 2, w: 8});
-      expect(dashboard.panels[1].gridPos).to.eql({x: 8, y: 0, h: 2, w: 8});
-      expect(dashboard.panels[2].gridPos).to.eql({x: 16, y: 0, h: 2, w: 8});
+      expect(dashboard.panels[0].gridPos).toMatchObject({x: 0, y: 0, h: 2, w: 8});
+      expect(dashboard.panels[1].gridPos).toMatchObject({x: 8, y: 0, h: 2, w: 8});
+      expect(dashboard.panels[2].gridPos).toMatchObject({x: 16, y: 0, h: 2, w: 8});
     });
 
     describe('After a second iteration', function() {
@@ -526,7 +530,7 @@ describe('DashboardModel', function() {
 
   });
 
-  describe('given dashboard with panel repeat in vertical direction', function(ctx) {
+  describe('given dashboard with panel repeat in vertical direction', function() {
     var dashboard;
 
     beforeEach(function() {
@@ -552,13 +556,13 @@ describe('DashboardModel', function() {
     });
 
     it('should place on items on top of each other and keep witdh', function() {
-      expect(dashboard.panels[0].gridPos).to.eql({x: 5, y: 0, h: 2, w: 8});
-      expect(dashboard.panels[1].gridPos).to.eql({x: 5, y: 2, h: 2, w: 8});
-      expect(dashboard.panels[2].gridPos).to.eql({x: 5, y: 4, h: 2, w: 8});
+      expect(dashboard.panels[0].gridPos).toMatchObject({x: 5, y: 0, h: 2, w: 8});
+      expect(dashboard.panels[1].gridPos).toMatchObject({x: 5, y: 2, h: 2, w: 8});
+      expect(dashboard.panels[2].gridPos).toMatchObject({x: 5, y: 4, h: 2, w: 8});
     });
   });
 
-  describe('When collapsing row', function(ctx) {
+  describe('When collapsing row', function() {
     var dashboard;
 
     beforeEach(function() {
@@ -575,13 +579,13 @@ describe('DashboardModel', function() {
     });
 
     it('should remove panels and put them inside collapsed row', function() {
-      expect(dashboard.panels.length).to.eql(3);
-      expect(dashboard.panels[1].panels.length).to.eql(2);
+      expect(dashboard.panels.length).toBe(3);
+      expect(dashboard.panels[1].panels.length).toBe(2);
     });
 
   });
 
-  describe('When expanding row', function(ctx) {
+  describe('When expanding row', function() {
     var dashboard;
 
     beforeEach(function() {
@@ -598,24 +602,27 @@ describe('DashboardModel', function() {
               {id: 4, type: 'graph', gridPos: {x: 12, y: 2, w: 12, h: 2}},
             ]
           },
+          {id: 5, type: 'graph', gridPos: {x: 0, y: 6, w: 1, h: 1}},
         ],
       });
       dashboard.toggleRow(dashboard.panels[1]);
     });
 
     it('should add panels back', function() {
-      expect(dashboard.panels.length).to.eql(4);
+      expect(dashboard.panels.length).toBe(5);
     });
 
     it('should add them below row in array', function() {
-      expect(dashboard.panels[2].id).to.eql(3);
-      expect(dashboard.panels[3].id).to.eql(4);
+      expect(dashboard.panels[2].id).toBe(3);
+      expect(dashboard.panels[3].id).toBe(4);
     });
 
     it('should position them below row', function() {
-      expect(dashboard.panels[2].gridPos).to.eql({x: 0, y: 8, w: 12, h: 2});
+      expect(dashboard.panels[2].gridPos).toMatchObject({x: 0, y: 8, w: 12, h: 2});
     });
 
+    it('should move panels below down', function() {
+      expect(dashboard.panels[4].gridPos).toMatchObject({x: 0, y: 10, w: 1, h: 1});
+    });
   });
-
 });

+ 0 - 5
public/app/headers/common.d.ts

@@ -5,11 +5,6 @@ declare module 'eventemitter3' {
   export default config;
 }
 
-declare module 'gridstack' {
-  var gridstack: any;
-  export default gridstack;
-}
-
 declare module 'gemini-scrollbar' {
   var d3: any;
   export default d3;

+ 2 - 2
public/sass/components/_row.scss

@@ -44,16 +44,16 @@
   color: $text-muted;
   visibility: hidden;
   opacity: 0;
+  flex-grow: 1;
 
   a {
     color: $text-color-weak;
     padding-left: $spacer;
+
     &:hover {
       color: $link-hover-color;
     }
   }
-
-  flex-grow: 1;
 }
 
 .dashboard-row__panel_count {

+ 0 - 1
public/sass/components/_search.scss

@@ -111,7 +111,6 @@
   padding: 3px 10px;
   white-space: nowrap;
   background-color: $tight-form-bg;
-  border: $input-btn-border-width solid $input-label-border-color;;
   margin-bottom: 4px;
   @include left-brand-border();