From 5f6ecac3f98be0f2016e835c9e57859c7a87d2c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Fri, 15 Apr 2016 15:11:40 -0400 Subject: [PATCH 001/164] poc(editmode): experimental edit mode --- public/app/core/directives/dash_class.js | 10 +- public/app/features/dashboard/keybindings.js | 5 +- .../features/dashboard/partials/settings.html | 6 +- public/app/partials/dashboard.html | 162 ++++++++---------- public/sass/pages/_dashboard.scss | 117 ++++--------- 5 files changed, 122 insertions(+), 178 deletions(-) diff --git a/public/app/core/directives/dash_class.js b/public/app/core/directives/dash_class.js index 013c267fc0f..13911712e37 100644 --- a/public/app/core/directives/dash_class.js +++ b/public/app/core/directives/dash_class.js @@ -20,17 +20,13 @@ function (_, $, coreModule) { elem.toggleClass('panel-in-fullscreen', false); }); - $scope.$watch('dashboard.hideControls', function() { + $scope.$watch('dashboard.editMode', function() { if (!$scope.dashboard) { return; } - var hideControls = $scope.dashboard.hideControls || $scope.playlist_active; - - if (lastHideControlsVal !== hideControls) { - elem.toggleClass('hide-controls', hideControls); - lastHideControlsVal = hideControls; - } + var editMode = $scope.dashboard.editMode; + elem.toggleClass('dash-edit-mode', editMode === true); }); $scope.$watch('playlistSrv', function(newValue) { diff --git a/public/app/features/dashboard/keybindings.js b/public/app/features/dashboard/keybindings.js index b07dd2fd848..332a1e3a996 100644 --- a/public/app/features/dashboard/keybindings.js +++ b/public/app/features/dashboard/keybindings.js @@ -43,9 +43,8 @@ function(angular, $) { scope.broadcastRefresh(); }, { inputDisabled: true }); - keyboardManager.bind('ctrl+h', function() { - var current = scope.dashboard.hideControls; - scope.dashboard.hideControls = !current; + keyboardManager.bind('ctrl+e', function() { + scope.dashboard.editMode = !scope.dashboard.editMode; }, { inputDisabled: true }); keyboardManager.bind('ctrl+s', function(evt) { diff --git a/public/app/features/dashboard/partials/settings.html b/public/app/features/dashboard/partials/settings.html index 2a2287613ae..56fd57a423f 100644 --- a/public/app/features/dashboard/partials/settings.html +++ b/public/app/features/dashboard/partials/settings.html @@ -49,9 +49,9 @@ label-class="width-10"> -
-
-
-
-
- - - -
-
-
-
- - -
-
-
- -
- - -
- -
-
-
- Drop here -
-
-
- -
+
-
-
-
- - ADD ROW - +
+
+ + +
+ +
+
+
+ Drop here +
+
+
+ +
+ +
+
+ + ADD ROW + +
+
diff --git a/public/sass/pages/_dashboard.scss b/public/sass/pages/_dashboard.scss index 8fb1e6bcdaa..435734b8198 100644 --- a/public/sass/pages/_dashboard.scss +++ b/public/sass/pages/_dashboard.scss @@ -13,85 +13,6 @@ color: $variable; } -.row-tab { - .dropdown-menu-right { - top: 0; - left: 33px; - } -} - -.row-tab-button { - padding: 0px; - cursor: pointer; - vertical-align: middle; - width: 30px; - height: 30px; - text-align: center; - display: inline-block; - line-height: 30px; - background: $btn-success-bg; - color: rgba(255,255,255,.90); -} - -.row-button { - width: 24px; - float: left; - cursor: pointer; - line-height: 31px; - background-color: $blue-dark; -} - -.row-text { - white-space: nowrap; - text-transform: uppercase; - font-weight: bold; - font-size: 0.9em; - text-align: center; - line-height: 31px; - height: 31px; -} - -.row-close { - padding: 0px; - margin: 0px; - background: $panel-bg; - text-align: center; -} - -.row-close-buttons { - position: absolute; - left: 0; -} - -.row-open { - margin-top: 5px; - left: -30px; - position: absolute; - z-index: 100; - transition: .10s left; - transition-delay: .10s; - - &:hover { - left: -12px; - } -} - -.row-control-inner { - padding:0px; - margin:0px; - position:relative; -} - -.hide-controls { - padding: 0; - .row-tab { - display: none; - } - .add-row-panel-hint { - display: none; - } -} - .playlist-active { .add-row-panel-hint, .dashnav-refresh-action, @@ -287,3 +208,41 @@ div.flot-text { padding: 0.5rem .5rem .2rem .5rem; } } + +// +// Dashboard row header +// + +.dash-row-header { + display: flex; + flex-direction: row; + text-align: left; +} + +.dash-row-header-title { + font-size: $font-size-h3; + font-family: $headings-font-family; + padding: $spacer $spacer*2; +} + +.dash-row-header-settings { + display: none; +} + +.dash-row-header-collapse-toggle { + flex-grow: 100; + text-align: right; + display: none; +} + +.dash-edit-mode { + .dash-row { + background-color: $dark-5; + padding: 0 $spacer $spacer $spacer; + } + + .dash-row-header-collapse-toggle, + .dash-row-header-settings { + display: block; + } +} From a7e8e64d7839135f856ef3a2ce24629333ebfb0e Mon Sep 17 00:00:00 2001 From: Matt Toback Date: Fri, 15 Apr 2016 19:52:18 -0400 Subject: [PATCH 002/164] The beginnings of the build mode and rows --- public/app/core/directives/dash_class.js | 2 - .../features/dashboard/dashnav/dashnav.html | 4 ++ public/app/features/dashboard/keybindings.js | 2 +- .../features/dashboard/partials/settings.html | 5 +-- public/app/features/dashboard/rowCtrl.js | 5 +++ public/app/partials/dashboard.html | 9 ++-- public/sass/_variables.dark.scss | 4 ++ public/sass/_variables.light.scss | 4 ++ public/sass/pages/_dashboard.scss | 42 ++++++++++++++++--- 9 files changed, 61 insertions(+), 16 deletions(-) diff --git a/public/app/core/directives/dash_class.js b/public/app/core/directives/dash_class.js index 13911712e37..91836e34150 100644 --- a/public/app/core/directives/dash_class.js +++ b/public/app/core/directives/dash_class.js @@ -10,8 +10,6 @@ function (_, $, coreModule) { return { link: function($scope, elem) { - var lastHideControlsVal; - $scope.onAppEvent('panel-fullscreen-enter', function() { elem.toggleClass('panel-in-fullscreen', true); }); diff --git a/public/app/features/dashboard/dashnav/dashnav.html b/public/app/features/dashboard/dashnav/dashnav.html index 9afd152d8aa..927a3fd7d3b 100644 --- a/public/app/features/dashboard/dashnav/dashnav.html +++ b/public/app/features/dashboard/dashnav/dashnav.html @@ -51,6 +51,10 @@
  • Delete dashboard
  • +
  • + + Leave Build Mode +
  • - diff --git a/public/app/features/dashboard/rowCtrl.js b/public/app/features/dashboard/rowCtrl.js index 5607f1eecac..3dd145a463e 100644 --- a/public/app/features/dashboard/rowCtrl.js +++ b/public/app/features/dashboard/rowCtrl.js @@ -32,6 +32,11 @@ function (angular, _, config) { row.collapse = row.collapse ? false : true; }; + $scope.settingsHover = function(row) { + // Shows/hides the settings button on hover + return row.hoverSettings = ! row.hoverSettings; + }; + $scope.addPanel = function(panel) { $scope.dashboard.addPanel(panel, $scope.row); }; diff --git a/public/app/partials/dashboard.html b/public/app/partials/dashboard.html index 3e47370dd88..1c92f85cf63 100644 --- a/public/app/partials/dashboard.html +++ b/public/app/partials/dashboard.html @@ -12,10 +12,10 @@
    -
    +
    - diff --git a/public/sass/_variables.dark.scss b/public/sass/_variables.dark.scss index 560f2d2dab1..7013753c8a9 100644 --- a/public/sass/_variables.dark.scss +++ b/public/sass/_variables.dark.scss @@ -268,3 +268,7 @@ $checkboxImageUrl: '../img/checkbox.png'; $card-background: linear-gradient(135deg, #2f2f2f, #262626); $card-background-hover: linear-gradient(135deg, #343434, #262626); $card-shadow: -1px -1px 0 0 hsla(0, 0%, 100%, .1), 1px 1px 0 0 rgba(0, 0, 0, .3); + +// dash row +$dash-row-background: linear-gradient(135deg, #262626, #292929); +$dash-row-shadow: -1px -1px 0 0 hsla(0, 0%, 100%, .1), 1px 1px 0 0 rgba(0, 0, 0, .3); diff --git a/public/sass/_variables.light.scss b/public/sass/_variables.light.scss index a7b5c72af2b..46208330375 100644 --- a/public/sass/_variables.light.scss +++ b/public/sass/_variables.light.scss @@ -292,3 +292,7 @@ $checkboxImageUrl: '../img/checkbox_white.png'; $card-background: linear-gradient(135deg, $gray-5, $gray-6); $card-background-hover: linear-gradient(135deg, $gray-6, $gray-7); $card-shadow: -1px -1px 0 0 hsla(0, 0%, 100%, .1), 1px 1px 0 0 rgba(0, 0, 0, .1); + +// dash row +$dash-row-background: linear-gradient(135deg, $gray-5, $gray-6); +$dash-row-shadow: -1px -1px 0 0 hsla(0, 0%, 100%, .1), 1px 1px 0 0 rgba(0, 0, 0, .1); diff --git a/public/sass/pages/_dashboard.scss b/public/sass/pages/_dashboard.scss index 435734b8198..b045e0483de 100644 --- a/public/sass/pages/_dashboard.scss +++ b/public/sass/pages/_dashboard.scss @@ -217,32 +217,62 @@ div.flot-text { display: flex; flex-direction: row; text-align: left; + align-items: center; } .dash-row-header-title { font-size: $font-size-h3; font-family: $headings-font-family; - padding: $spacer $spacer*2; + padding: $spacer $spacer $spacer $spacer/2; } .dash-row-header-settings { - display: none; + display: block; +} + +.dash-row-header-chevron { + flex-grow: 100; + text-align: right; + margin-right: 0.6rem; } .dash-row-header-collapse-toggle { flex-grow: 100; text-align: right; display: none; + margin-right: $spacer/2; } .dash-edit-mode { - .dash-row { - background-color: $dark-5; - padding: 0 $spacer $spacer $spacer; - } +// .dash-row { +// background: $dash-row-background; +// box-shadow: $dash-row-shadow; +// padding: 0 ($spacer/4) ($spacer/2) ($spacer/4); +// margin-bottom: $spacer; +// } + +.dash-row { + background: lighten($body-bg, 1%); + box-shadow: inset 15px 0px 0px 0px #262626; + padding: 0 ($spacer/4) ($spacer/2) ($spacer*2); + margin-left: 5px; + margin-bottom: $spacer; +} .dash-row-header-collapse-toggle, .dash-row-header-settings { display: block; } } + +.fa.fa-wrench-close:after { + content: ""; + position: absolute; + width: .22rem; + height: 33.421356%; + top: 19px; + display: block; + background: #33B5E5; + left: 181px; + transform: translate(-50%, 0) rotate(-45deg); +} From ad56f67ad1706c240d580059830b880c33c896c9 Mon Sep 17 00:00:00 2001 From: bergquist Date: Fri, 21 Oct 2016 14:00:20 +0200 Subject: [PATCH 003/164] feat(alerting): add support to keep last state on no data closes #6332 --- pkg/models/alert.go | 2 + pkg/services/alerting/result_handler.go | 12 ++- pkg/services/alerting/result_handler_test.go | 84 +++++++------------- public/app/features/alerting/alert_def.ts | 1 + 4 files changed, 41 insertions(+), 58 deletions(-) diff --git a/pkg/models/alert.go b/pkg/models/alert.go index f50bb3193dc..4bad6a33715 100644 --- a/pkg/models/alert.go +++ b/pkg/models/alert.go @@ -15,6 +15,8 @@ const ( AlertStatePaused AlertStateType = "paused" AlertStateAlerting AlertStateType = "alerting" AlertStateOK AlertStateType = "ok" + + KeepLastAlertState AlertStateType = "keep_last" ) func (s AlertStateType) IsValid() bool { diff --git a/pkg/services/alerting/result_handler.go b/pkg/services/alerting/result_handler.go index 4372955803a..e27f8d9c35b 100644 --- a/pkg/services/alerting/result_handler.go +++ b/pkg/services/alerting/result_handler.go @@ -41,7 +41,6 @@ func (handler *DefaultResultHandler) Handle(evalContext *EvalContext) error { evalContext.Rule.State = m.AlertStateAlerting annotationData = simplejson.NewFromAny(evalContext.EvalMatches) } else { - // handle no data case if evalContext.NoDataFound { evalContext.Rule.State = evalContext.Rule.NoDataState } else { @@ -50,7 +49,7 @@ func (handler *DefaultResultHandler) Handle(evalContext *EvalContext) error { } countStateResult(evalContext.Rule.State) - if evalContext.Rule.State != oldState { + if handler.shouldUpdateAlertState(evalContext, oldState) { handler.log.Info("New state change", "alertId", evalContext.Rule.Id, "newState", evalContext.Rule.State, "oldState", oldState) cmd := &m.SetAlertStateCommand{ @@ -91,6 +90,15 @@ func (handler *DefaultResultHandler) Handle(evalContext *EvalContext) error { return nil } +func (handler *DefaultResultHandler) shouldUpdateAlertState(evalContext *EvalContext, oldState m.AlertStateType) bool { + if evalContext.NoDataFound && evalContext.Rule.NoDataState == m.KeepLastAlertState { + evalContext.Rule.State = oldState + return false + } + + return evalContext.Rule.State != oldState +} + func countStateResult(state m.AlertStateType) { switch state { case m.AlertStateAlerting: diff --git a/pkg/services/alerting/result_handler_test.go b/pkg/services/alerting/result_handler_test.go index 32589bef172..cf56d402273 100644 --- a/pkg/services/alerting/result_handler_test.go +++ b/pkg/services/alerting/result_handler_test.go @@ -1,58 +1,30 @@ package alerting -// import ( -// "testing" -// "time" -// -// "github.com/grafana/grafana/pkg/bus" -// m "github.com/grafana/grafana/pkg/models" -// "github.com/grafana/grafana/pkg/services/alerting/alertstates" -// -// . "github.com/smartystreets/goconvey/convey" -// ) -// -// func TestAlertResultHandler(t *testing.T) { -// Convey("Test result Handler", t, func() { -// resultHandler := ResultHandlerImpl{} -// mockResult := &AlertResultContext{ -// Triggered: false, -// Rule: &AlertRule{ -// Id: 1, -// OrgId 1, -// }, -// } -// mockAlertState := &m.AlertState{} -// bus.ClearBusHandlers() -// bus.AddHandler("test", func(query *m.GetLastAlertStateQuery) error { -// query.Result = mockAlertState -// return nil -// }) -// -// Convey("Should update", func() { -// -// Convey("when no earlier alert state", func() { -// mockAlertState = nil -// So(resultHandler.shouldUpdateState(mockResult), ShouldBeTrue) -// }) -// -// Convey("alert state have changed", func() { -// mockAlertState = &m.AlertState{ -// State: alertstates.Critical, -// } -// mockResult.Triggered = false -// So(resultHandler.shouldUpdateState(mockResult), ShouldBeTrue) -// }) -// -// Convey("last alert state was 15min ago", func() { -// now := time.Now() -// mockAlertState = &m.AlertState{ -// State: alertstates.Critical, -// Created: now.Add(time.Minute * -30), -// } -// mockResult.Triggered = true -// mockResult.StartTime = time.Now() -// So(resultHandler.shouldUpdateState(mockResult), ShouldBeTrue) -// }) -// }) -// }) -// } +import ( + "context" + "testing" + + "github.com/grafana/grafana/pkg/models" + . "github.com/smartystreets/goconvey/convey" +) + +func TestAlertResultHandler(t *testing.T) { + Convey("Test result Handler", t, func() { + + handler := NewResultHandler() + evalContext := NewEvalContext(context.TODO(), &Rule{}) + + Convey("Should update", func() { + + Convey("when no earlier alert state", func() { + oldState := models.AlertStateOK + + evalContext.Rule.State = models.AlertStateAlerting + evalContext.Rule.NoDataState = models.KeepLastAlertState + evalContext.NoDataFound = true + + So(handler.shouldUpdateAlertState(evalContext, oldState), ShouldBeFalse) + }) + }) + }) +} diff --git a/public/app/features/alerting/alert_def.ts b/public/app/features/alerting/alert_def.ts index 8e9a86735ad..9c567d2ebc5 100644 --- a/public/app/features/alerting/alert_def.ts +++ b/public/app/features/alerting/alert_def.ts @@ -40,6 +40,7 @@ var noDataModes = [ {text: 'OK', value: 'ok'}, {text: 'Alerting', value: 'alerting'}, {text: 'No Data', value: 'no_data'}, + {text: 'Keep Last', value: 'keep_last'}, ]; function createReducerPart(model) { From a2e14f56e4b8e44d3854800d7f6a71476eebfd4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Sat, 22 Oct 2016 10:54:50 +0200 Subject: [PATCH 004/164] refactoring(alerting PR #6354): added new option type for NoData option so AlertStateType does not have to contain invalid state, #6354 --- pkg/models/alert.go | 16 +++++- pkg/services/alerting/result_handler.go | 17 +++--- pkg/services/alerting/result_handler_test.go | 56 ++++++++++---------- pkg/services/alerting/rule.go | 4 +- 4 files changed, 52 insertions(+), 41 deletions(-) diff --git a/pkg/models/alert.go b/pkg/models/alert.go index 4bad6a33715..7531be90e88 100644 --- a/pkg/models/alert.go +++ b/pkg/models/alert.go @@ -8,6 +8,7 @@ import ( type AlertStateType string type AlertSeverityType string +type NoDataOption string const ( AlertStateNoData AlertStateType = "no_data" @@ -15,14 +16,27 @@ const ( AlertStatePaused AlertStateType = "paused" AlertStateAlerting AlertStateType = "alerting" AlertStateOK AlertStateType = "ok" +) - KeepLastAlertState AlertStateType = "keep_last" +const ( + NoDataSetNoData NoDataOption = "no_data" + NoDataSetAlerting NoDataOption = "alerting" + NoDataSetOK NoDataOption = "ok" + NoDataKeepState NoDataOption = "keep_state" ) func (s AlertStateType) IsValid() bool { return s == AlertStateOK || s == AlertStateNoData || s == AlertStateExecError || s == AlertStatePaused } +func (s NoDataOption) IsValid() bool { + return s == NoDataSetNoData || s == NoDataSetAlerting || s == NoDataSetOK || s == NoDataKeepState +} + +func (s NoDataOption) ToAlertState() AlertStateType { + return AlertStateType(s) +} + type Alert struct { Id int64 Version int64 diff --git a/pkg/services/alerting/result_handler.go b/pkg/services/alerting/result_handler.go index e27f8d9c35b..d786e8d599d 100644 --- a/pkg/services/alerting/result_handler.go +++ b/pkg/services/alerting/result_handler.go @@ -30,19 +30,21 @@ func NewResultHandler() *DefaultResultHandler { func (handler *DefaultResultHandler) Handle(evalContext *EvalContext) error { oldState := evalContext.Rule.State - exeuctionError := "" + executionError := "" annotationData := simplejson.New() if evalContext.Error != nil { handler.log.Error("Alert Rule Result Error", "ruleId", evalContext.Rule.Id, "error", evalContext.Error) evalContext.Rule.State = m.AlertStateExecError - exeuctionError = evalContext.Error.Error() - annotationData.Set("errorMessage", exeuctionError) + executionError = evalContext.Error.Error() + annotationData.Set("errorMessage", executionError) } else if evalContext.Firing { evalContext.Rule.State = m.AlertStateAlerting annotationData = simplejson.NewFromAny(evalContext.EvalMatches) } else { if evalContext.NoDataFound { - evalContext.Rule.State = evalContext.Rule.NoDataState + if evalContext.Rule.NoDataState != m.NoDataKeepState { + evalContext.Rule.State = evalContext.Rule.NoDataState.ToAlertState() + } } else { evalContext.Rule.State = m.AlertStateOK } @@ -56,7 +58,7 @@ func (handler *DefaultResultHandler) Handle(evalContext *EvalContext) error { AlertId: evalContext.Rule.Id, OrgId: evalContext.Rule.OrgId, State: evalContext.Rule.State, - Error: exeuctionError, + Error: executionError, EvalData: annotationData, } @@ -91,11 +93,6 @@ func (handler *DefaultResultHandler) Handle(evalContext *EvalContext) error { } func (handler *DefaultResultHandler) shouldUpdateAlertState(evalContext *EvalContext, oldState m.AlertStateType) bool { - if evalContext.NoDataFound && evalContext.Rule.NoDataState == m.KeepLastAlertState { - evalContext.Rule.State = oldState - return false - } - return evalContext.Rule.State != oldState } diff --git a/pkg/services/alerting/result_handler_test.go b/pkg/services/alerting/result_handler_test.go index cf56d402273..7a1abc6d1ef 100644 --- a/pkg/services/alerting/result_handler_test.go +++ b/pkg/services/alerting/result_handler_test.go @@ -1,30 +1,30 @@ package alerting -import ( - "context" - "testing" - - "github.com/grafana/grafana/pkg/models" - . "github.com/smartystreets/goconvey/convey" -) - -func TestAlertResultHandler(t *testing.T) { - Convey("Test result Handler", t, func() { - - handler := NewResultHandler() - evalContext := NewEvalContext(context.TODO(), &Rule{}) - - Convey("Should update", func() { - - Convey("when no earlier alert state", func() { - oldState := models.AlertStateOK - - evalContext.Rule.State = models.AlertStateAlerting - evalContext.Rule.NoDataState = models.KeepLastAlertState - evalContext.NoDataFound = true - - So(handler.shouldUpdateAlertState(evalContext, oldState), ShouldBeFalse) - }) - }) - }) -} +// import ( +// "context" +// "testing" +// +// "github.com/grafana/grafana/pkg/models" +// . "github.com/smartystreets/goconvey/convey" +// ) +// +// func TestAlertResultHandler(t *testing.T) { +// Convey("Test result Handler", t, func() { +// +// handler := NewResultHandler() +// evalContext := NewEvalContext(context.TODO(), &Rule{}) +// +// Convey("Should update", func() { +// +// Convey("when no earlier alert state", func() { +// oldState := models.AlertStateOK +// +// evalContext.Rule.State = models.AlertStateAlerting +// evalContext.Rule.NoDataState = models.NoDataKeepState +// evalContext.NoDataFound = true +// +// So(handler.shouldUpdateAlertState(evalContext, oldState), ShouldBeFalse) +// }) +// }) +// }) +// } diff --git a/pkg/services/alerting/rule.go b/pkg/services/alerting/rule.go index bfbb28b99fb..2ef090717ff 100644 --- a/pkg/services/alerting/rule.go +++ b/pkg/services/alerting/rule.go @@ -18,7 +18,7 @@ type Rule struct { Frequency int64 Name string Message string - NoDataState m.AlertStateType + NoDataState m.NoDataOption State m.AlertStateType Conditions []Condition Notifications []int64 @@ -76,7 +76,7 @@ func NewRuleFromDBAlert(ruleDef *m.Alert) (*Rule, error) { model.Message = ruleDef.Message model.Frequency = ruleDef.Frequency model.State = ruleDef.State - model.NoDataState = m.AlertStateType(ruleDef.Settings.Get("noDataState").MustString("no_data")) + model.NoDataState = m.NoDataOption(ruleDef.Settings.Get("noDataState").MustString("no_data")) for _, v := range ruleDef.Settings.Get("notifications").MustArray() { jsonModel := simplejson.NewFromAny(v) From 29e834e74bd7a5517a1e00f2af935d5cc0f9b8b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Sun, 23 Oct 2016 10:05:31 +0200 Subject: [PATCH 005/164] feat(UX): revived dash-edit-mode branch, #6099 --- .../app/core/directives/plugin_component.ts | 2 +- public/app/core/filters/filters.ts | 4 +- public/app/core/routes/dashboard_loaders.js | 2 +- public/app/features/dashboard/all.js | 1 + .../app/features/dashboard/dashboard_ctrl.ts | 1 + .../features/dashboard/dashnav/dashnav.html | 4 +- public/app/features/dashboard/row/row.html | 87 +++++++++++++++++++ public/app/features/dashboard/row/row.ts | 73 ++++++++++++++++ public/app/features/dashboard/rowCtrl.js | 39 --------- public/app/partials/dashboard.html | 78 +---------------- public/sass/pages/_dashboard.scss | 66 ++++++++------ 11 files changed, 211 insertions(+), 146 deletions(-) create mode 100644 public/app/features/dashboard/row/row.html create mode 100644 public/app/features/dashboard/row/row.ts diff --git a/public/app/core/directives/plugin_component.ts b/public/app/core/directives/plugin_component.ts index 60685fae74e..83c030cb317 100644 --- a/public/app/core/directives/plugin_component.ts +++ b/public/app/core/directives/plugin_component.ts @@ -58,7 +58,7 @@ function pluginDirectiveLoader($compile, datasourceSrv, $rootScope, $q, $http, $ var componentInfo: any = { name: 'panel-plugin-' + scope.panel.type, bindings: {dashboard: "=", panel: "=", row: "="}, - attrs: {dashboard: "dashboard", panel: "panel", row: "row"}, + attrs: {dashboard: "ctrl.dashboard", panel: "panel", row: "ctrl.row"}, }; var panelElemName = 'panel-' + scope.panel.type; diff --git a/public/app/core/filters/filters.ts b/public/app/core/filters/filters.ts index 6122a010182..63f2bf28bc3 100644 --- a/public/app/core/filters/filters.ts +++ b/public/app/core/filters/filters.ts @@ -60,8 +60,8 @@ coreModule.filter('noXml', function() { coreModule.filter('interpolateTemplateVars', function (templateSrv) { var filterFunc: any = function(text, scope) { var scopedVars; - if (scope.ctrl && scope.ctrl.panel) { - scopedVars = scope.ctrl.panel.scopedVars; + if (scope.ctrl) { + scopedVars = (scope.ctrl.panel || scope.ctrl.row).scopedVars; } else { scopedVars = scope.row.scopedVars; } diff --git a/public/app/core/routes/dashboard_loaders.js b/public/app/core/routes/dashboard_loaders.js index 49e81c23a7e..3c16b15c9c3 100644 --- a/public/app/core/routes/dashboard_loaders.js +++ b/public/app/core/routes/dashboard_loaders.js @@ -31,7 +31,7 @@ function (coreModule) { meta: { canStar: false, canShare: false }, dashboard: { title: "New dashboard", - rows: [{ height: '250px', panels:[] }] + rows: [{title: 'Dashboard Row', height: '250px', panels:[] }] }, }, $scope); }); diff --git a/public/app/features/dashboard/all.js b/public/app/features/dashboard/all.js index 3aa298001a5..8d66c2eb1b2 100644 --- a/public/app/features/dashboard/all.js +++ b/public/app/features/dashboard/all.js @@ -22,4 +22,5 @@ define([ './export/export_modal', './dash_list_ctrl', './ad_hoc_filters', + './row/row', ], function () {}); diff --git a/public/app/features/dashboard/dashboard_ctrl.ts b/public/app/features/dashboard/dashboard_ctrl.ts index 649a04474cc..925b3eb63e0 100644 --- a/public/app/features/dashboard/dashboard_ctrl.ts +++ b/public/app/features/dashboard/dashboard_ctrl.ts @@ -41,6 +41,7 @@ export class DashboardCtrl { $scope.setupDashboardInternal = function(data) { var dashboard = dashboardSrv.create(data.dashboard, data.meta); dashboardSrv.setCurrent(dashboard); + dashboard.editMode = true; // init services timeSrv.init(dashboard); diff --git a/public/app/features/dashboard/dashnav/dashnav.html b/public/app/features/dashboard/dashnav/dashnav.html index 562451df561..7bd9295de25 100644 --- a/public/app/features/dashboard/dashnav/dashnav.html +++ b/public/app/features/dashboard/dashnav/dashnav.html @@ -62,8 +62,8 @@
  • - - Leave Build Mode + + Leave Build Mode
  • diff --git a/public/app/features/dashboard/row/row.html b/public/app/features/dashboard/row/row.html new file mode 100644 index 00000000000..a8280fa2a71 --- /dev/null +++ b/public/app/features/dashboard/row/row.html @@ -0,0 +1,87 @@ +
    +
    +
    + +
    +
    +
    + +
    + +
    +
    + + +
    + +
    +
    + + +
    + +
    +
    +
    + Drop here +
    +
    +
    + +
    +
    +
    + diff --git a/public/app/features/dashboard/row/row.ts b/public/app/features/dashboard/row/row.ts new file mode 100644 index 00000000000..fe9ade5892a --- /dev/null +++ b/public/app/features/dashboard/row/row.ts @@ -0,0 +1,73 @@ +/// + +import _ from 'lodash'; +import coreModule from 'app/core/core_module'; + +export class DashRowCtrl { + showTitle: boolean; + + /** @ngInject */ + constructor(private $scope, private $rootScope) { + this.showTitle = true; + this.- + } + +} + + +export function rowDirective() { + return { + restrict: 'E', + templateUrl: 'public/app/features/dashboard/row/row.html', + controller: DashRowCtrl, + bindToController: true, + controllerAs: 'ctrl', + scope: { + dashboard: "=", + row: "=", + } + }; +} + +coreModule.directive('dashRow', rowDirective); + + +coreModule.directive('panelWidth', function($rootScope) { + + return function(scope, element) { + var fullscreen = false; + + function updateWidth() { + if (!fullscreen) { + element[0].style.width = ((scope.panel.span / 1.2) * 10) + '%'; + } + } + + $rootScope.onAppEvent('panel-fullscreen-enter', function(evt, info) { + fullscreen = true; + + if (scope.panel.id !== info.panelId) { + element.hide(); + } else { + element[0].style.width = '100%'; + } + }, scope); + + $rootScope.onAppEvent('panel-fullscreen-exit', function(evt, info) { + fullscreen = false; + + if (scope.panel.id !== info.panelId) { + element.show(); + } + + updateWidth(); + }, scope); + + scope.$watch('ctrl.panel.span', updateWidth); + + if (fullscreen) { + element.hide(); + } + }; +}); + diff --git a/public/app/features/dashboard/rowCtrl.js b/public/app/features/dashboard/rowCtrl.js index 69747e03460..e96e7e568bd 100644 --- a/public/app/features/dashboard/rowCtrl.js +++ b/public/app/features/dashboard/rowCtrl.js @@ -146,45 +146,6 @@ function (angular, _, config) { }; }); - module.directive('panelWidth', function() { - - return function(scope, element) { - var fullscreen = false; - - function updateWidth() { - if (!fullscreen) { - element[0].style.width = ((scope.panel.span / 1.2) * 10) + '%'; - } - } - - scope.onAppEvent('panel-fullscreen-enter', function(evt, info) { - fullscreen = true; - - if (scope.panel.id !== info.panelId) { - element.hide(); - } else { - element[0].style.width = '100%'; - } - }); - - scope.onAppEvent('panel-fullscreen-exit', function(evt, info) { - fullscreen = false; - - if (scope.panel.id !== info.panelId) { - element.show(); - } - - updateWidth(); - }); - - scope.$watch('panel.span', updateWidth); - - if (fullscreen) { - element.hide(); - } - }; - }); - module.directive('panelDropZone', function() { return function(scope, element) { scope.$on("ANGULAR_DRAG_START", function() { diff --git a/public/app/partials/dashboard.html b/public/app/partials/dashboard.html index 1c92f85cf63..cbdcf343f23 100644 --- a/public/app/partials/dashboard.html +++ b/public/app/partials/dashboard.html @@ -11,83 +11,9 @@
    -
    -
    -
    - - -
    + + -
    -
    - - -
    - -
    -
    -
    - Drop here -
    -
    -
    - -
    -
    -
    diff --git a/public/sass/pages/_dashboard.scss b/public/sass/pages/_dashboard.scss index 6e3344829e3..b7a6cd8153e 100644 --- a/public/sass/pages/_dashboard.scss +++ b/public/sass/pages/_dashboard.scss @@ -205,17 +205,43 @@ div.flot-text { // Dashboard row header // +.dash-row { + display: flex; +} + +.dash-row-handle-column { + width: 2rem; + background: $page-bg; + display: flex; + flex-direction: column; +} + +.dash-row-move-handle { + background: url($btn-drag-image) no-repeat 50% 50%; + background-size: 8px; + flex-grow: 1; + cursor: move; +} + +.dash-row-resize-handle { +} + +.dash-row-content { + flex-grow: 1; +} + .dash-row-header { display: flex; flex-direction: row; text-align: left; align-items: center; + background: $page-bg; + margin-right: $panel-margin; } .dash-row-header-title { - font-size: $font-size-h3; font-family: $headings-font-family; - padding: $spacer $spacer $spacer $spacer/2; + padding: 0.7rem; } .dash-row-header-settings { @@ -226,34 +252,24 @@ div.flot-text { flex-grow: 100; text-align: right; margin-right: 0.6rem; + font-size: $font-size-sm; + line-height: 2.5rem; + a { + color: $text-muted; + } + &:hover a { + color: $link-color; + } } -.dash-row-header-collapse-toggle { - flex-grow: 100; - text-align: right; - display: none; - margin-right: $spacer/2; -} .dash-edit-mode { -// .dash-row { -// background: $dash-row-background; -// box-shadow: $dash-row-shadow; -// padding: 0 ($spacer/4) ($spacer/2) ($spacer/4); -// margin-bottom: $spacer; -// } + .dash-row { + margin-bottom: $spacer; + } -.dash-row { - background: lighten($body-bg, 1%); - box-shadow: inset 15px 0px 0px 0px #262626; - padding: 0 ($spacer/4) ($spacer/2) ($spacer*2); - margin-left: 5px; - margin-bottom: $spacer; -} - - .dash-row-header-collapse-toggle, - .dash-row-header-settings { - display: block; + .panels-wrapper { + padding: $panel-margin*2 0 0 $panel-margin; } } From 56ccd80cce336d0f41329fa3dc58aa599a3c927b Mon Sep 17 00:00:00 2001 From: Noah Heil Date: Mon, 24 Oct 2016 03:05:16 -0600 Subject: [PATCH 006/164] Added two hints to help newer users I spent a couple of hours trying to figure out why the cloudwatch datasource was not working and the "internal error" notice was not helpful. So I added some hints so that people who are a little newer to linux/aws/grafana wont have to suffer like I did. --- docs/sources/datasources/cloudwatch.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/sources/datasources/cloudwatch.md b/docs/sources/datasources/cloudwatch.md index 2c2acb2ca56..ae909734617 100644 --- a/docs/sources/datasources/cloudwatch.md +++ b/docs/sources/datasources/cloudwatch.md @@ -25,6 +25,7 @@ be ready to build dashboards for you CloudWatch metrics. 3. Click the `Add new` link in the top header. 4. Select `CloudWatch` from the dropdown. + > NOTE: If at any moment you have issues with getting this datasource to work and grafana is giving you undescriptive errors then dont forget to check your log file (try looking in /var/log/grafana/). Name | Description ------------ | ------------- @@ -47,6 +48,7 @@ Checkout AWS docs on [IAM Roles](http://docs.aws.amazon.com/AWSEC2/latest/UserGu ### AWS credentials file Create a file at `~/.aws/credentials`. That is the `HOME` path for user running grafana-server. + > NOTE: If you think you have the credentials file in the right place but it is still not working then you might try moving your .aws file to '/usr/share/grafana/' and make sure your credentials file has at most 0644 permissions. Example content: From 01627b3a686011a73c98f06bc7dfc5f2ddbbff18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Mon, 24 Oct 2016 13:50:38 +0200 Subject: [PATCH 007/164] feat(ux): dashboard edit mode progress --- .../app/features/dashboard/dashboard_ctrl.ts | 38 +-- public/app/features/dashboard/row/row.html | 41 ++-- public/app/features/dashboard/row/row.ts | 112 ++++++++- public/app/features/dashboard/rowCtrl.js | 218 ++++-------------- public/app/features/dashboard/viewStateSrv.js | 3 + public/app/plugins/panel/graph/graph.ts | 1 - public/sass/_variables.scss | 2 +- public/sass/pages/_dashboard.scss | 4 +- .../angular-native-dragdrop/draganddrop.js | 6 +- 9 files changed, 188 insertions(+), 237 deletions(-) diff --git a/public/app/features/dashboard/dashboard_ctrl.ts b/public/app/features/dashboard/dashboard_ctrl.ts index 925b3eb63e0..ef6258d86d3 100644 --- a/public/app/features/dashboard/dashboard_ctrl.ts +++ b/public/app/features/dashboard/dashboard_ctrl.ts @@ -26,7 +26,6 @@ export class DashboardCtrl { $timeout) { $scope.editor = { index: 0 }; - $scope.panels = config.panels; var resizeEventTimeout; @@ -107,22 +106,12 @@ export class DashboardCtrl { $rootScope.$broadcast('refresh'); }; - $scope.addRow = function(dash, row) { - dash.rows.push(row); - }; - $scope.addRowDefault = function() { - $scope.resetRow(); - $scope.row.title = 'New row'; - $scope.addRow($scope.dashboard, $scope.row); - }; - - $scope.resetRow = function() { - $scope.row = { - title: '', + $scope.dashboard.rows.push({ + title: 'New row', + panels: [], height: '250px', - editable: true, - }; + }); }; $scope.showJsonEditor = function(evt, options) { @@ -132,24 +121,6 @@ export class DashboardCtrl { $scope.appEvent('show-dash-editor', { src: 'public/app/partials/edit_json.html', scope: editScope }); }; - $scope.onDrop = function(panelId, row, dropTarget) { - var info = $scope.dashboard.getPanelInfoById(panelId); - if (dropTarget) { - var dropInfo = $scope.dashboard.getPanelInfoById(dropTarget.id); - dropInfo.row.panels[dropInfo.index] = info.panel; - info.row.panels[info.index] = dropTarget; - var dragSpan = info.panel.span; - info.panel.span = dropTarget.span; - dropTarget.span = dragSpan; - } else { - info.row.panels.splice(info.index, 1); - info.panel.span = 12 - $scope.dashboard.rowSpan(row); - row.panels.push(info.panel); - } - - $rootScope.$broadcast('render'); - }; - $scope.registerWindowResizeEvent = function() { angular.element(window).bind('resize', function() { $timeout.cancel(resizeEventTimeout); @@ -166,7 +137,6 @@ export class DashboardCtrl { } init(dashboard) { - this.$scope.resetRow(); this.$scope.registerWindowResizeEvent(); this.$scope.onAppEvent('show-json-editor', this.$scope.showJsonEditor); this.$scope.onAppEvent('template-variable-value-updated', this.$scope.templateVariableUpdated); diff --git a/public/app/features/dashboard/row/row.html b/public/app/features/dashboard/row/row.html index a8280fa2a71..fbd1695c0a5 100644 --- a/public/app/features/dashboard/row/row.html +++ b/public/app/features/dashboard/row/row.html @@ -11,18 +11,15 @@
    @@ -68,12 +65,12 @@
    -
    +
    -
    +
    Drop here diff --git a/public/app/features/dashboard/row/row.ts b/public/app/features/dashboard/row/row.ts index fe9ade5892a..6e966c2e8f9 100644 --- a/public/app/features/dashboard/row/row.ts +++ b/public/app/features/dashboard/row/row.ts @@ -1,21 +1,83 @@ /// import _ from 'lodash'; -import coreModule from 'app/core/core_module'; +import config from 'app/core/config'; +import {coreModule, appEvents} from 'app/core/core'; export class DashRowCtrl { - showTitle: boolean; + dashboard: any; + row: any; + panelPlugins; /** @ngInject */ constructor(private $scope, private $rootScope) { - this.showTitle = true; - this.- + this.panelPlugins = config.panels; } + onDrop(panelId, dropTarget) { + var info = this.dashboard.getPanelInfoById(panelId); + if (dropTarget) { + var dropInfo = this.dashboard.getPanelInfoById(dropTarget.id); + dropInfo.row.panels[dropInfo.index] = info.panel; + info.row.panels[info.index] = dropTarget; + var dragSpan = info.panel.span; + info.panel.span = dropTarget.span; + dropTarget.span = dragSpan; + } else { + info.row.panels.splice(info.index, 1); + info.panel.span = 12 - this.dashboard.rowSpan(this.row); + this.row.panels.push(info.panel); + } + + this.$rootScope.$broadcast('render'); + } + + addPanel(panel) { + this.dashboard.addPanel(panel, this.row); + } + + editRow() { + // this.appEvent('show-dash-editor', { + // src: 'public/app/partials/roweditor.html', + // scope: this.$scope.$new() + // }); + } + + addPanelDefault(type) { + var defaultSpan = 12; + var _as = 12 - this.dashboard.rowSpan(this.row); + + var panel = { + title: config.new_panel_title, + error: false, + span: _as < defaultSpan && _as > 0 ? _as : defaultSpan, + editable: true, + type: type, + isNew: true, + }; + + this.addPanel(panel); + } + + deleteRow() { + if (!this.row.panels.length) { + this.dashboard.rows = _.without(this.dashboard.rows, this.row); + return; + } + + appEvents.emit('confirm-modal', { + title: 'Delete', + text: 'Are you sure you want to delete this row?', + icon: 'fa-trash', + yesText: 'Delete', + onConfirm: () => { + this.dashboard.rows = _.without(this.dashboard.rows, this.row); + } + }); + } } - -export function rowDirective() { +export function rowDirective($rootScope) { return { restrict: 'E', templateUrl: 'public/app/features/dashboard/row/row.html', @@ -25,6 +87,22 @@ export function rowDirective() { scope: { dashboard: "=", row: "=", + }, + link: function(scope, element) { + scope.$watchGroup(['ctrl.row.collapse', 'ctrl.row.height'], function() { + element.css({minHeight: scope.ctrl.row.collapse ? '5px' : scope.ctrl.row.height}); + }); + + $rootScope.onAppEvent('panel-fullscreen-enter', function(evt, info) { + var hasPanel = _.find(scope.ctrl.row.panels, {id: info.panelId}); + if (!hasPanel) { + element.hide(); + } + }, scope); + + $rootScope.onAppEvent('panel-fullscreen-exit', function() { + element.show(); + }, scope); } }; } @@ -63,7 +141,7 @@ coreModule.directive('panelWidth', function($rootScope) { updateWidth(); }, scope); - scope.$watch('ctrl.panel.span', updateWidth); + scope.$watch('panel.span', updateWidth); if (fullscreen) { element.hide(); @@ -71,3 +149,23 @@ coreModule.directive('panelWidth', function($rootScope) { }; }); + +coreModule.directive('panelDropZone', function($timeout) { + return function(scope, element) { + scope.$on("ANGULAR_DRAG_START", function() { + $timeout(function() { + var dropZoneSpan = 12 - scope.ctrl.dashboard.rowSpan(scope.ctrl.row); + + if (dropZoneSpan > 0) { + element.find('.panel-container').css('height', scope.ctrl.row.height); + element[0].style.width = ((dropZoneSpan / 1.2) * 10) + '%'; + element.show(); + } + }); + }); + + scope.$on("ANGULAR_DRAG_END", function() { + element.hide(); + }); + }; +}); diff --git a/public/app/features/dashboard/rowCtrl.js b/public/app/features/dashboard/rowCtrl.js index e96e7e568bd..e5f063d5f63 100644 --- a/public/app/features/dashboard/rowCtrl.js +++ b/public/app/features/dashboard/rowCtrl.js @@ -1,167 +1,51 @@ -define([ - 'angular', - 'lodash', - 'app/core/config' -], -function (angular, _, config) { - 'use strict'; - - var module = angular.module('grafana.controllers'); - - module.controller('RowCtrl', function($scope, $rootScope, $timeout) { - var _d = { - title: "Row", - height: "150px", - collapse: false, - editable: true, - panels: [], - }; - - _.defaults($scope.row,_d); - - $scope.init = function() { - $scope.editor = {index: 0}; - }; - - $scope.togglePanelMenu = function(posX) { - $scope.showPanelMenu = !$scope.showPanelMenu; - $scope.panelMenuPos = posX; - }; - - $scope.toggleRow = function(row) { - row.collapse = row.collapse ? false : true; - }; - - $scope.settingsHover = function(row) { - // Shows/hides the settings button on hover - return row.hoverSettings = ! row.hoverSettings; - }; - - $scope.addPanel = function(panel) { - $scope.dashboard.addPanel(panel, $scope.row); - }; - - $scope.deleteRow = function() { - function delete_row() { - $scope.dashboard.rows = _.without($scope.dashboard.rows, $scope.row); - } - - if (!$scope.row.panels.length) { - delete_row(); - return; - } - - $scope.appEvent('confirm-modal', { - title: 'Delete', - text: 'Are you sure you want to delete this row?', - icon: 'fa-trash', - yesText: 'Delete', - onConfirm: function() { - delete_row(); - } - }); - }; - - $scope.editRow = function() { - $scope.appEvent('show-dash-editor', { - src: 'public/app/partials/roweditor.html', - scope: $scope.$new() - }); - }; - - $scope.moveRow = function(direction) { - var rowsList = $scope.dashboard.rows; - var rowIndex = _.indexOf(rowsList, $scope.row); - var newIndex = rowIndex; - switch(direction) { - case 'up': { - newIndex = rowIndex - 1; - break; - } - case 'down': { - newIndex = rowIndex + 1; - break; - } - case 'top': { - newIndex = 0; - break; - } - case 'bottom': { - newIndex = rowsList.length - 1; - break; - } - default: { - newIndex = rowIndex; - } - } - if (newIndex >= 0 && newIndex <= (rowsList.length - 1)) { - _.move(rowsList, rowIndex, newIndex); - } - }; - - $scope.addPanelDefault = function(type) { - var defaultSpan = 12; - var _as = 12 - $scope.dashboard.rowSpan($scope.row); - - var panel = { - title: config.new_panel_title, - error: false, - span: _as < defaultSpan && _as > 0 ? _as : defaultSpan, - editable: true, - type: type, - isNew: true, - }; - - $scope.addPanel(panel); - - $timeout(function() { - $scope.dashboardViewState.update({fullscreen: true, edit: true, panelId: panel.id }); - }); - }; - - $scope.setHeight = function(height) { - $scope.row.height = height; - $scope.$broadcast('render'); - }; - - $scope.init(); - }); - - module.directive('rowHeight', function() { - return function(scope, element) { - scope.$watchGroup(['row.collapse', 'row.height'], function() { - element.css({ minHeight: scope.row.collapse ? '5px' : scope.row.height }); - }); - - scope.onAppEvent('panel-fullscreen-enter', function(evt, info) { - var hasPanel = _.find(scope.row.panels, {id: info.panelId}); - if (!hasPanel) { - element.hide(); - } - }); - - scope.onAppEvent('panel-fullscreen-exit', function() { - element.show(); - }); - }; - }); - - module.directive('panelDropZone', function() { - return function(scope, element) { - scope.$on("ANGULAR_DRAG_START", function() { - var dropZoneSpan = 12 - scope.dashboard.rowSpan(scope.row); - - if (dropZoneSpan > 0) { - element.find('.panel-container').css('height', scope.row.height); - element[0].style.width = ((dropZoneSpan / 1.2) * 10) + '%'; - element.show(); - } - }); - - scope.$on("ANGULAR_DRAG_END", function() { - element.hide(); - }); - }; - }); - -}); +// define([ +// 'angular', +// 'lodash', +// 'app/core/config' +// ], +// function (angular, _, config) { +// 'use strict'; +// +// var module = angular.module('grafana.controllers'); +// +// module.controller('RowCtrl', function($scope, $rootScope, $timeout) { +// +// $scope.moveRow = function(direction) { +// var rowsList = $scope.dashboard.rows; +// var rowIndex = _.indexOf(rowsList, $scope.row); +// var newIndex = rowIndex; +// switch(direction) { +// case 'up': { +// newIndex = rowIndex - 1; +// break; +// } +// case 'down': { +// newIndex = rowIndex + 1; +// break; +// } +// case 'top': { +// newIndex = 0; +// break; +// } +// case 'bottom': { +// newIndex = rowsList.length - 1; +// break; +// } +// default: { +// newIndex = rowIndex; +// } +// } +// if (newIndex >= 0 && newIndex <= (rowsList.length - 1)) { +// _.move(rowsList, rowIndex, newIndex); +// } +// }; +// +// $scope.setHeight = function(height) { +// $scope.row.height = height; +// $scope.$broadcast('render'); +// }; +// +// $scope.init(); +// }); +// +// }); diff --git a/public/app/features/dashboard/viewStateSrv.js b/public/app/features/dashboard/viewStateSrv.js index d1dee7a2d5f..0645114ebf2 100644 --- a/public/app/features/dashboard/viewStateSrv.js +++ b/public/app/features/dashboard/viewStateSrv.js @@ -149,6 +149,7 @@ function (angular, _, $) { ctrl.editMode = false; ctrl.fullscreen = false; + ctrl.dashboard.editMode = this.oldDashboardEditMode; this.$scope.appEvent('panel-fullscreen-exit', {panelId: ctrl.panel.id}); @@ -170,8 +171,10 @@ function (angular, _, $) { ctrl.editMode = this.state.edit && this.dashboard.meta.canEdit; ctrl.fullscreen = true; + this.oldDashboardEditMode = this.dashboard.editMode; this.oldTimeRange = ctrl.range; this.fullscreenPanel = panelScope; + this.dashboard.editMode = false; $(window).scrollTop(0); diff --git a/public/app/plugins/panel/graph/graph.ts b/public/app/plugins/panel/graph/graph.ts index 6a3e49b8455..9d7349e7dbc 100755 --- a/public/app/plugins/panel/graph/graph.ts +++ b/public/app/plugins/panel/graph/graph.ts @@ -384,7 +384,6 @@ module.directive('grafanaGraph', function($rootScope, timeSrv) { if (!annotations || annotations.length === 0) { return; } - console.log(annotations); var types = {}; types['$__alerting'] = { diff --git a/public/sass/_variables.scss b/public/sass/_variables.scss index e96328cb64d..e4f8c642a4b 100644 --- a/public/sass/_variables.scss +++ b/public/sass/_variables.scss @@ -80,7 +80,7 @@ $enable-flex: false; // Typography // ------------------------- -$font-family-sans-serif: "Helvetica Neue", Helvetica, Arial, sans-serif; +$font-family-sans-serif: "Open Sans", Helvetica, Arial, sans-serif; $font-family-serif: Georgia, "Times New Roman", Times, serif; $font-family-monospace: Menlo, Monaco, Consolas, "Courier New", monospace; $font-family-base: $font-family-sans-serif !default; diff --git a/public/sass/pages/_dashboard.scss b/public/sass/pages/_dashboard.scss index b7a6cd8153e..273aa2c0bfd 100644 --- a/public/sass/pages/_dashboard.scss +++ b/public/sass/pages/_dashboard.scss @@ -211,7 +211,7 @@ div.flot-text { .dash-row-handle-column { width: 2rem; - background: $page-bg; + background: $input-label-bg; display: flex; flex-direction: column; } @@ -235,7 +235,7 @@ div.flot-text { flex-direction: row; text-align: left; align-items: center; - background: $page-bg; + background: $input-label-bg; margin-right: $panel-margin; } diff --git a/public/vendor/angular-native-dragdrop/draganddrop.js b/public/vendor/angular-native-dragdrop/draganddrop.js index af8acac934b..f1866c8374b 100755 --- a/public/vendor/angular-native-dragdrop/draganddrop.js +++ b/public/vendor/angular-native-dragdrop/draganddrop.js @@ -290,12 +290,12 @@ sendData = angular.fromJson(sendData); var dropOffset = calculateDropOffset(e); - + var position = dropOffset ? { x: dropOffset.x - sendData.offset.x, y: dropOffset.y - sendData.offset.y } : null; - + determineEffectAllowed(e); var uiOnDropFn = $parse(attr.uiOnDrop); @@ -305,7 +305,7 @@ element.removeClass(dragEnterClass); dragging = 0; } - + function isDragChannelAccepted(dragChannel, dropChannel) { if (dropChannel === '*') { return true; From 6fb81f54bbf954ebe25b5db4fde7e9bff8ce79e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Mon, 24 Oct 2016 14:12:19 +0200 Subject: [PATCH 008/164] ux(): minor fix --- public/app/features/dashboard/row/row.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/public/app/features/dashboard/row/row.ts b/public/app/features/dashboard/row/row.ts index 6e966c2e8f9..26c61f4a3b0 100644 --- a/public/app/features/dashboard/row/row.ts +++ b/public/app/features/dashboard/row/row.ts @@ -10,7 +10,7 @@ export class DashRowCtrl { panelPlugins; /** @ngInject */ - constructor(private $scope, private $rootScope) { + constructor(private $scope, private $rootScope, private $timeout) { this.panelPlugins = config.panels; } @@ -34,6 +34,9 @@ export class DashRowCtrl { addPanel(panel) { this.dashboard.addPanel(panel, this.row); + this.$timeout(() => { + this.$scope.$broadcast('render'); + }); } editRow() { From 8a715cd122082b2f22f7a4775dee125e367d5764 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Tue, 25 Oct 2016 10:47:13 +0200 Subject: [PATCH 009/164] using gf-form in row header --- public/app/features/dashboard/row/row.html | 115 +++++++++++---------- public/app/features/dashboard/row/row.ts | 8 ++ public/sass/_variables.scss | 2 +- public/sass/components/_gf-form.scss | 5 +- public/sass/pages/_dashboard.scss | 4 +- 5 files changed, 78 insertions(+), 56 deletions(-) diff --git a/public/app/features/dashboard/row/row.html b/public/app/features/dashboard/row/row.html index fbd1695c0a5..bdff7c8506e 100644 --- a/public/app/features/dashboard/row/row.html +++ b/public/app/features/dashboard/row/row.html @@ -1,71 +1,82 @@ -
    +
    -
    -
    -
    - -
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    -
    +
    diff --git a/public/app/features/dashboard/row/row.ts b/public/app/features/dashboard/row/row.ts index 26c61f4a3b0..cf7dc9dce64 100644 --- a/public/app/features/dashboard/row/row.ts +++ b/public/app/features/dashboard/row/row.ts @@ -1,6 +1,9 @@ /// import _ from 'lodash'; +import $ from 'jquery'; +import angular from 'angular'; + import config from 'app/core/config'; import {coreModule, appEvents} from 'app/core/core'; @@ -12,6 +15,7 @@ export class DashRowCtrl { /** @ngInject */ constructor(private $scope, private $rootScope, private $timeout) { this.panelPlugins = config.panels; + this.row.title = this.row.title || 'Row title'; } onDrop(panelId, dropTarget) { @@ -32,6 +36,10 @@ export class DashRowCtrl { this.$rootScope.$broadcast('render'); } + onDragEnter(data) { + console.log('drag enter', data); + } + addPanel(panel) { this.dashboard.addPanel(panel, this.row); this.$timeout(() => { diff --git a/public/sass/_variables.scss b/public/sass/_variables.scss index e4f8c642a4b..186b22f2390 100644 --- a/public/sass/_variables.scss +++ b/public/sass/_variables.scss @@ -161,7 +161,7 @@ $table-sm-cell-padding: .3rem !default; // Forms $input-padding-x: .75rem !default; $input-padding-y: .6rem !default; -$input-line-height: 1.42rem !default; +$input-line-height: 1.35rem !default; $input-btn-border-width: 1px; $input-border-radius: 0 $border-radius $border-radius 0 !default; diff --git a/public/sass/components/_gf-form.scss b/public/sass/components/_gf-form.scss index b1df60426d7..c22418d70da 100644 --- a/public/sass/components/_gf-form.scss +++ b/public/sass/components/_gf-form.scss @@ -62,7 +62,7 @@ $gf-form-margin: 0.25rem; &--grow { flex-grow: 1; - min-height: 2.70rem; + min-height: 2.60rem; } } @@ -196,6 +196,9 @@ $gf-form-margin: 0.25rem; margin-right: $gf-form-margin; line-height: $input-line-height; font-size: $font-size-sm; + box-shadow: none; + border: $input-btn-border-width solid transparent; + @include border-radius($label-border-radius-sm); flex-shrink: 0; flex-grow: 0; diff --git a/public/sass/pages/_dashboard.scss b/public/sass/pages/_dashboard.scss index 273aa2c0bfd..5e7c37c1e10 100644 --- a/public/sass/pages/_dashboard.scss +++ b/public/sass/pages/_dashboard.scss @@ -210,7 +210,7 @@ div.flot-text { } .dash-row-handle-column { - width: 2rem; + min-width: 1.5rem; background: $input-label-bg; display: flex; flex-direction: column; @@ -235,8 +235,8 @@ div.flot-text { flex-direction: row; text-align: left; align-items: center; - background: $input-label-bg; margin-right: $panel-margin; + margin-left: $gf-form-margin; } .dash-row-header-title { From 5e1f1c098995a48a345494e0c425be6701bba711 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Tue, 25 Oct 2016 12:12:59 +0200 Subject: [PATCH 010/164] updated --- public/app/features/dashboard/row/row.html | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/public/app/features/dashboard/row/row.html b/public/app/features/dashboard/row/row.html index bdff7c8506e..a1b1e1a1ea9 100644 --- a/public/app/features/dashboard/row/row.html +++ b/public/app/features/dashboard/row/row.html @@ -1,9 +1,9 @@ -
    -
    -
    -
    -
    -
    + + + + + +
    @@ -12,7 +12,7 @@