Skip to content

Commit

Permalink
Compatibility with grafana 7 #442 (#444)
Browse files Browse the repository at this point in the history
* fixes to make it work

* todo

* initial ui
  • Loading branch information
rozetko authored Jun 18, 2020
1 parent 322a06f commit 36a34f9
Show file tree
Hide file tree
Showing 9 changed files with 291 additions and 14 deletions.
4 changes: 4 additions & 0 deletions src/panel/graph_panel/controllers/analytic_controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -631,6 +631,10 @@ export class AnalyticController {

get inspectedAnalyticUnit(): AnalyticUnit | null {
for(let analyticUnit of this.analyticUnits) {
// TODO: inspect flag isn't persisted on the server,
// so it resets when closing panel editor in Grafana 7
// (because AnalyticController is re-created)
// P.S. it works in Grafana 5 and 6
if(analyticUnit.inspect) {
return analyticUnit;
}
Expand Down
25 changes: 15 additions & 10 deletions src/panel/graph_panel/graph_ctrl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,9 @@ class GraphCtrl extends MetricsPanelCtrl {
throw new Error('Cannot parse grafana url');
}

this._panelId = `${this.dashboard.uid}/${this.panel.id}`;
// editSourceId is a true panel ID in panel editor mode in Grafana 7.x
const panelId = this.panel.editSourceId || this.panel.id;
this._panelId = `${this.dashboard.uid}/${panelId}`;
this._datasources = {};
this._dataTimerange = {};
}
Expand Down Expand Up @@ -469,7 +471,7 @@ class GraphCtrl extends MetricsPanelCtrl {
}

for(let series of this.seriesList) {
if(series.unit) {
if(series.unit !== undefined && series.yaxis !== undefined) {
this.panel.yaxes[series.yaxis - 1].format = series.unit;
}
}
Expand Down Expand Up @@ -670,25 +672,28 @@ class GraphCtrl extends MetricsPanelCtrl {
return `${this.panelPath}/partials`;
}

get grafanaVersion() {
get grafanaVersion(): string | null {
if(_.has(window, 'grafanaBootData.settings.buildInfo.version')) {
return window.grafanaBootData.settings.buildInfo.version;
}
return null;
}

getTemplatePath(filename: string) {
getTemplatePath(filename: string): string {
const grafanaVersion = this.grafanaVersion;
if(grafanaVersion === null) {
throw new Error('Unknown Grafana version');
}
if(grafanaVersion[0] === '5') {
return `${this.partialsPath}/${filename}_5.x.html`;
switch(grafanaVersion[0]) {
case '5':
return `${this.partialsPath}/${filename}_5.x.html`;
case '6':
return `${this.partialsPath}/${filename}_6.x.html`;
case '7':
return `${this.partialsPath}/${filename}_7.x.html`;
default:
throw new Error(`Unsupported Grafana version: ${grafanaVersion}`);
}
if(grafanaVersion[0] === '6') {
return `${this.partialsPath}/${filename}_6.x.html`;
}
throw new Error(`Unsupported Grafana version: ${grafanaVersion}`);
}

createNew() {
Expand Down
148 changes: 148 additions & 0 deletions src/panel/graph_panel/partials/analytic_unit_7.x.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
<div class="section gf-form-group">
<div class="gf-form">
<label class="gf-form-label query-keyword">
Name
</label>
<input
type="text" class="gf-form-input"
ng-model="analyticUnit.name"
ng-blur="ctrl.onAnalyticUnitChange(analyticUnit)"
>
</div>
<div class="gf-form">
<label class="gf-form-label query-keyword"> Type </label>
<div class="gf-form-select-wrapper">
<select class="gf-form-input"
ng-model="analyticUnit.type"
ng-options="type.value as type.name for type in ctrl.analyticUnitTypes[analyticUnit.detectorType]"
ng-disabled="true"
/>
</div>
</div>
</div>

<div class="section gf-form-group">
<div class="gf-form">
<label class="gf-form-label query-keyword"> Positive Color </label>
<label class="gf-form-label">
<color-picker
color="analyticUnit.labeledColor"
onChange="ctrl.onColorChange.bind(ctrl, analyticUnit.id, false)"
/>
</label>
</div>

<div class="gf-form"
ng-if="analyticUnit.detectorType === 'pattern' || analyticUnit.detectorType === 'anomaly'"
>
<label class="gf-form-label query-keyword"> Negative Color </label>
<label class="gf-form-label">
<color-picker
color="analyticUnit.deletedColor"
onChange="ctrl.onColorChange.bind(ctrl, analyticUnit.id, true)"
/>
</label>
</div>
</div>

<div class="section gf-form-group" ng-if="analyticUnit.detectorType === 'threshold'">
<!-- TODO: move analytic-unit-specific fields rendering to class -->
<div class="gf-form">
<label class="gf-form-label query-keyword"> Condition </label>
<select class="gf-form-input"
ng-class="{
'width-5': analyticUnit.condition !== 'NO_DATA',
'width-9': analyticUnit.condition === 'NO_DATA'
}"
ng-model="analyticUnit.condition"
ng-options="type for type in ctrl.analyticsController.conditions"
ng-change="ctrl.onAnalyticUnitChange(analyticUnit)"
/>
<input class="gf-form-input"
ng-if="analyticUnit.condition !== 'NO_DATA'"
type="number"
ng-model="analyticUnit.value"
ng-blur="ctrl.onAnalyticUnitChange(analyticUnit)"
/>
</div>
</div>

<div class="section gf-form-group" ng-if="analyticUnit.detectorType === 'anomaly'">
<div class="gf-form">
<label class="gf-form-label query-keyword">
Alpha
&nbsp;
<i class="fa fa-info" bs-tooltip="'Takes value from 0 to 1. Less Alpha means smoother bounds'"></i>
</label>
<input class="gf-form-input"
min="0"
max="1"
type="number"
ng-model="analyticUnit.alpha"
ng-blur="ctrl.onAnalyticUnitChange(analyticUnit)"
/>
</div>

<div class="gf-form">
<label class="gf-form-label query-keyword">
Сonfidence
&nbsp;
<i class="fa fa-info" bs-tooltip="'Bounds for the metric'"></i>
</label>
<input class="gf-form-input"
min="0"
type="number"
ng-model="analyticUnit.confidence"
ng-blur="ctrl.onAnalyticUnitChange(analyticUnit)"
/>
</div>

</div>

<div class="section gf-form-group" ng-if="analyticUnit.detectorType === 'anomaly'">
<div class="gf-form">
<gf-form-switch
class="gf-form"
label="Seasonality"
label-class="query-keyword"
on-change="ctrl.onAnalyticUnitChange(analyticUnit)"
checked="analyticUnit.hasSeasonality"
/>
</div>

<div class="gf-form" ng-if="analyticUnit.hasSeasonality">
<label class="gf-form-label query-keyword"> Seasonality Period </label>
<input
type="number" class="gf-form-input"
ng-init="seasonalityValue = analyticUnit.seasonalityPeriod.value"
ng-model="seasonalityValue"
ng-blur="ctrl.onSeasonalityChange(analyticUnit.id, seasonalityValue)"
min="0"
>
</div>

<div class="gf-form" ng-if="analyticUnit.hasSeasonality">
<div class="gf-form-select-wrapper">
<!-- TODO: move periods from ng-options -->
<select class="gf-form-input"
ng-model="analyticUnit.seasonalityPeriod.unit"
ng-change="ctrl.onSeasonalityChange(analyticUnit.id)"
ng-options="type for type in ['seconds', 'minutes', 'hours', 'days', 'years']"
/>
</div>
</div>

</div>

<div class="section gf-form-group" ng-if="analyticUnit.detectorType === 'anomaly'">
<div class="gf-form">
<label class="gf-form-label query-keyword"> Enabled bounds </label>
<div class="gf-form-select-wrapper">
<select class="gf-form-input"
ng-model="analyticUnit.enableBounds"
ng-change="ctrl.onAnalyticUnitChange(analyticUnit)"
ng-options="bound.value as bound.name for bound in ctrl.boundTypes"
/>
</div>
</div>
</div>
2 changes: 1 addition & 1 deletion src/panel/graph_panel/partials/analytic_units_5.x.html
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
</div>

<div class="gf-form-query-content" ng-if="!analyticUnit.collapsed">
<ng-include src="ctrl.partialsPath + '/analytic_unit.html'"></ng-include>
<ng-include src="ctrl.partialsPath + '/analytic_unit_5.x_6.x.html'"></ng-include>
</div>

<div class="gf-form">
Expand Down
2 changes: 1 addition & 1 deletion src/panel/graph_panel/partials/analytic_units_6.x.html
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,6 @@
class="query-editor-row__body gf-form-query"
ng-class="analyticUnit.collapsed && 'query-editor-row__body--collapsed'"
>
<ng-include src="ctrl.partialsPath + '/analytic_unit.html'"></ng-include>
<ng-include src="ctrl.partialsPath + '/analytic_unit_5.x_6.x.html'"></ng-include>
</div>
</div>
106 changes: 106 additions & 0 deletions src/panel/graph_panel/partials/analytic_units_7.x.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
<div class="query-editor-row" ng-repeat="analyticUnit in ctrl.analyticsController.analyticUnits">
<div class="query-editor-row__header">
<div class="query-editor-row__ref-id" ng-click="ctrl.onToggleCollapsed(analyticUnit.id)">
<i class="fa fa-fw fa-caret-down" ng-hide="analyticUnit.collapsed"></i>
<i class="fa fa-fw fa-caret-right" ng-show="analyticUnit.collapsed"></i>
<span>{{analyticUnit.name}}</span>
<em class="query-editor-row__context-info">({{analyticUnit.id}})</em>
</div>
<div
class="query-editor-row__collapsed-text"
style="line-height: 0px;"
>
&nbsp;
<i ng-if="analyticUnit.status === 'READY'"
class="fa fa-fw fa-check-circle"
bs-tooltip="'Ready'"
></i>
<i ng-if="analyticUnit.status === 'SUCCESS'"
class="fa fa-fw fa-check"
bs-tooltip="'Learning succeeded'"
></i>
<i ng-if="analyticUnit.status === 'LEARNING'"
class="fa fa-fw fa-leanpub"
bs-tooltip="'Learning'"
></i>
<i ng-if="analyticUnit.status === 'DETECTION'"
class="fa fa-fw fa-search"
bs-tooltip="'Detection'"
></i>
<i ng-if="analyticUnit.status === 'PENDING'"
class="fa fa-fw fa-list-ul"
bs-tooltip="'Pending'"
></i>
<i ng-if="analyticUnit.status === 'FAILED'"
class="fa fa-fw fa-exclamation-circle"
bs-tooltip="'Error: ' + analyticUnit.error"
></i>
</div>
</div>

<div
class="gf-form-query"
ng-class="analyticUnit.collapsed && 'query-editor-row__body--collapsed'"
>
<div class="query-editor-row__header">
<button class="query-editor-row__action" ng-click=ctrl.onToggleVisibility(analyticUnit.id)>
<a ng-if="analyticUnit.visible" bs-tooltip="'Hide. It`s visible now.'" class="pointer">
<i class="fa fa-fw fa-eye"></i>
</a>
<a ng-if="!analyticUnit.visible" bs-tooltip="'Show. It`s hidden now.'" class="pointer">
<i class="fa fa-fw fa-eye-slash"></i>
</a>
</button>

<button class="query-editor-row__action" ng-click="ctrl.onToggleInspect(analyticUnit.id)" bs-tooltip="'Inspect Mode'">
<a class="pointer">
<!--use ctrl.pluginPath-->
<img src="public/plugins/corpglory-hastic-app/img/inspect_enabled.svg" class="fa fa-fw"
ng-if="analyticUnit.inspect"></img>
<img src="public/plugins/corpglory-hastic-app/img/inspect_disabled.svg" class="fa fa-fw"
ng-if="!analyticUnit.inspect"></img>
</a>
</button>

<button class="query-editor-row__action" ng-click="ctrl.onRemove(analyticUnit.id)" bs-tooltip="'Delete'">
<a class="pointer">
<i class="fa fa-fw fa-trash"></i>
</a>
</button>

<button class="query-editor-row__action" ng-if="
(analyticUnit.detectorType === 'pattern' ||
(analyticUnit.detectorType === 'anomaly' && analyticUnit.hasSeasonality)) &&
!analyticUnit.selected" bs-tooltip="'Label'">
<a class="pointer" ng-style="analyticUnit.status === 'LEARNING' && { 'cursor': 'not-allowed' }"
ng-click="ctrl.onToggleLabelingMode(analyticUnit.id)" ng-disabled="analyticUnit.status === 'LEARNING'">
<i class="fa fa-fw fa-bar-chart" ng-if="!analyticUnit.saving"></i>
<i class="fa fa-fw fa-spinner fa-spin" ng-if="analyticUnit.saving"></i>
Label
</a>
</button>

<select class="gf-form-input width-11" ng-if="analyticUnit.selected && !analyticUnit.saving"
ng-model="ctrl.analyticsController.labelingMode"
ng-options="type.value as type.name for type in analyticUnit.labelingModes"
ng-disabled="analyticUnit.status === 'LEARNING'" />

<button class="query-editor-row__action" ng-if="analyticUnit.selected && !analyticUnit.saving"
bs-tooltip="'Cancel labeling'">
<a class="pointer" ng-click="ctrl.onCancelLabeling(analyticUnit.id)">
<i class="fa fa-fw fa-ban"></i>
</a>
</button>

<button class="query-editor-row__action" ng-click="ctrl.runDetectInCurrentRange(analyticUnit)"
ng-disabled="analyticUnit.saving" bs-tooltip="'Learn & Detect'">
<a class="pointer">
Apply
</a>
</button>
</div>
<div class="query-editor-row__body">
<ng-include src="ctrl.partialsPath + '/analytic_unit_7.x.html'"></ng-include>
</div>
</div>
</div>
14 changes: 14 additions & 0 deletions src/panel/graph_panel/partials/new_analytic_unit_7.x.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<div class="query-editor-row">
<div class="query-editor-row__header">
<div class="query-editor-row__ref-id width-25" style="cursor: default;">
<span>New analytic unit</span>
</div>

<div class="query-editor-row__collapsed-text">
</div>
</div>

<div class="query-editor-row__body gf-form-query">
<ng-include src="ctrl.partialsPath + '/new_analytic_unit.html'"></ng-include>
</div>
</div>
4 changes: 2 additions & 2 deletions src/panel/graph_panel/partials/tab_analytics.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<div class="gf-form-group">
<div class="section gf-form-group">
<div class="gf-form">
<label class="gf-form-label">Select Hastic datasource</label>
<select class="gf-form-input width-15"
<select class="gf-form-input"
ng-model="ctrl.panel.hasticDatasource"
ng-options="ds.id as ds.name for ds in ctrl.hasticDatasources"
ng-change="ctrl.onHasticDatasourceChange()"
Expand Down

0 comments on commit 36a34f9

Please sign in to comment.