mirror of
https://github.com/timberjoegithub/grafana-statusmap.git
synced 2026-07-21 23:42:03 +00:00
Merge pull request #112 from flant/feat_pagination
feat: pagination See issue #83, pulls: #93 and #112.
This commit is contained in:
Vendored
+12
@@ -69,6 +69,18 @@
|
|||||||
.width-c-70 {
|
.width-c-70 {
|
||||||
width: 70rem !important; }
|
width: 70rem !important; }
|
||||||
|
|
||||||
|
.statusmap-pagination {
|
||||||
|
margin-top: 5px; }
|
||||||
|
.statusmap-pagination label {
|
||||||
|
margin-right: 0px; }
|
||||||
|
.statusmap-pagination input {
|
||||||
|
margin-right: 0px; }
|
||||||
|
.statusmap-pagination .last-in-group {
|
||||||
|
margin-right: 4px; }
|
||||||
|
|
||||||
|
.pagination-buttons {
|
||||||
|
text-align: right; }
|
||||||
|
|
||||||
.status-heatmap-legend-wrapper {
|
.status-heatmap-legend-wrapper {
|
||||||
margin: 0 10px; }
|
margin: 0 10px; }
|
||||||
.status-heatmap-legend-wrapper svg {
|
.status-heatmap-legend-wrapper svg {
|
||||||
|
|||||||
Vendored
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"version": 3,
|
"version": 3,
|
||||||
"mappings": "AAAA,8BAA+B;EAE7B,MAAM,EAAE,SAAS;EAGjB,kDAAoB;IAClB,cAAc,EAAE,IAAI;EAGtB,uDAAyB;IACzB,gBAAgB,ECNL,OAAO;IDOlB,KAAK,ECVM,OAAO;IDWlB,OAAO,EAAE,GAAG;;AAId,gBAAiB;EACf,QAAQ,EAAE,QAAQ;EAGhB,iCAAK;IACH,IAAI,ECpBG,OAAO;IDqBd,KAAK,ECrBE,OAAO;IDsBd,SAAS,EEtBE,IAAI;EFyBjB,iCAAK;IACH,OAAO,EAAE,GAAG;IACZ,MAAM,EC1BM,OAAO;ED+BvB,oBAAI;IACF,cAAc,EAAE,IAAI;IAEpB,yBAAK;MACH,cAAc,EAAE,cAAc;;AAKpC,kBAAmB;EAGjB,QAAQ,EAAE,QAAQ;EAClB,OAAO,EAAE,IAAI;EACb,WAAW,EAAE,GAAG;EAChB,aAAa,EAAE,GAAG;EAClB,SAAS,EAAE,KAAK;EAChB,UAAU,EAAE,KAAK;EACjB,QAAQ,EAAE,MAAM;EAChB,WAAW,EAAE,IAAI;EACjB,OAAO,EAAE,IAAI;EAGb,WAAW,EAAE,MAAM;EACnB,SAAS,EEzDI,IAAI;EF0DjB,gBAAgB,ECvDC,OAAO;EDwDxB,KAAK,EC1DM,OAAO;ED4DlB,iCAAe;IACb,KAAK,EAAE,OAAO;IACd,OAAO,EAAE,GAAG;IACZ,WAAW,EAAE,IAAI;IACjB,WAAW,EAAE,uDAAuD;;AAIxE,yBAA0B;EACxB,QAAQ,EAAE,QAAQ;EAClB,OAAO,EAAE,CAAC;;AAGZ,yBAA0B;EACxB,IAAI,ECzEY,OAAO;;AD6EvB,8BAAK;EACH,MAAM,EAAE,OAAgB;EACxB,YAAY,EAAE,CAAC;;AAInB,yBAA0B;EACxB,YAAY,EAAE,CAAC;EACf,IAAI,EAAE,wBAAwB;EAC9B,MAAM,EAAE,wBAAwB;;AAGlC,WAAY;EACV,KAAK,EAAE,gBACT;;AACA,WAAY;EACV,KAAK,EAAE,gBACT;;AACA,WAAY;EACV,KAAK,EAAE,gBACT;;AACA,WAAY;EACV,KAAK,EAAE,gBACT;;AAEA,8BAA+B;EAC7B,MAAM,EAAE,MAAM;EAEd,kCAAI;IACF,MAAM,EAAE,IAAI;IACZ,KAAK,EAAE,IAAI;IACX,WAAW,EAAE,MAAM;EAIrB,2DAA6B;IAC3B,UAAU,EAAE,GAAG;EAGjB,4DAA8B;IAC5B,OAAO,EAAE,YAAY;EAIrB,+CAAK;IACH,IAAI,EC3HG,OAAO;ID4Hd,KAAK,EC5HE,OAAO;ID6Hd,SAAS,EE7HE,IAAI;EFgIjB,+CAAK;IACH,OAAO,EAAE,GAAG;IACZ,MAAM,ECjIM,OAAO;EDoIrB,kDAAQ;IACN,OAAO,EAAE,GAAG;IACZ,MAAM,ECtIM,OAAO",
|
"mappings": "AAAA,8BAA+B;EAE7B,MAAM,EAAE,SAAS;EAGjB,kDAAoB;IAClB,cAAc,EAAE,IAAI;EAGtB,uDAAyB;IACzB,gBAAgB,ECNL,OAAO;IDOlB,KAAK,ECVM,OAAO;IDWlB,OAAO,EAAE,GAAG;;AAId,gBAAiB;EACf,QAAQ,EAAE,QAAQ;EAGhB,iCAAK;IACH,IAAI,ECpBG,OAAO;IDqBd,KAAK,ECrBE,OAAO;IDsBd,SAAS,EEtBE,IAAI;EFyBjB,iCAAK;IACH,OAAO,EAAE,GAAG;IACZ,MAAM,EC1BM,OAAO;ED+BvB,oBAAI;IACF,cAAc,EAAE,IAAI;IAEpB,yBAAK;MACH,cAAc,EAAE,cAAc;;AAKpC,kBAAmB;EAGjB,QAAQ,EAAE,QAAQ;EAClB,OAAO,EAAE,IAAI;EACb,WAAW,EAAE,GAAG;EAChB,aAAa,EAAE,GAAG;EAClB,SAAS,EAAE,KAAK;EAChB,UAAU,EAAE,KAAK;EACjB,QAAQ,EAAE,MAAM;EAChB,WAAW,EAAE,IAAI;EACjB,OAAO,EAAE,IAAI;EAGb,WAAW,EAAE,MAAM;EACnB,SAAS,EEzDI,IAAI;EF0DjB,gBAAgB,ECvDC,OAAO;EDwDxB,KAAK,EC1DM,OAAO;ED4DlB,iCAAe;IACb,KAAK,EAAE,OAAO;IACd,OAAO,EAAE,GAAG;IACZ,WAAW,EAAE,IAAI;IACjB,WAAW,EAAE,uDAAuD;;AAIxE,yBAA0B;EACxB,QAAQ,EAAE,QAAQ;EAClB,OAAO,EAAE,CAAC;;AAGZ,yBAA0B;EACxB,IAAI,ECzEY,OAAO;;AD6EvB,8BAAK;EACH,MAAM,EAAE,OAAgB;EACxB,YAAY,EAAE,CAAC;;AAInB,yBAA0B;EACxB,YAAY,EAAE,CAAC;EACf,IAAI,EAAE,wBAAwB;EAC9B,MAAM,EAAE,wBAAwB;;AAGlC,WAAY;EACV,KAAK,EAAE,gBACT;;AACA,WAAY;EACV,KAAK,EAAE,gBACT;;AACA,WAAY;EACV,KAAK,EAAE,gBACT;;AACA,WAAY;EACV,KAAK,EAAE,gBACT;;AAEA,qBAAsB;EAEpB,UAAU,EAAE,GAAG;EACf,2BAAM;IACJ,YAAY,EAAC,GAAG;EAElB,2BAAM;IACJ,YAAY,EAAE,GAAG;EAEnB,oCAAe;IACb,YAAY,EAAE,GAAG;;AAIrB,mBAAmB;EAAC,UAAU,EAAE,KAAK;;AAErC,8BAA+B;EAC7B,MAAM,EAAE,MAAM;EAEd,kCAAI;IACF,MAAM,EAAE,IAAI;IACZ,KAAK,EAAE,IAAI;IACX,WAAW,EAAE,MAAM;EAIrB,2DAA6B;IAC3B,UAAU,EAAE,GAAG;EAGjB,4DAA8B;IAC5B,OAAO,EAAE,YAAY;EAIrB,+CAAK;IACH,IAAI,EC3IG,OAAO;ID4Id,KAAK,EC5IE,OAAO;ID6Id,SAAS,EE7IE,IAAI;EFgJjB,+CAAK;IACH,OAAO,EAAE,GAAG;IACZ,MAAM,ECjJM,OAAO;EDoJrB,kDAAQ;IACN,OAAO,EAAE,GAAG;IACZ,MAAM,ECtJM,OAAO",
|
||||||
"sources": ["../../src/css/_statusmap.scss","../../src/css/_variables.dark.scss","../../src/css/_variables.scss"],
|
"sources": ["../../src/css/_statusmap.scss","../../src/css/_variables.dark.scss","../../src/css/_variables.scss"],
|
||||||
"names": [],
|
"names": [],
|
||||||
"file": "statusmap.dark.css"
|
"file": "statusmap.dark.css"
|
||||||
|
|||||||
Vendored
+12
@@ -69,6 +69,18 @@
|
|||||||
.width-c-70 {
|
.width-c-70 {
|
||||||
width: 70rem !important; }
|
width: 70rem !important; }
|
||||||
|
|
||||||
|
.statusmap-pagination {
|
||||||
|
margin-top: 5px; }
|
||||||
|
.statusmap-pagination label {
|
||||||
|
margin-right: 0px; }
|
||||||
|
.statusmap-pagination input {
|
||||||
|
margin-right: 0px; }
|
||||||
|
.statusmap-pagination .last-in-group {
|
||||||
|
margin-right: 4px; }
|
||||||
|
|
||||||
|
.pagination-buttons {
|
||||||
|
text-align: right; }
|
||||||
|
|
||||||
.status-heatmap-legend-wrapper {
|
.status-heatmap-legend-wrapper {
|
||||||
margin: 0 10px; }
|
margin: 0 10px; }
|
||||||
.status-heatmap-legend-wrapper svg {
|
.status-heatmap-legend-wrapper svg {
|
||||||
|
|||||||
Vendored
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"version": 3,
|
"version": 3,
|
||||||
"mappings": "AAAA,8BAA+B;EAE7B,MAAM,EAAE,SAAS;EAGjB,kDAAoB;IAClB,cAAc,EAAE,IAAI;EAGtB,uDAAyB;IACzB,gBAAgB,ECNL,OAAO;IDOlB,KAAK,ECVM,OAAO;IDWlB,OAAO,EAAE,GAAG;;AAId,gBAAiB;EACf,QAAQ,EAAE,QAAQ;EAGhB,iCAAK;IACH,IAAI,ECpBG,OAAO;IDqBd,KAAK,ECrBE,OAAO;IDsBd,SAAS,EEtBE,IAAI;EFyBjB,iCAAK;IACH,OAAO,EAAE,GAAG;IACZ,MAAM,EC1BM,OAAO;ED+BvB,oBAAI;IACF,cAAc,EAAE,IAAI;IAEpB,yBAAK;MACH,cAAc,EAAE,cAAc;;AAKpC,kBAAmB;EAGjB,QAAQ,EAAE,QAAQ;EAClB,OAAO,EAAE,IAAI;EACb,WAAW,EAAE,GAAG;EAChB,aAAa,EAAE,GAAG;EAClB,SAAS,EAAE,KAAK;EAChB,UAAU,EAAE,KAAK;EACjB,QAAQ,EAAE,MAAM;EAChB,WAAW,EAAE,IAAI;EACjB,OAAO,EAAE,IAAI;EAGb,WAAW,EAAE,MAAM;EACnB,SAAS,EEzDI,IAAI;EF0DjB,gBAAgB,ECvDC,OAAO;EDwDxB,KAAK,EC1DM,OAAO;ED4DlB,iCAAe;IACb,KAAK,EAAE,OAAO;IACd,OAAO,EAAE,GAAG;IACZ,WAAW,EAAE,IAAI;IACjB,WAAW,EAAE,uDAAuD;;AAIxE,yBAA0B;EACxB,QAAQ,EAAE,QAAQ;EAClB,OAAO,EAAE,CAAC;;AAGZ,yBAA0B;EACxB,IAAI,ECzEY,OAAO;;AD6EvB,8BAAK;EACH,MAAM,EAAE,OAAgB;EACxB,YAAY,EAAE,CAAC;;AAInB,yBAA0B;EACxB,YAAY,EAAE,CAAC;EACf,IAAI,EAAE,wBAAwB;EAC9B,MAAM,EAAE,wBAAwB;;AAGlC,WAAY;EACV,KAAK,EAAE,gBACT;;AACA,WAAY;EACV,KAAK,EAAE,gBACT;;AACA,WAAY;EACV,KAAK,EAAE,gBACT;;AACA,WAAY;EACV,KAAK,EAAE,gBACT;;AAEA,8BAA+B;EAC7B,MAAM,EAAE,MAAM;EAEd,kCAAI;IACF,MAAM,EAAE,IAAI;IACZ,KAAK,EAAE,IAAI;IACX,WAAW,EAAE,MAAM;EAIrB,2DAA6B;IAC3B,UAAU,EAAE,GAAG;EAGjB,4DAA8B;IAC5B,OAAO,EAAE,YAAY;EAIrB,+CAAK;IACH,IAAI,EC3HG,OAAO;ID4Hd,KAAK,EC5HE,OAAO;ID6Hd,SAAS,EE7HE,IAAI;EFgIjB,+CAAK;IACH,OAAO,EAAE,GAAG;IACZ,MAAM,ECjIM,OAAO;EDoIrB,kDAAQ;IACN,OAAO,EAAE,GAAG;IACZ,MAAM,ECtIM,OAAO",
|
"mappings": "AAAA,8BAA+B;EAE7B,MAAM,EAAE,SAAS;EAGjB,kDAAoB;IAClB,cAAc,EAAE,IAAI;EAGtB,uDAAyB;IACzB,gBAAgB,ECNL,OAAO;IDOlB,KAAK,ECVM,OAAO;IDWlB,OAAO,EAAE,GAAG;;AAId,gBAAiB;EACf,QAAQ,EAAE,QAAQ;EAGhB,iCAAK;IACH,IAAI,ECpBG,OAAO;IDqBd,KAAK,ECrBE,OAAO;IDsBd,SAAS,EEtBE,IAAI;EFyBjB,iCAAK;IACH,OAAO,EAAE,GAAG;IACZ,MAAM,EC1BM,OAAO;ED+BvB,oBAAI;IACF,cAAc,EAAE,IAAI;IAEpB,yBAAK;MACH,cAAc,EAAE,cAAc;;AAKpC,kBAAmB;EAGjB,QAAQ,EAAE,QAAQ;EAClB,OAAO,EAAE,IAAI;EACb,WAAW,EAAE,GAAG;EAChB,aAAa,EAAE,GAAG;EAClB,SAAS,EAAE,KAAK;EAChB,UAAU,EAAE,KAAK;EACjB,QAAQ,EAAE,MAAM;EAChB,WAAW,EAAE,IAAI;EACjB,OAAO,EAAE,IAAI;EAGb,WAAW,EAAE,MAAM;EACnB,SAAS,EEzDI,IAAI;EF0DjB,gBAAgB,ECvDC,OAAO;EDwDxB,KAAK,EC1DM,OAAO;ED4DlB,iCAAe;IACb,KAAK,EAAE,OAAO;IACd,OAAO,EAAE,GAAG;IACZ,WAAW,EAAE,IAAI;IACjB,WAAW,EAAE,uDAAuD;;AAIxE,yBAA0B;EACxB,QAAQ,EAAE,QAAQ;EAClB,OAAO,EAAE,CAAC;;AAGZ,yBAA0B;EACxB,IAAI,ECzEY,OAAO;;AD6EvB,8BAAK;EACH,MAAM,EAAE,OAAgB;EACxB,YAAY,EAAE,CAAC;;AAInB,yBAA0B;EACxB,YAAY,EAAE,CAAC;EACf,IAAI,EAAE,wBAAwB;EAC9B,MAAM,EAAE,wBAAwB;;AAGlC,WAAY;EACV,KAAK,EAAE,gBACT;;AACA,WAAY;EACV,KAAK,EAAE,gBACT;;AACA,WAAY;EACV,KAAK,EAAE,gBACT;;AACA,WAAY;EACV,KAAK,EAAE,gBACT;;AAEA,qBAAsB;EAEpB,UAAU,EAAE,GAAG;EACf,2BAAM;IACJ,YAAY,EAAC,GAAG;EAElB,2BAAM;IACJ,YAAY,EAAE,GAAG;EAEnB,oCAAe;IACb,YAAY,EAAE,GAAG;;AAIrB,mBAAmB;EAAC,UAAU,EAAE,KAAK;;AAErC,8BAA+B;EAC7B,MAAM,EAAE,MAAM;EAEd,kCAAI;IACF,MAAM,EAAE,IAAI;IACZ,KAAK,EAAE,IAAI;IACX,WAAW,EAAE,MAAM;EAIrB,2DAA6B;IAC3B,UAAU,EAAE,GAAG;EAGjB,4DAA8B;IAC5B,OAAO,EAAE,YAAY;EAIrB,+CAAK;IACH,IAAI,EC3IG,OAAO;ID4Id,KAAK,EC5IE,OAAO;ID6Id,SAAS,EE7IE,IAAI;EFgJjB,+CAAK;IACH,OAAO,EAAE,GAAG;IACZ,MAAM,ECjJM,OAAO;EDoJrB,kDAAQ;IACN,OAAO,EAAE,GAAG;IACZ,MAAM,ECtJM,OAAO",
|
||||||
"sources": ["../../src/css/_statusmap.scss","../../src/css/_variables.light.scss","../../src/css/_variables.scss"],
|
"sources": ["../../src/css/_statusmap.scss","../../src/css/_variables.light.scss","../../src/css/_variables.scss"],
|
||||||
"names": [],
|
"names": [],
|
||||||
"file": "statusmap.light.css"
|
"file": "statusmap.light.css"
|
||||||
|
|||||||
Vendored
+23
-3
@@ -1,17 +1,37 @@
|
|||||||
<div class="status-heatmap-wrapper">
|
<div class="status-heatmap-wrapper">
|
||||||
<div class="status-heatmap-canvas-wrapper">
|
<div class="status-heatmap-canvas-wrapper">
|
||||||
|
|
||||||
<div class="datapoints-warning" ng-if="ctrl.multipleValues || ctrl.noColorDefined || ctrl.noDatapoints">
|
<div class="datapoints-warning" ng-if="ctrl.multipleValues || ctrl.noColorDefined || ctrl.noDatapoints">
|
||||||
<span class="small" ng-if="ctrl.multipleValues" bs-tooltip="'{{ctrl.dataWarnings.multipleValues.tip}}'">{{ctrl.dataWarnings.multipleValues.title}}</span>
|
<span class="small" ng-if="ctrl.multipleValues" bs-tooltip="'{{ctrl.dataWarnings.multipleValues.tip}}'">{{ctrl.dataWarnings.multipleValues.title}}</span>
|
||||||
<span class="small" ng-if="ctrl.noColorDefined" bs-tooltip="'{{ctrl.dataWarnings.noColorDefined.tip}}'">{{ctrl.dataWarnings.noColorDefined.title}}</span>
|
<span class="small" ng-if="ctrl.noColorDefined" bs-tooltip="'{{ctrl.dataWarnings.noColorDefined.tip}}'">{{ctrl.dataWarnings.noColorDefined.title}}</span>
|
||||||
<span class="small" ng-if="ctrl.noDatapoints" bs-tooltip="'{{ctrl.dataWarnings.noDatapoints.tip}}'">{{ctrl.dataWarnings.noDatapoints.title}}</span>
|
<span class="small" ng-if="ctrl.noDatapoints" bs-tooltip="'{{ctrl.dataWarnings.noDatapoints.tip}}'">{{ctrl.dataWarnings.noDatapoints.title}}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div class="statusmap-panel" ng-dblclick="ctrl.zoomOut()"></div>
|
<div class="statusmap-panel" ng-dblclick="ctrl.zoomOut()"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="status-heatmap-legend-wrapper" ng-if="ctrl.panel.legend.show">
|
<div class="status-heatmap-legend-wrapper" ng-if="ctrl.panel.legend.show">
|
||||||
<status-heatmap-legend></status-heatmap-legend>
|
<status-heatmap-legend></status-heatmap-legend>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="clearfix"></div>
|
||||||
|
|
||||||
|
<div class="statusmap-pagination gf-form" ng-if="ctrl.panel.usingPagination">
|
||||||
|
<div class="gf-form">
|
||||||
|
<button class="btn btn-inverse" ng-disabled="!pager.hasPrev()" ng-click="ctrl.onPrevPage()">
|
||||||
|
<i class="fa fa-arrow-left"></i> Previous
|
||||||
|
</button>
|
||||||
|
<label class="gf-form-label">{{pager.currentPage+1}}/{{pager.pages()}}</label>
|
||||||
|
<button class="btn btn-inverse last-in-group" ng-disabled="!pager.hasNext()" ng-click="ctrl.onNextPage()">
|
||||||
|
Next <i class="fa fa-arrow-right"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="gf-form">
|
||||||
|
<label class="gf-form-label">Rows per page</label>
|
||||||
|
<input type="number" class="gf-form-input width-3 last-in-group" placeholder="12" data-placement="top"
|
||||||
|
bs-tooltip="'Number of rows to show per page.'" ng-model="ctrl.pageSizeViewer" ng-change="ctrl.onChangePageSize()"
|
||||||
|
ng-model-onblur>
|
||||||
|
</div>
|
||||||
|
<label class="gf-form-label">Show {{pager.pageStartRow()}} to {{pager.pageEndRow()}} of {{pager.totalRows()}} rows</label>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="clearfix"></div>
|
<div class="clearfix"></div>
|
||||||
|
|||||||
Vendored
+64
-3
@@ -3,7 +3,7 @@
|
|||||||
System.register(["lodash", "./color_legend", "./options_editor", "./tooltip_editor", "./panel_config_migration", "app/core/utils/kbn", "app/plugins/sdk", "./libs/grafana/events/index", "./statusmap_data", "./rendering", "./libs/polygrafill/index", "./color_mode_discrete"], function (_export, _context) {
|
System.register(["lodash", "./color_legend", "./options_editor", "./tooltip_editor", "./panel_config_migration", "app/core/utils/kbn", "app/plugins/sdk", "./libs/grafana/events/index", "./statusmap_data", "./rendering", "./libs/polygrafill/index", "./color_mode_discrete"], function (_export, _context) {
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var _, optionsEditorCtrl, tooltipEditorCtrl, migratePanelConfig, kbn, loadPluginCss, MetricsPanelCtrl, CoreEvents, PanelEvents, Bucket, BucketMatrix, rendering, Polygrafill, ColorModeDiscrete, VALUE_INDEX, TIME_INDEX, colorSchemes, colorModes, opacityScales, renderComplete, StatusHeatmapCtrl;
|
var _, optionsEditorCtrl, tooltipEditorCtrl, migratePanelConfig, kbn, loadPluginCss, MetricsPanelCtrl, CoreEvents, PanelEvents, Bucket, BucketMatrix, BucketMatrixPager, rendering, Polygrafill, ColorModeDiscrete, VALUE_INDEX, TIME_INDEX, colorSchemes, colorModes, opacityScales, renderComplete, StatusHeatmapCtrl;
|
||||||
|
|
||||||
function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
|
function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
|
||||||
|
|
||||||
@@ -49,6 +49,7 @@ System.register(["lodash", "./color_legend", "./options_editor", "./tooltip_edit
|
|||||||
}, function (_statusmap_data) {
|
}, function (_statusmap_data) {
|
||||||
Bucket = _statusmap_data.Bucket;
|
Bucket = _statusmap_data.Bucket;
|
||||||
BucketMatrix = _statusmap_data.BucketMatrix;
|
BucketMatrix = _statusmap_data.BucketMatrix;
|
||||||
|
BucketMatrixPager = _statusmap_data.BucketMatrixPager;
|
||||||
}, function (_rendering) {
|
}, function (_rendering) {
|
||||||
rendering = _rendering.default;
|
rendering = _rendering.default;
|
||||||
}, function (_libsPolygrafillIndex) {
|
}, function (_libsPolygrafillIndex) {
|
||||||
@@ -166,6 +167,8 @@ System.register(["lodash", "./color_legend", "./options_editor", "./tooltip_edit
|
|||||||
|
|
||||||
_inherits(StatusHeatmapCtrl, _MetricsPanelCtrl);
|
_inherits(StatusHeatmapCtrl, _MetricsPanelCtrl);
|
||||||
|
|
||||||
|
// TODO remove this transient variable: use ng-model-options="{ getterSetter: true }"
|
||||||
|
|
||||||
/** @ngInject */
|
/** @ngInject */
|
||||||
function StatusHeatmapCtrl($scope, $injector, timeSrv, annotationsSrv, $window, datasourceSrv, variableSrv, templateSrv) {
|
function StatusHeatmapCtrl($scope, $injector, timeSrv, annotationsSrv, $window, datasourceSrv, variableSrv, templateSrv) {
|
||||||
var _this;
|
var _this;
|
||||||
@@ -180,6 +183,8 @@ System.register(["lodash", "./color_legend", "./options_editor", "./tooltip_edit
|
|||||||
|
|
||||||
_defineProperty(_assertThisInitialized(_this), "bucketMatrix", void 0);
|
_defineProperty(_assertThisInitialized(_this), "bucketMatrix", void 0);
|
||||||
|
|
||||||
|
_defineProperty(_assertThisInitialized(_this), "bucketMatrixPager", void 0);
|
||||||
|
|
||||||
_defineProperty(_assertThisInitialized(_this), "graph", void 0);
|
_defineProperty(_assertThisInitialized(_this), "graph", void 0);
|
||||||
|
|
||||||
_defineProperty(_assertThisInitialized(_this), "discreteHelper", void 0);
|
_defineProperty(_assertThisInitialized(_this), "discreteHelper", void 0);
|
||||||
@@ -206,6 +211,8 @@ System.register(["lodash", "./color_legend", "./options_editor", "./tooltip_edit
|
|||||||
|
|
||||||
_defineProperty(_assertThisInitialized(_this), "annotationsPromise", void 0);
|
_defineProperty(_assertThisInitialized(_this), "annotationsPromise", void 0);
|
||||||
|
|
||||||
|
_defineProperty(_assertThisInitialized(_this), "pageSizeViewer", 15);
|
||||||
|
|
||||||
_defineProperty(_assertThisInitialized(_this), "panelDefaults", {
|
_defineProperty(_assertThisInitialized(_this), "panelDefaults", {
|
||||||
// datasource name, null = default datasource
|
// datasource name, null = default datasource
|
||||||
datasource: null,
|
datasource: null,
|
||||||
@@ -251,7 +258,10 @@ System.register(["lodash", "./color_legend", "./options_editor", "./tooltip_edit
|
|||||||
yAxisSort: 'metrics',
|
yAxisSort: 'metrics',
|
||||||
highlightCards: true,
|
highlightCards: true,
|
||||||
useMax: true,
|
useMax: true,
|
||||||
seriesFilterIndex: -1
|
seriesFilterIndex: -1,
|
||||||
|
// Pagination options
|
||||||
|
usingPagination: false,
|
||||||
|
pageSize: 15
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!Polygrafill.hasAppEventCompatibleEmitter(_this.events)) {
|
if (!Polygrafill.hasAppEventCompatibleEmitter(_this.events)) {
|
||||||
@@ -265,6 +275,17 @@ System.register(["lodash", "./color_legend", "./options_editor", "./tooltip_edit
|
|||||||
|
|
||||||
_.defaultsDeep(_this.panel, _this.panelDefaults);
|
_.defaultsDeep(_this.panel, _this.panelDefaults);
|
||||||
|
|
||||||
|
_this.bucketMatrix = new BucketMatrix(); // Create pager for bucketMatrix and restore page size.
|
||||||
|
|
||||||
|
_this.bucketMatrixPager = new BucketMatrixPager();
|
||||||
|
|
||||||
|
_this.bucketMatrixPager.setEnable(_this.panel.usingPagination);
|
||||||
|
|
||||||
|
_this.bucketMatrixPager.setDefaultPageSize(_this.panel.pageSize);
|
||||||
|
|
||||||
|
_this.bucketMatrixPager.setPageSize(_this.panel.pageSize);
|
||||||
|
|
||||||
|
$scope.pager = _this.bucketMatrixPager;
|
||||||
_this.opacityScales = opacityScales;
|
_this.opacityScales = opacityScales;
|
||||||
_this.colorModes = colorModes;
|
_this.colorModes = colorModes;
|
||||||
_this.colorSchemes = colorSchemes; // default graph width for discrete card width calculation
|
_this.colorSchemes = colorSchemes; // default graph width for discrete card width calculation
|
||||||
@@ -317,6 +338,39 @@ System.register(["lodash", "./color_legend", "./options_editor", "./tooltip_edit
|
|||||||
value: function onRenderComplete(data) {
|
value: function onRenderComplete(data) {
|
||||||
this.graph.chartWidth = data.chartWidth;
|
this.graph.chartWidth = data.chartWidth;
|
||||||
this.renderingCompleted();
|
this.renderingCompleted();
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: "changeDefaultPaginationSize",
|
||||||
|
value: function changeDefaultPaginationSize(defaultPageSize) {
|
||||||
|
this.bucketMatrixPager.setDefaultPageSize(defaultPageSize);
|
||||||
|
this.bucketMatrixPager.setPageSize(defaultPageSize);
|
||||||
|
this.pageSizeViewer = defaultPageSize;
|
||||||
|
this.render();
|
||||||
|
this.refresh();
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: "onChangePageSize",
|
||||||
|
value: function onChangePageSize() {
|
||||||
|
if (this.pageSizeViewer <= 0) {
|
||||||
|
this.pageSizeViewer = this.bucketMatrixPager.defaultPageSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.bucketMatrixPager.setPageSize(this.pageSizeViewer);
|
||||||
|
this.bucketMatrixPager.setCurrent(0);
|
||||||
|
this.render();
|
||||||
|
this.refresh();
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: "onPrevPage",
|
||||||
|
value: function onPrevPage() {
|
||||||
|
this.bucketMatrixPager.switchToPrev();
|
||||||
|
this.render();
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: "onNextPage",
|
||||||
|
value: function onNextPage() {
|
||||||
|
this.bucketMatrixPager.switchToNext();
|
||||||
|
this.render();
|
||||||
} // getChartWidth returns an approximation of chart canvas width or
|
} // getChartWidth returns an approximation of chart canvas width or
|
||||||
// a saved value calculated during a render.
|
// a saved value calculated during a render.
|
||||||
|
|
||||||
@@ -445,7 +499,14 @@ System.register(["lodash", "./color_legend", "./options_editor", "./tooltip_edit
|
|||||||
this.calculateInterval();
|
this.calculateInterval();
|
||||||
}
|
}
|
||||||
|
|
||||||
this.bucketMatrix = this.convertDataToBuckets(dataList, this.range.from.valueOf(), this.range.to.valueOf(), this.intervalMs, true);
|
var newBucketMatrix = this.convertDataToBuckets(dataList, this.range.from.valueOf(), this.range.to.valueOf(), this.intervalMs, true);
|
||||||
|
this.bucketMatrix = newBucketMatrix;
|
||||||
|
this.bucketMatrixPager.bucketMatrix = newBucketMatrix;
|
||||||
|
|
||||||
|
if (newBucketMatrix.targets.length !== this.bucketMatrix.targets.length) {
|
||||||
|
this.bucketMatrixPager.setCurrent(0);
|
||||||
|
}
|
||||||
|
|
||||||
this.noDatapoints = this.bucketMatrix.noDatapoints;
|
this.noDatapoints = this.bucketMatrix.noDatapoints;
|
||||||
|
|
||||||
if (this.annotationsPromise) {
|
if (this.annotationsPromise) {
|
||||||
|
|||||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+14
@@ -216,4 +216,18 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="section gf-form-group">
|
||||||
|
<h5 class="section-heading">Pagination</h5>
|
||||||
|
<div class="gf-form">
|
||||||
|
<gf-form-switch class="gf-form" label="Enable pagination" label-class="width-12"
|
||||||
|
checked="ctrl.panel.usingPagination" on-change="ctrl.render()"></gf-form-switch>
|
||||||
|
</div>
|
||||||
|
<div class="gf-form" ng-if="ctrl.panel.usingPagination">
|
||||||
|
<label class="gf-form-label width-10">Rows per page</label>
|
||||||
|
<input type="number" class="gf-form-input width-5" placeholder="2" data-placement="top"
|
||||||
|
bs-tooltip="'Number of rows to show by default'" ng-model="ctrl.panel.pageSize" ng-change="ctrl.changeDefaultPaginationSize(ctrl.panel.pageSize)"
|
||||||
|
ng-model-onblur>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Vendored
+15
-6
@@ -153,6 +153,8 @@ System.register(["lodash", "jquery", "moment", "app/core/utils/kbn", "app/core/c
|
|||||||
|
|
||||||
_defineProperty(this, "bucketMatrix", void 0);
|
_defineProperty(this, "bucketMatrix", void 0);
|
||||||
|
|
||||||
|
_defineProperty(this, "bucketMatrixPager", void 0);
|
||||||
|
|
||||||
_defineProperty(this, "panel", void 0);
|
_defineProperty(this, "panel", void 0);
|
||||||
|
|
||||||
_defineProperty(this, "$heatmap", void 0);
|
_defineProperty(this, "$heatmap", void 0);
|
||||||
@@ -238,7 +240,14 @@ System.register(["lodash", "jquery", "moment", "app/core/utils/kbn", "app/core/c
|
|||||||
height = parseInt(height.replace('px', ''), 10);
|
height = parseInt(height.replace('px', ''), 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
height -= this.panel.legend.show ? 32 : 10; // bottom padding and space for legend. Change margin in .status-heatmap-color-legend !
|
if (this.panel.usingPagination) {
|
||||||
|
// TODO get height of pagination controls.
|
||||||
|
// reserve height for legend and for a row of pagination controls.
|
||||||
|
height -= this.panel.legend.show ? 70 : 40; // bottom padding and space for legend. Change margin in .status-heatmap-color-legend !
|
||||||
|
} else {
|
||||||
|
// reserve height for legend
|
||||||
|
height -= this.panel.legend.show ? 32 : 4; // bottom padding and space for legend. Change margin in .status-heatmap-color-legend !
|
||||||
|
}
|
||||||
|
|
||||||
this.$heatmap.css('height', height + 'px');
|
this.$heatmap.css('height', height + 'px');
|
||||||
return true;
|
return true;
|
||||||
@@ -334,7 +343,7 @@ System.register(["lodash", "jquery", "moment", "app/core/utils/kbn", "app/core/c
|
|||||||
}, {
|
}, {
|
||||||
key: "addYAxis",
|
key: "addYAxis",
|
||||||
value: function addYAxis() {
|
value: function addYAxis() {
|
||||||
var ticks = this.bucketMatrix.targets;
|
var ticks = this.bucketMatrixPager.targets(); // TODO move sorting into bucketMatrixPager.
|
||||||
|
|
||||||
if (this.panel.yAxisSort == 'a → z') {
|
if (this.panel.yAxisSort == 'a → z') {
|
||||||
ticks.sort(function (a, b) {
|
ticks.sort(function (a, b) {
|
||||||
@@ -424,8 +433,8 @@ System.register(["lodash", "jquery", "moment", "app/core/utils/kbn", "app/core/c
|
|||||||
|
|
||||||
this.yGridSize = this.chartHeight;
|
this.yGridSize = this.chartHeight;
|
||||||
|
|
||||||
if (this.bucketMatrix.targets.length > 0) {
|
if (this.bucketMatrixPager.targets().length > 0) {
|
||||||
this.yGridSize = Math.floor(this.chartHeight / this.bucketMatrix.targets.length);
|
this.yGridSize = Math.floor(this.chartHeight / this.bucketMatrixPager.targets().length);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.cardHeight = this.yGridSize ? this.yGridSize - this.cardVSpacing : 0;
|
this.cardHeight = this.yGridSize ? this.yGridSize - this.cardVSpacing : 0;
|
||||||
@@ -462,7 +471,7 @@ System.register(["lodash", "jquery", "moment", "app/core/utils/kbn", "app/core/c
|
|||||||
|
|
||||||
this.setOpacityScale(maxValue); // Draw cards from buckets.
|
this.setOpacityScale(maxValue); // Draw cards from buckets.
|
||||||
|
|
||||||
this.heatmap.selectAll(".statusmap-cards-row").data(this.bucketMatrix.targets).enter().selectAll(".statustmap-card").data(function (target) {
|
this.heatmap.selectAll(".statusmap-cards-row").data(this.bucketMatrixPager.targets()).enter().selectAll(".statustmap-card").data(function (target) {
|
||||||
return _this.bucketMatrix.buckets[target];
|
return _this.bucketMatrix.buckets[target];
|
||||||
}).enter().append("rect").attr("cardId", function (b) {
|
}).enter().append("rect").attr("cardId", function (b) {
|
||||||
return b.id;
|
return b.id;
|
||||||
@@ -581,7 +590,6 @@ System.register(["lodash", "jquery", "moment", "app/core/utils/kbn", "app/core/c
|
|||||||
return w;
|
return w;
|
||||||
} // Top y for card.
|
} // Top y for card.
|
||||||
// yScale gives ???
|
// yScale gives ???
|
||||||
//
|
|
||||||
|
|
||||||
}, {
|
}, {
|
||||||
key: "getCardY",
|
key: "getCardY",
|
||||||
@@ -842,6 +850,7 @@ System.register(["lodash", "jquery", "moment", "app/core/utils/kbn", "app/core/c
|
|||||||
this.panel = this.ctrl.panel;
|
this.panel = this.ctrl.panel;
|
||||||
this.timeRange = this.ctrl.range;
|
this.timeRange = this.ctrl.range;
|
||||||
this.bucketMatrix = this.ctrl.bucketMatrix;
|
this.bucketMatrix = this.ctrl.bucketMatrix;
|
||||||
|
this.bucketMatrixPager = this.ctrl.bucketMatrixPager;
|
||||||
|
|
||||||
if (!this.bucketMatrix || !this.setElementHeight()) {
|
if (!this.bucketMatrix || !this.setElementHeight()) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+145
-1
@@ -3,7 +3,7 @@
|
|||||||
System.register([], function (_export, _context) {
|
System.register([], function (_export, _context) {
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var Bucket, BucketMatrix;
|
var Bucket, BucketMatrix, pagerChanged, BucketMatrixPager;
|
||||||
|
|
||||||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
||||||
|
|
||||||
@@ -98,6 +98,7 @@ System.register([], function (_export, _context) {
|
|||||||
function () {
|
function () {
|
||||||
// buckets for each y label
|
// buckets for each y label
|
||||||
// a flag that indicate that buckets has stub values
|
// a flag that indicate that buckets has stub values
|
||||||
|
// An array of row labels
|
||||||
// TODO remove: a transition from CardsData
|
// TODO remove: a transition from CardsData
|
||||||
function BucketMatrix() {
|
function BucketMatrix() {
|
||||||
_classCallCheck(this, BucketMatrix);
|
_classCallCheck(this, BucketMatrix);
|
||||||
@@ -155,6 +156,149 @@ System.register([], function (_export, _context) {
|
|||||||
|
|
||||||
return BucketMatrix;
|
return BucketMatrix;
|
||||||
}());
|
}());
|
||||||
|
|
||||||
|
_export("pagerChanged", pagerChanged = {
|
||||||
|
name: 'statusmap-pager-changed'
|
||||||
|
});
|
||||||
|
|
||||||
|
_export("BucketMatrixPager", BucketMatrixPager =
|
||||||
|
/*#__PURE__*/
|
||||||
|
function () {
|
||||||
|
function BucketMatrixPager() {
|
||||||
|
_classCallCheck(this, BucketMatrixPager);
|
||||||
|
|
||||||
|
_defineProperty(this, "bucketMatrix", void 0);
|
||||||
|
|
||||||
|
_defineProperty(this, "enable", void 0);
|
||||||
|
|
||||||
|
_defineProperty(this, "defaultPageSize", -1);
|
||||||
|
|
||||||
|
_defineProperty(this, "pageSize", -1);
|
||||||
|
|
||||||
|
_defineProperty(this, "currentPage", 0);
|
||||||
|
|
||||||
|
var m = new BucketMatrix();
|
||||||
|
this.bucketMatrix = m;
|
||||||
|
} // An array of row labels for current page.
|
||||||
|
|
||||||
|
|
||||||
|
_createClass(BucketMatrixPager, [{
|
||||||
|
key: "targets",
|
||||||
|
value: function targets() {
|
||||||
|
if (!this.enable) {
|
||||||
|
return this.bucketMatrix.targets;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.bucketMatrix.targets.slice(this.pageSize * this.currentPage, this.pageSize * (this.currentPage + 1));
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: "buckets",
|
||||||
|
value: function buckets() {
|
||||||
|
if (!this.enable) {
|
||||||
|
return this.bucketMatrix.buckets;
|
||||||
|
}
|
||||||
|
|
||||||
|
var buckets = {};
|
||||||
|
var me = this;
|
||||||
|
this.targets().map(function (rowLabel) {
|
||||||
|
buckets[rowLabel] = me.bucketMatrix.buckets[rowLabel];
|
||||||
|
});
|
||||||
|
return buckets;
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: "setEnable",
|
||||||
|
value: function setEnable(enable) {
|
||||||
|
this.enable = enable;
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: "setCurrent",
|
||||||
|
value: function setCurrent(num) {
|
||||||
|
this.currentPage = num;
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: "setDefaultPageSize",
|
||||||
|
value: function setDefaultPageSize(num) {
|
||||||
|
this.defaultPageSize = num;
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: "setPageSize",
|
||||||
|
value: function setPageSize(num) {
|
||||||
|
this.pageSize = num;
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: "pages",
|
||||||
|
value: function pages() {
|
||||||
|
return Math.ceil(this.totalRows() / this.pageSize);
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: "totalRows",
|
||||||
|
value: function totalRows() {
|
||||||
|
return this.bucketMatrix.targets.length;
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: "pageStartRow",
|
||||||
|
value: function pageStartRow() {
|
||||||
|
if (!this.enable) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.pageSize * this.currentPage + 1;
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: "pageEndRow",
|
||||||
|
value: function pageEndRow() {
|
||||||
|
if (!this.enable) {
|
||||||
|
return this.totalRows();
|
||||||
|
}
|
||||||
|
|
||||||
|
var last = this.pageSize * (this.currentPage + 1);
|
||||||
|
|
||||||
|
if (last > this.totalRows()) {
|
||||||
|
return this.totalRows();
|
||||||
|
}
|
||||||
|
|
||||||
|
return last;
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: "hasNext",
|
||||||
|
value: function hasNext() {
|
||||||
|
if (!this.enable) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((this.currentPage + 1) * this.pageSize >= this.totalRows()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true; // currentPage >= ctrl.bucketMatrix.targets.length/ctrl.pageSizeViewer - 1 || ctrl.numberOfPages == 0
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: "hasPrev",
|
||||||
|
value: function hasPrev() {
|
||||||
|
if (!this.enable) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.currentPage > 0;
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: "switchToNext",
|
||||||
|
value: function switchToNext() {
|
||||||
|
if (this.hasNext()) {
|
||||||
|
this.currentPage = this.currentPage + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: "switchToPrev",
|
||||||
|
value: function switchToPrev() {
|
||||||
|
if (this.hasPrev()) {
|
||||||
|
this.currentPage = this.currentPage - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}]);
|
||||||
|
|
||||||
|
return BucketMatrixPager;
|
||||||
|
}());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|||||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
@@ -102,6 +102,22 @@
|
|||||||
width: 70.0rem!important
|
width: 70.0rem!important
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.statusmap-pagination {
|
||||||
|
// space between legend and pagination controls
|
||||||
|
margin-top: 5px;
|
||||||
|
label {
|
||||||
|
margin-right:0px;
|
||||||
|
}
|
||||||
|
input {
|
||||||
|
margin-right: 0px;
|
||||||
|
}
|
||||||
|
.last-in-group {
|
||||||
|
margin-right: 4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.pagination-buttons{text-align: right;}
|
||||||
|
|
||||||
.status-heatmap-legend-wrapper {
|
.status-heatmap-legend-wrapper {
|
||||||
margin: 0 10px;
|
margin: 0 10px;
|
||||||
|
|
||||||
|
|||||||
+23
-3
@@ -1,17 +1,37 @@
|
|||||||
<div class="status-heatmap-wrapper">
|
<div class="status-heatmap-wrapper">
|
||||||
<div class="status-heatmap-canvas-wrapper">
|
<div class="status-heatmap-canvas-wrapper">
|
||||||
|
|
||||||
<div class="datapoints-warning" ng-if="ctrl.multipleValues || ctrl.noColorDefined || ctrl.noDatapoints">
|
<div class="datapoints-warning" ng-if="ctrl.multipleValues || ctrl.noColorDefined || ctrl.noDatapoints">
|
||||||
<span class="small" ng-if="ctrl.multipleValues" bs-tooltip="'{{ctrl.dataWarnings.multipleValues.tip}}'">{{ctrl.dataWarnings.multipleValues.title}}</span>
|
<span class="small" ng-if="ctrl.multipleValues" bs-tooltip="'{{ctrl.dataWarnings.multipleValues.tip}}'">{{ctrl.dataWarnings.multipleValues.title}}</span>
|
||||||
<span class="small" ng-if="ctrl.noColorDefined" bs-tooltip="'{{ctrl.dataWarnings.noColorDefined.tip}}'">{{ctrl.dataWarnings.noColorDefined.title}}</span>
|
<span class="small" ng-if="ctrl.noColorDefined" bs-tooltip="'{{ctrl.dataWarnings.noColorDefined.tip}}'">{{ctrl.dataWarnings.noColorDefined.title}}</span>
|
||||||
<span class="small" ng-if="ctrl.noDatapoints" bs-tooltip="'{{ctrl.dataWarnings.noDatapoints.tip}}'">{{ctrl.dataWarnings.noDatapoints.title}}</span>
|
<span class="small" ng-if="ctrl.noDatapoints" bs-tooltip="'{{ctrl.dataWarnings.noDatapoints.tip}}'">{{ctrl.dataWarnings.noDatapoints.title}}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div class="statusmap-panel" ng-dblclick="ctrl.zoomOut()"></div>
|
<div class="statusmap-panel" ng-dblclick="ctrl.zoomOut()"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="status-heatmap-legend-wrapper" ng-if="ctrl.panel.legend.show">
|
<div class="status-heatmap-legend-wrapper" ng-if="ctrl.panel.legend.show">
|
||||||
<status-heatmap-legend></status-heatmap-legend>
|
<status-heatmap-legend></status-heatmap-legend>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="clearfix"></div>
|
||||||
|
|
||||||
|
<div class="statusmap-pagination gf-form" ng-if="ctrl.panel.usingPagination">
|
||||||
|
<div class="gf-form">
|
||||||
|
<button class="btn btn-inverse" ng-disabled="!pager.hasPrev()" ng-click="ctrl.onPrevPage()">
|
||||||
|
<i class="fa fa-arrow-left"></i> Previous
|
||||||
|
</button>
|
||||||
|
<label class="gf-form-label">{{pager.currentPage+1}}/{{pager.pages()}}</label>
|
||||||
|
<button class="btn btn-inverse last-in-group" ng-disabled="!pager.hasNext()" ng-click="ctrl.onNextPage()">
|
||||||
|
Next <i class="fa fa-arrow-right"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="gf-form">
|
||||||
|
<label class="gf-form-label">Rows per page</label>
|
||||||
|
<input type="number" class="gf-form-input width-3 last-in-group" placeholder="12" data-placement="top"
|
||||||
|
bs-tooltip="'Number of rows to show per page.'" ng-model="ctrl.pageSizeViewer" ng-change="ctrl.onChangePageSize()"
|
||||||
|
ng-model-onblur>
|
||||||
|
</div>
|
||||||
|
<label class="gf-form-label">Show {{pager.pageStartRow()}} to {{pager.pageEndRow()}} of {{pager.totalRows()}} rows</label>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="clearfix"></div>
|
<div class="clearfix"></div>
|
||||||
|
|||||||
+59
-3
@@ -16,7 +16,7 @@ import {loadPluginCss} from 'app/plugins/sdk';
|
|||||||
import { MetricsPanelCtrl } from 'app/plugins/sdk';
|
import { MetricsPanelCtrl } from 'app/plugins/sdk';
|
||||||
import { AnnotationsSrv } from 'app/features/annotations/annotations_srv';
|
import { AnnotationsSrv } from 'app/features/annotations/annotations_srv';
|
||||||
import { CoreEvents, PanelEvents } from './libs/grafana/events/index';
|
import { CoreEvents, PanelEvents } from './libs/grafana/events/index';
|
||||||
import { Bucket, BucketMatrix } from './statusmap_data';
|
import {Bucket, BucketMatrix, BucketMatrixPager } from './statusmap_data';
|
||||||
import rendering from './rendering';
|
import rendering from './rendering';
|
||||||
import { Polygrafill } from './libs/polygrafill/index';
|
import { Polygrafill } from './libs/polygrafill/index';
|
||||||
|
|
||||||
@@ -70,6 +70,7 @@ class StatusHeatmapCtrl extends MetricsPanelCtrl {
|
|||||||
|
|
||||||
data: any;
|
data: any;
|
||||||
bucketMatrix: BucketMatrix;
|
bucketMatrix: BucketMatrix;
|
||||||
|
bucketMatrixPager: BucketMatrixPager;
|
||||||
|
|
||||||
graph: any;
|
graph: any;
|
||||||
discreteHelper: ColorModeDiscrete;
|
discreteHelper: ColorModeDiscrete;
|
||||||
@@ -88,6 +89,9 @@ class StatusHeatmapCtrl extends MetricsPanelCtrl {
|
|||||||
annotations: object[] = [];
|
annotations: object[] = [];
|
||||||
annotationsPromise: any;
|
annotationsPromise: any;
|
||||||
|
|
||||||
|
// TODO remove this transient variable: use ng-model-options="{ getterSetter: true }"
|
||||||
|
pageSizeViewer: number = 15;
|
||||||
|
|
||||||
panelDefaults: any = {
|
panelDefaults: any = {
|
||||||
// datasource name, null = default datasource
|
// datasource name, null = default datasource
|
||||||
datasource: null,
|
datasource: null,
|
||||||
@@ -132,7 +136,11 @@ class StatusHeatmapCtrl extends MetricsPanelCtrl {
|
|||||||
highlightCards: true,
|
highlightCards: true,
|
||||||
useMax: true,
|
useMax: true,
|
||||||
|
|
||||||
seriesFilterIndex: -1
|
seriesFilterIndex: -1,
|
||||||
|
|
||||||
|
// Pagination options
|
||||||
|
usingPagination: false,
|
||||||
|
pageSize: 15
|
||||||
};
|
};
|
||||||
|
|
||||||
/** @ngInject */
|
/** @ngInject */
|
||||||
@@ -148,6 +156,15 @@ class StatusHeatmapCtrl extends MetricsPanelCtrl {
|
|||||||
migratePanelConfig(this.panel);
|
migratePanelConfig(this.panel);
|
||||||
_.defaultsDeep(this.panel, this.panelDefaults);
|
_.defaultsDeep(this.panel, this.panelDefaults);
|
||||||
|
|
||||||
|
this.bucketMatrix = new BucketMatrix();
|
||||||
|
|
||||||
|
// Create pager for bucketMatrix and restore page size.
|
||||||
|
this.bucketMatrixPager = new BucketMatrixPager();
|
||||||
|
this.bucketMatrixPager.setEnable(this.panel.usingPagination);
|
||||||
|
this.bucketMatrixPager.setDefaultPageSize(this.panel.pageSize);
|
||||||
|
this.bucketMatrixPager.setPageSize(this.panel.pageSize);
|
||||||
|
$scope.pager = this.bucketMatrixPager;
|
||||||
|
|
||||||
this.opacityScales = opacityScales;
|
this.opacityScales = opacityScales;
|
||||||
this.colorModes = colorModes;
|
this.colorModes = colorModes;
|
||||||
this.colorSchemes = colorSchemes;
|
this.colorSchemes = colorSchemes;
|
||||||
@@ -199,6 +216,37 @@ class StatusHeatmapCtrl extends MetricsPanelCtrl {
|
|||||||
this.renderingCompleted();
|
this.renderingCompleted();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
changeDefaultPaginationSize(defaultPageSize: number): void {
|
||||||
|
this.bucketMatrixPager.setDefaultPageSize(defaultPageSize);
|
||||||
|
this.bucketMatrixPager.setPageSize(defaultPageSize);
|
||||||
|
this.pageSizeViewer = defaultPageSize;
|
||||||
|
|
||||||
|
this.render();
|
||||||
|
this.refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
onChangePageSize(): void {
|
||||||
|
if (this.pageSizeViewer <= 0) {
|
||||||
|
this.pageSizeViewer = this.bucketMatrixPager.defaultPageSize;
|
||||||
|
}
|
||||||
|
this.bucketMatrixPager.setPageSize(this.pageSizeViewer);
|
||||||
|
this.bucketMatrixPager.setCurrent(0);
|
||||||
|
|
||||||
|
this.render();
|
||||||
|
this.refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
onPrevPage(): void {
|
||||||
|
this.bucketMatrixPager.switchToPrev();
|
||||||
|
this.render();
|
||||||
|
}
|
||||||
|
|
||||||
|
onNextPage(): void {
|
||||||
|
this.bucketMatrixPager.switchToNext();
|
||||||
|
this.render();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// getChartWidth returns an approximation of chart canvas width or
|
// getChartWidth returns an approximation of chart canvas width or
|
||||||
// a saved value calculated during a render.
|
// a saved value calculated during a render.
|
||||||
getChartWidth():number {
|
getChartWidth():number {
|
||||||
@@ -320,7 +368,15 @@ class StatusHeatmapCtrl extends MetricsPanelCtrl {
|
|||||||
if (!this.intervalMs) {
|
if (!this.intervalMs) {
|
||||||
this.calculateInterval();
|
this.calculateInterval();
|
||||||
}
|
}
|
||||||
this.bucketMatrix = this.convertDataToBuckets(dataList, this.range.from.valueOf(), this.range.to.valueOf(), this.intervalMs, true);
|
|
||||||
|
let newBucketMatrix = this.convertDataToBuckets(dataList, this.range.from.valueOf(), this.range.to.valueOf(), this.intervalMs, true);
|
||||||
|
|
||||||
|
this.bucketMatrix = newBucketMatrix;
|
||||||
|
this.bucketMatrixPager.bucketMatrix = newBucketMatrix;
|
||||||
|
if (newBucketMatrix.targets.length !== this.bucketMatrix.targets.length) {
|
||||||
|
this.bucketMatrixPager.setCurrent(0);
|
||||||
|
}
|
||||||
|
|
||||||
this.noDatapoints = this.bucketMatrix.noDatapoints;
|
this.noDatapoints = this.bucketMatrix.noDatapoints;
|
||||||
|
|
||||||
if (this.annotationsPromise) {
|
if (this.annotationsPromise) {
|
||||||
|
|||||||
@@ -216,4 +216,18 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="section gf-form-group">
|
||||||
|
<h5 class="section-heading">Pagination</h5>
|
||||||
|
<div class="gf-form">
|
||||||
|
<gf-form-switch class="gf-form" label="Enable pagination" label-class="width-12"
|
||||||
|
checked="ctrl.panel.usingPagination" on-change="ctrl.render()"></gf-form-switch>
|
||||||
|
</div>
|
||||||
|
<div class="gf-form" ng-if="ctrl.panel.usingPagination">
|
||||||
|
<label class="gf-form-label width-10">Rows per page</label>
|
||||||
|
<input type="number" class="gf-form-input width-5" placeholder="2" data-placement="top"
|
||||||
|
bs-tooltip="'Number of rows to show by default'" ng-model="ctrl.panel.pageSize" ng-change="ctrl.changeDefaultPaginationSize(ctrl.panel.pageSize)"
|
||||||
|
ng-model-onblur>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+16
-8
@@ -7,7 +7,7 @@ import * as d3 from 'd3';
|
|||||||
import * as d3ScaleChromatic from './libs/d3-scale-chromatic/index';
|
import * as d3ScaleChromatic from './libs/d3-scale-chromatic/index';
|
||||||
import {StatusmapTooltip} from './tooltip';
|
import {StatusmapTooltip} from './tooltip';
|
||||||
import {AnnotationTooltip} from './annotations';
|
import {AnnotationTooltip} from './annotations';
|
||||||
import { Bucket, BucketMatrix } from './statusmap_data';
|
import { Bucket, BucketMatrix, BucketMatrixPager } from './statusmap_data';
|
||||||
import { StatusHeatmapCtrl, renderComplete } from './module';
|
import { StatusHeatmapCtrl, renderComplete } from './module';
|
||||||
import { CoreEvents, PanelEvents } from './libs/grafana/events/index';
|
import { CoreEvents, PanelEvents } from './libs/grafana/events/index';
|
||||||
|
|
||||||
@@ -61,6 +61,7 @@ export class StatusmapRenderer {
|
|||||||
yGridSize: number = 0;
|
yGridSize: number = 0;
|
||||||
|
|
||||||
bucketMatrix: BucketMatrix;
|
bucketMatrix: BucketMatrix;
|
||||||
|
bucketMatrixPager: BucketMatrixPager;
|
||||||
panel: any;
|
panel: any;
|
||||||
$heatmap: any;
|
$heatmap: any;
|
||||||
tooltip: StatusmapTooltip;
|
tooltip: StatusmapTooltip;
|
||||||
@@ -133,7 +134,14 @@ export class StatusmapRenderer {
|
|||||||
height = parseInt(height.replace('px', ''), 10);
|
height = parseInt(height.replace('px', ''), 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
height -= this.panel.legend.show ? 32 : 10; // bottom padding and space for legend. Change margin in .status-heatmap-color-legend !
|
if (this.panel.usingPagination) {
|
||||||
|
// TODO get height of pagination controls.
|
||||||
|
// reserve height for legend and for a row of pagination controls.
|
||||||
|
height -= this.panel.legend.show ? 70 : 40; // bottom padding and space for legend. Change margin in .status-heatmap-color-legend !
|
||||||
|
} else {
|
||||||
|
// reserve height for legend
|
||||||
|
height -= this.panel.legend.show ? 32 : 4; // bottom padding and space for legend. Change margin in .status-heatmap-color-legend !
|
||||||
|
}
|
||||||
|
|
||||||
this.$heatmap.css('height', height + 'px');
|
this.$heatmap.css('height', height + 'px');
|
||||||
|
|
||||||
@@ -236,8 +244,9 @@ export class StatusmapRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
addYAxis() {
|
addYAxis() {
|
||||||
let ticks = this.bucketMatrix.targets;
|
let ticks = this.bucketMatrixPager.targets();
|
||||||
|
|
||||||
|
// TODO move sorting into bucketMatrixPager.
|
||||||
if (this.panel.yAxisSort == 'a → z') {
|
if (this.panel.yAxisSort == 'a → z') {
|
||||||
ticks.sort((a, b) => a.localeCompare(b, 'en', {ignorePunctuation: false, numeric: true}));
|
ticks.sort((a, b) => a.localeCompare(b, 'en', {ignorePunctuation: false, numeric: true}));
|
||||||
} else if (this.panel.yAxisSort == 'z → a') {
|
} else if (this.panel.yAxisSort == 'z → a') {
|
||||||
@@ -326,8 +335,8 @@ export class StatusmapRenderer {
|
|||||||
|
|
||||||
// calculate yOffset for YAxis
|
// calculate yOffset for YAxis
|
||||||
this.yGridSize = this.chartHeight;
|
this.yGridSize = this.chartHeight;
|
||||||
if (this.bucketMatrix.targets.length > 0) {
|
if (this.bucketMatrixPager.targets().length > 0) {
|
||||||
this.yGridSize = Math.floor(this.chartHeight / this.bucketMatrix.targets.length);
|
this.yGridSize = Math.floor(this.chartHeight / this.bucketMatrixPager.targets().length);
|
||||||
}
|
}
|
||||||
this.cardHeight = this.yGridSize ? this.yGridSize - this.cardVSpacing : 0;
|
this.cardHeight = this.yGridSize ? this.yGridSize - this.cardVSpacing : 0;
|
||||||
this.yOffset = this.cardHeight / 2;
|
this.yOffset = this.cardHeight / 2;
|
||||||
@@ -364,7 +373,7 @@ export class StatusmapRenderer {
|
|||||||
this.setOpacityScale(maxValue);
|
this.setOpacityScale(maxValue);
|
||||||
|
|
||||||
// Draw cards from buckets.
|
// Draw cards from buckets.
|
||||||
this.heatmap.selectAll(".statusmap-cards-row").data(this.bucketMatrix.targets)
|
this.heatmap.selectAll(".statusmap-cards-row").data(this.bucketMatrixPager.targets())
|
||||||
.enter()
|
.enter()
|
||||||
.selectAll(".statustmap-card")
|
.selectAll(".statustmap-card")
|
||||||
.data((target:string) => this.bucketMatrix.buckets[target])
|
.data((target:string) => this.bucketMatrix.buckets[target])
|
||||||
@@ -501,7 +510,6 @@ export class StatusmapRenderer {
|
|||||||
|
|
||||||
// Top y for card.
|
// Top y for card.
|
||||||
// yScale gives ???
|
// yScale gives ???
|
||||||
//
|
|
||||||
getCardY(b: Bucket) {
|
getCardY(b: Bucket) {
|
||||||
return this.yScale(b.yLabel) + this.chartTop - this.cardHeight - this.cardVSpacing/2;
|
return this.yScale(b.yLabel) + this.chartTop - this.cardHeight - this.cardVSpacing/2;
|
||||||
}
|
}
|
||||||
@@ -745,11 +753,11 @@ export class StatusmapRenderer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
this.panel = this.ctrl.panel;
|
this.panel = this.ctrl.panel;
|
||||||
this.timeRange = this.ctrl.range;
|
this.timeRange = this.ctrl.range;
|
||||||
this.bucketMatrix = this.ctrl.bucketMatrix;
|
this.bucketMatrix = this.ctrl.bucketMatrix;
|
||||||
|
this.bucketMatrixPager = this.ctrl.bucketMatrixPager;
|
||||||
|
|
||||||
if (!this.bucketMatrix || !this.setElementHeight()) {
|
if (!this.bucketMatrix || !this.setElementHeight()) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
+120
-1
@@ -62,6 +62,7 @@ class BucketMatrix {
|
|||||||
// a flag that indicate that buckets has stub values
|
// a flag that indicate that buckets has stub values
|
||||||
noDatapoints: boolean = false;
|
noDatapoints: boolean = false;
|
||||||
|
|
||||||
|
// An array of row labels
|
||||||
targets: string[] = [];
|
targets: string[] = [];
|
||||||
rangeMs: number = 0;
|
rangeMs: number = 0;
|
||||||
intervalMs: number = 0;
|
intervalMs: number = 0;
|
||||||
@@ -93,4 +94,122 @@ class BucketMatrix {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export {Bucket, BucketMatrix };
|
export var pagerChanged:any = {name:'statusmap-pager-changed'};
|
||||||
|
|
||||||
|
class BucketMatrixPager {
|
||||||
|
bucketMatrix: BucketMatrix;
|
||||||
|
enable: boolean;
|
||||||
|
defaultPageSize: number = -1;
|
||||||
|
pageSize: number = -1;
|
||||||
|
currentPage: number = 0;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
let m = new BucketMatrix();
|
||||||
|
|
||||||
|
this.bucketMatrix = m;
|
||||||
|
}
|
||||||
|
|
||||||
|
// An array of row labels for current page.
|
||||||
|
targets(): string[] {
|
||||||
|
if (!this.enable) {
|
||||||
|
return this.bucketMatrix.targets;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.bucketMatrix.targets.slice(this.pageSize * this.currentPage, this.pageSize * (this.currentPage+1) );
|
||||||
|
}
|
||||||
|
|
||||||
|
buckets(): {[yLabel: string]: Bucket[]} {
|
||||||
|
if (!this.enable) {
|
||||||
|
return this.bucketMatrix.buckets;
|
||||||
|
}
|
||||||
|
|
||||||
|
let buckets: {[yLabel: string]: Bucket[]} = {}
|
||||||
|
let me = this;
|
||||||
|
|
||||||
|
this.targets().map(function (rowLabel) {
|
||||||
|
buckets[rowLabel] = me.bucketMatrix.buckets[rowLabel];
|
||||||
|
})
|
||||||
|
|
||||||
|
return buckets;
|
||||||
|
}
|
||||||
|
|
||||||
|
setEnable(enable: boolean) {
|
||||||
|
this.enable = enable;
|
||||||
|
}
|
||||||
|
|
||||||
|
setCurrent(num: number): void {
|
||||||
|
this.currentPage = num;
|
||||||
|
}
|
||||||
|
|
||||||
|
setDefaultPageSize(num: number): void {
|
||||||
|
this.defaultPageSize = num;
|
||||||
|
}
|
||||||
|
|
||||||
|
setPageSize(num: number): void {
|
||||||
|
this.pageSize = num;
|
||||||
|
}
|
||||||
|
|
||||||
|
pages(): number {
|
||||||
|
return Math.ceil(this.totalRows() / this.pageSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
totalRows(): number {
|
||||||
|
return this.bucketMatrix.targets.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
pageStartRow(): number {
|
||||||
|
if (!this.enable) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return (this.pageSize * this.currentPage) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pageEndRow(): number {
|
||||||
|
if (!this.enable) {
|
||||||
|
return this.totalRows();
|
||||||
|
}
|
||||||
|
|
||||||
|
let last = this.pageSize * (this.currentPage+1);
|
||||||
|
if (last > this.totalRows()) {
|
||||||
|
return this.totalRows();
|
||||||
|
}
|
||||||
|
|
||||||
|
return last;
|
||||||
|
}
|
||||||
|
|
||||||
|
hasNext(): boolean {
|
||||||
|
if (!this.enable) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((this.currentPage+1)*this.pageSize >= this.totalRows()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
// currentPage >= ctrl.bucketMatrix.targets.length/ctrl.pageSizeViewer - 1 || ctrl.numberOfPages == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
hasPrev(): boolean {
|
||||||
|
if (!this.enable) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.currentPage > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
switchToNext() {
|
||||||
|
if (this.hasNext()) {
|
||||||
|
this.currentPage = this.currentPage + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switchToPrev() {
|
||||||
|
if (this.hasPrev()) {
|
||||||
|
this.currentPage = this.currentPage - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export {Bucket, BucketMatrix, BucketMatrixPager };
|
||||||
Reference in New Issue
Block a user