|
|
@ -1,7 +1,7 @@ |
|
|
|
<div class="gf-form-group"> |
|
|
|
<div class="gf-form-group"> |
|
|
|
<div class="gf-form"> |
|
|
|
<div class="gf-form"> |
|
|
|
<label class="gf-form-label">Select Hastic datasource</label> |
|
|
|
<label class="gf-form-label">Select Hastic datasource</label> |
|
|
|
<select class="gf-form-input max-width-15" |
|
|
|
<select class="gf-form-input width-15" |
|
|
|
ng-model="ctrl.panel.hasticDatasource" |
|
|
|
ng-model="ctrl.panel.hasticDatasource" |
|
|
|
ng-options="ds.id as ds.name for ds in ctrl.hasticDatasources" |
|
|
|
ng-options="ds.id as ds.name for ds in ctrl.hasticDatasources" |
|
|
|
ng-change="ctrl.onHasticDatasourceChange()" |
|
|
|
ng-change="ctrl.onHasticDatasourceChange()" |
|
|
@ -12,7 +12,7 @@ |
|
|
|
<div class="gf-form"> |
|
|
|
<div class="gf-form"> |
|
|
|
<div class="gf-form-button-row" ng-if="ctrl.analyticsController.serverStatus === false"> |
|
|
|
<div class="gf-form-button-row" ng-if="ctrl.analyticsController.serverStatus === false"> |
|
|
|
<h5>Hastic server at "{{ctrl.hasticDatasource.url}}" is not available</h5> |
|
|
|
<h5>Hastic server at "{{ctrl.hasticDatasource.url}}" is not available</h5> |
|
|
|
<button class="btn btn-inverse" ng-click="ctrl.runDatasourceConnectivityCheck()"> |
|
|
|
<button class="btn btn-inverse" ng-click="ctrl.onHasticDatasourceChange()"> |
|
|
|
<i class="fa fa-plug"></i> |
|
|
|
<i class="fa fa-plug"></i> |
|
|
|
Reconnect to Hastic server |
|
|
|
Reconnect to Hastic server |
|
|
|
</button> |
|
|
|
</button> |
|
|
@ -20,213 +20,299 @@ |
|
|
|
|
|
|
|
|
|
|
|
<div ng-if="ctrl.analyticsController.serverStatus === true && !ctrl.analyticsController.loading"> |
|
|
|
<div ng-if="ctrl.analyticsController.serverStatus === true && !ctrl.analyticsController.loading"> |
|
|
|
<h5> Analytic Units </h5> |
|
|
|
<h5> Analytic Units </h5> |
|
|
|
<div class="editor-row"> |
|
|
|
<div ng-repeat="analyticUnit in ctrl.analyticsController.analyticUnits"> |
|
|
|
<div class="gf-form" ng-repeat="analyticUnit in ctrl.analyticsController.analyticUnits"> |
|
|
|
<div class="gf-form-inline"> |
|
|
|
|
|
|
|
<div class="gf-form"> |
|
|
|
<label class="gf-form-label width-5"> |
|
|
|
<label class="gf-form-label width-5"> |
|
|
|
<i class="fa fa-info" bs-tooltip="'Analytic unit id: ' + analyticUnit.id"></i> |
|
|
|
<i class="fa fa-info" bs-tooltip="'Analytic unit id: ' + analyticUnit.id"></i> |
|
|
|
Name |
|
|
|
Name |
|
|
|
</label> |
|
|
|
</label> |
|
|
|
<input |
|
|
|
<input |
|
|
|
type="text" class="gf-form-input max-width-15" |
|
|
|
type="text" class="gf-form-input width-15" |
|
|
|
ng-model="analyticUnit.name" |
|
|
|
ng-model="analyticUnit.name" |
|
|
|
ng-blur="ctrl.onAnalyticUnitChange(analyticUnit)" |
|
|
|
ng-blur="ctrl.onAnalyticUnitChange(analyticUnit)" |
|
|
|
> |
|
|
|
> |
|
|
|
|
|
|
|
|
|
|
|
<label class="gf-form-label width-4"> Type </label> |
|
|
|
|
|
|
|
<div class="gf-form-select-wrapper"> |
|
|
|
|
|
|
|
<select class="gf-form-input width-10" |
|
|
|
|
|
|
|
ng-model="analyticUnit.type" |
|
|
|
|
|
|
|
ng-options="type.value as type.name for type in ctrl.analyticUnitTypes[analyticUnit.detectorType]" |
|
|
|
|
|
|
|
ng-disabled="true" |
|
|
|
|
|
|
|
/> |
|
|
|
|
|
|
|
</div> |
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
|
|
<!-- |
|
|
|
<div class="gf-form"> |
|
|
|
<label class="gf-form-label width-6"> Confidence </label> |
|
|
|
<label class="gf-form-label width-5"> Type </label> |
|
|
|
<input |
|
|
|
<div class="gf-form-select-wrapper"> |
|
|
|
type="number" class="gf-form-input width-5 ng-valid ng-scope ng-empty ng-dirty ng-valid-number ng-touched" |
|
|
|
<select class="gf-form-input width-9" |
|
|
|
placeholder="auto" bs-tooltip="'Override automatic decimal precision for legend and tooltips'" |
|
|
|
ng-model="analyticUnit.type" |
|
|
|
data-placement="right" ng-model="ctrl.panel.decimals" ng-change="ctrl.render()" ng-model-onblur="" data-original-title="" title="" |
|
|
|
ng-options="type.value as type.name for type in ctrl.analyticUnitTypes[analyticUnit.detectorType]" |
|
|
|
/> |
|
|
|
ng-disabled="true" |
|
|
|
--> |
|
|
|
/> |
|
|
|
|
|
|
|
</div> |
|
|
|
|
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
|
|
<label class="gf-form-label width-8"> Positive Color </label> |
|
|
|
<div class="gf-form"> |
|
|
|
<span class="gf-form-label"> |
|
|
|
<label class="gf-form-label width-8"> Positive Color </label> |
|
|
|
<color-picker |
|
|
|
<span class="gf-form-label"> |
|
|
|
color="analyticUnit.labeledColor" |
|
|
|
<color-picker |
|
|
|
onChange="ctrl.onColorChange.bind(ctrl, analyticUnit.id, false)" |
|
|
|
color="analyticUnit.labeledColor" |
|
|
|
/> |
|
|
|
onChange="ctrl.onColorChange.bind(ctrl, analyticUnit.id, false)" |
|
|
|
</span> |
|
|
|
/> |
|
|
|
|
|
|
|
</span> |
|
|
|
|
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
|
|
<!-- Hack to avoid Grafana's .gf-form-label + .gf-form-label css. Fix for https://github.com/hastic/hastic-grafana-app/issues/192 --> |
|
|
|
<div class="gf-form" |
|
|
|
<div ng-if="analyticUnit.detectorType === 'pattern'"></div> |
|
|
|
ng-if="analyticUnit.detectorType === 'pattern' || analyticUnit.detectorType === 'anomaly'" |
|
|
|
|
|
|
|
> |
|
|
|
|
|
|
|
<label class="gf-form-label width-8"> Negative Color </label> |
|
|
|
|
|
|
|
<span class="gf-form-label"> |
|
|
|
|
|
|
|
<color-picker |
|
|
|
|
|
|
|
color="analyticUnit.deletedColor" |
|
|
|
|
|
|
|
onChange="ctrl.onColorChange.bind(ctrl, analyticUnit.id, true)" |
|
|
|
|
|
|
|
/> |
|
|
|
|
|
|
|
</span> |
|
|
|
|
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
|
|
<label ng-if="analyticUnit.detectorType === 'pattern'" class="gf-form-label width-8"> Negative Color </label> |
|
|
|
<div class="gf-form" ng-if="analyticUnit.visible"> |
|
|
|
<span ng-if="analyticUnit.detectorType === 'pattern'" class="gf-form-label"> |
|
|
|
<!-- TODO: Remove hack with "margin-bottom: 0" --> |
|
|
|
<color-picker |
|
|
|
<gf-form-switch |
|
|
|
color="analyticUnit.deletedColor" |
|
|
|
class="gf-form" |
|
|
|
onChange="ctrl.onColorChange.bind(ctrl, analyticUnit.id, true)" |
|
|
|
style="margin-bottom: 0" |
|
|
|
|
|
|
|
label="Inspect" |
|
|
|
|
|
|
|
label-class="width-5" |
|
|
|
|
|
|
|
on-change="ctrl.onToggleInspect(analyticUnit.id)" |
|
|
|
|
|
|
|
checked="analyticUnit.inspect" |
|
|
|
/> |
|
|
|
/> |
|
|
|
</span> |
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
|
|
<!-- TODO: move analytic-unit-specific fields rendering to class --> |
|
|
|
<div |
|
|
|
<select class="gf-form-input width-9" |
|
|
|
class="gf-form" |
|
|
|
ng-if="analyticUnit.detectorType === 'threshold'" |
|
|
|
|
|
|
|
ng-model="analyticUnit.condition" |
|
|
|
|
|
|
|
ng-options="type for type in ctrl.analyticsController.conditions" |
|
|
|
|
|
|
|
ng-change="ctrl.onAnalyticUnitChange(analyticUnit)" |
|
|
|
|
|
|
|
/> |
|
|
|
|
|
|
|
<input class="gf-form-input width-5" |
|
|
|
|
|
|
|
ng-if=" |
|
|
|
ng-if=" |
|
|
|
analyticUnit.detectorType === 'threshold' && |
|
|
|
analyticUnit.detectorType === 'pattern' || |
|
|
|
analyticUnit.condition !== 'NO_DATA' |
|
|
|
(analyticUnit.detectorType === 'anomaly' && analyticUnit.hasSeasonality) |
|
|
|
" |
|
|
|
" |
|
|
|
type="number" |
|
|
|
> |
|
|
|
ng-model="analyticUnit.value" |
|
|
|
<label |
|
|
|
ng-blur="ctrl.onAnalyticUnitChange(analyticUnit)" |
|
|
|
class="gf-form-label pointer" |
|
|
|
/> |
|
|
|
ng-if="!analyticUnit.selected" |
|
|
|
|
|
|
|
ng-style="analyticUnit.status === 'LEARNING' && { 'cursor': 'not-allowed' }" |
|
|
|
|
|
|
|
ng-click="ctrl.onToggleLabelingMode(analyticUnit.id)" |
|
|
|
|
|
|
|
ng-disabled="analyticUnit.status === 'LEARNING'" |
|
|
|
|
|
|
|
> |
|
|
|
|
|
|
|
<i class="fa fa-bar-chart" ng-if="!analyticUnit.saving"></i> |
|
|
|
|
|
|
|
<i class="fa fa-spinner fa-spin" ng-if="analyticUnit.saving"></i> |
|
|
|
|
|
|
|
Label |
|
|
|
|
|
|
|
</label> |
|
|
|
|
|
|
|
<select class="gf-form-input width-12" |
|
|
|
|
|
|
|
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'" |
|
|
|
|
|
|
|
/> |
|
|
|
|
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
|
|
<label class="gf-form-label width-6" ng-if="analyticUnit.detectorType === 'anomaly'"> Alpha </label> |
|
|
|
<div class="gf-form" ng-if="!analyticUnit.selected"> |
|
|
|
<input class="gf-form-input width-5" |
|
|
|
<label class="gf-form-label"> |
|
|
|
ng-if="analyticUnit.detectorType === 'anomaly'" |
|
|
|
<a |
|
|
|
min="0" |
|
|
|
ng-if="analyticUnit.visible" |
|
|
|
max="1" |
|
|
|
bs-tooltip="'Hide. It`s visible now.'" |
|
|
|
type="number" |
|
|
|
ng-click="ctrl.onToggleVisibility(analyticUnit.id)" |
|
|
|
ng-model="analyticUnit.alpha" |
|
|
|
class="pointer" |
|
|
|
ng-blur="ctrl.onAnalyticUnitChange(analyticUnit)" |
|
|
|
> |
|
|
|
/> |
|
|
|
<i class="fa fa-eye"></i> |
|
|
|
|
|
|
|
</a> |
|
|
|
|
|
|
|
|
|
|
|
<label class="gf-form-label width-6" ng-if="analyticUnit.detectorType === 'anomaly'"> Confidence </label> |
|
|
|
<a |
|
|
|
<input class="gf-form-input width-5" |
|
|
|
ng-if="!analyticUnit.visible" |
|
|
|
ng-if="analyticUnit.detectorType === 'anomaly'" |
|
|
|
bs-tooltip="'Show. It`s hidden now.'" |
|
|
|
min="0" |
|
|
|
ng-click="ctrl.onToggleVisibility(analyticUnit.id)" |
|
|
|
type="number" |
|
|
|
class="pointer" |
|
|
|
ng-model="analyticUnit.confidence" |
|
|
|
> |
|
|
|
ng-blur="ctrl.onAnalyticUnitChange(analyticUnit)" |
|
|
|
<i class="fa fa-eye-slash"></i> |
|
|
|
/> |
|
|
|
</a> |
|
|
|
|
|
|
|
</label> |
|
|
|
|
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
|
|
<label class="gf-form-label" ng-if="analyticUnit.status === 'READY' && analyticUnit.visible"> |
|
|
|
<div class="gf-form" ng-if="!analyticUnit.selected"> |
|
|
|
Inspect |
|
|
|
<a |
|
|
|
</label> |
|
|
|
class="btn btn-danger" |
|
|
|
|
|
|
|
ng-click="ctrl.onRemove(analyticUnit.id)" |
|
|
|
|
|
|
|
> |
|
|
|
|
|
|
|
<i class="fa fa-trash"></i> |
|
|
|
|
|
|
|
</a> |
|
|
|
|
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
|
|
<gf-form-switch ng-if="analyticUnit.status === 'READY' && analyticUnit.visible" |
|
|
|
<div class="gf-form" ng-if="analyticUnit.selected"> |
|
|
|
on-change="ctrl.onToggleInspect(analyticUnit.id)" |
|
|
|
<div class="gf-form-label"> |
|
|
|
checked="analyticUnit.inspect" |
|
|
|
<a |
|
|
|
/> |
|
|
|
class="pointer" |
|
|
|
|
|
|
|
ng-click="ctrl.onCancelLabeling(analyticUnit.id)" |
|
|
|
|
|
|
|
> |
|
|
|
|
|
|
|
Cancel |
|
|
|
|
|
|
|
</a> |
|
|
|
|
|
|
|
</div> |
|
|
|
|
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
|
|
<label class="gf-form-label" ng-if="analyticUnit.visible"> |
|
|
|
<div class="gf-form"> |
|
|
|
HSR |
|
|
|
<label> |
|
|
|
</label> |
|
|
|
<i ng-if="analyticUnit.status === 'READY'" class="grafana-tip fa fa-check-circle ng-scope" bs-tooltip="'Ready'"></i> |
|
|
|
|
|
|
|
<i ng-if="analyticUnit.status === 'SUCCESS'" class="grafana-tip fa fa-check ng-scope" bs-tooltip="'Learning succeeded'"></i> |
|
|
|
|
|
|
|
<i ng-if="analyticUnit.status === 'LEARNING'" class="grafana-tip fa fa-leanpub ng-scope" bs-tooltip="'Learning'"></i> |
|
|
|
|
|
|
|
<i ng-if="analyticUnit.status === 'DETECTION'" class="grafana-tip fa fa-search ng-scope" bs-tooltip="'Detection'"></i> |
|
|
|
|
|
|
|
<i ng-if="analyticUnit.status === 'PENDING'" class="grafana-tip fa fa-list-ul ng-scope" bs-tooltip="'Pending'"></i> |
|
|
|
|
|
|
|
<i ng-if="analyticUnit.status === 'FAILED'" class="grafana-tip fa fa-exclamation-circle ng-scope" bs-tooltip="'Error: ' + analyticUnit.error"></i> |
|
|
|
|
|
|
|
</label> |
|
|
|
|
|
|
|
</div> |
|
|
|
|
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
|
|
<gf-form-switch ng-if="analyticUnit.visible" |
|
|
|
<div class="gf-form-inline"> |
|
|
|
on-change="ctrl.onToggleHSR(analyticUnit.id)" |
|
|
|
<div class="gf-form width-20"/> |
|
|
|
checked="analyticUnit.showHSR" |
|
|
|
<!-- TODO: move analytic-unit-specific fields rendering to class --> |
|
|
|
/> |
|
|
|
<div class="gf-form" ng-if="analyticUnit.detectorType === 'threshold'"> |
|
|
|
|
|
|
|
<label class="gf-form-label width-5"> 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 width-4" |
|
|
|
|
|
|
|
ng-if="analyticUnit.condition !== 'NO_DATA'" |
|
|
|
|
|
|
|
type="number" |
|
|
|
|
|
|
|
ng-model="analyticUnit.value" |
|
|
|
|
|
|
|
ng-blur="ctrl.onAnalyticUnitChange(analyticUnit)" |
|
|
|
|
|
|
|
/> |
|
|
|
|
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
|
|
<label class="gf-form-label" ng-hide="analyticUnit.selected"> |
|
|
|
<div class="gf-form" ng-if="analyticUnit.detectorType === 'anomaly'"> |
|
|
|
<a |
|
|
|
<label class="gf-form-label width-5"> Alpha </label> |
|
|
|
ng-if="analyticUnit.visible" |
|
|
|
<input class="gf-form-input width-9" |
|
|
|
bs-tooltip="'Hide. It`s visible now.'" |
|
|
|
min="0" |
|
|
|
ng-click="ctrl.onToggleVisibility(analyticUnit.id)" |
|
|
|
max="1" |
|
|
|
class="pointer" |
|
|
|
type="number" |
|
|
|
> |
|
|
|
ng-model="analyticUnit.alpha" |
|
|
|
<i class="fa fa-eye"></i> |
|
|
|
ng-blur="ctrl.onAnalyticUnitChange(analyticUnit)" |
|
|
|
</a> |
|
|
|
/> |
|
|
|
|
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
|
|
<a |
|
|
|
<div class="gf-form" ng-if="analyticUnit.detectorType === 'anomaly'"> |
|
|
|
ng-if="!analyticUnit.visible" |
|
|
|
<label class="gf-form-label width-6"> Confidence </label> |
|
|
|
bs-tooltip="'Show. It`s hidden now.'" |
|
|
|
<input class="gf-form-input width-5" |
|
|
|
ng-click="ctrl.onToggleVisibility(analyticUnit.id)" |
|
|
|
min="0" |
|
|
|
class="pointer" |
|
|
|
type="number" |
|
|
|
> |
|
|
|
ng-model="analyticUnit.confidence" |
|
|
|
<i class="fa fa-eye-slash"></i> |
|
|
|
ng-blur="ctrl.onAnalyticUnitChange(analyticUnit)" |
|
|
|
</a> |
|
|
|
/> |
|
|
|
</label> |
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
|
|
<label class="gf-form-label" |
|
|
|
<div class="gf-form" ng-if="analyticUnit.detectorType === 'anomaly'"> |
|
|
|
ng-if="analyticUnit.detectorType === 'threshold' || analyticUnit.detectorType === 'anomaly'" |
|
|
|
<!-- TODO: Remove hack with "margin-bottom: 0" --> |
|
|
|
|
|
|
|
<gf-form-switch |
|
|
|
|
|
|
|
class="gf-form" |
|
|
|
|
|
|
|
style="margin-bottom: 0" |
|
|
|
|
|
|
|
label="Seasonality" |
|
|
|
|
|
|
|
label-class="width-7" |
|
|
|
|
|
|
|
on-change="ctrl.onAnalyticUnitChange(analyticUnit)" |
|
|
|
|
|
|
|
checked="analyticUnit.hasSeasonality" |
|
|
|
|
|
|
|
/> |
|
|
|
|
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<div |
|
|
|
|
|
|
|
class="gf-form" |
|
|
|
|
|
|
|
ng-if="analyticUnit.detectorType === 'anomaly' && analyticUnit.hasSeasonality" |
|
|
|
> |
|
|
|
> |
|
|
|
<a class="pointer" ng-click="ctrl.runDetect(analyticUnit.id)"> |
|
|
|
<label class="gf-form-label width-9"> Seasonality Period </label> |
|
|
|
<i class="fa fa-spinner fa-spin" ng-if="analyticUnit.saving"></i> |
|
|
|
<input |
|
|
|
<b ng-if="!analyticUnit.saving"> Detect </b> |
|
|
|
type="number" class="gf-form-input width-5" |
|
|
|
<b ng-if="analyticUnit.saving" ng-disabled="true"> saving... </b> |
|
|
|
ng-init="seasonalityValue = analyticUnit.seasonalityPeriod.value" |
|
|
|
</a> |
|
|
|
ng-model="seasonalityValue" |
|
|
|
</label> |
|
|
|
ng-blur="ctrl.onSeasonalityChange(analyticUnit.id, seasonalityValue)" |
|
|
|
|
|
|
|
min="0" |
|
|
|
|
|
|
|
> |
|
|
|
|
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
|
|
<label |
|
|
|
<div class="gf-form" |
|
|
|
class="gf-form-label" |
|
|
|
ng-if=" |
|
|
|
ng-if="analyticUnit.detectorType === 'pattern'" |
|
|
|
analyticUnit.detectorType === 'anomaly' && |
|
|
|
ng-style="analyticUnit.status === 'LEARNING' && { 'cursor': 'not-allowed' }" |
|
|
|
analyticUnit.hasSeasonality |
|
|
|
|
|
|
|
" |
|
|
|
> |
|
|
|
> |
|
|
|
<a class="pointer" tabindex="1" |
|
|
|
<div class="gf-form-select-wrapper"> |
|
|
|
ng-click="ctrl.onToggleLabelingMode(analyticUnit.id)" |
|
|
|
<!-- TODO: move periods from ng-options --> |
|
|
|
ng-disabled="analyticUnit.status === 'LEARNING'" |
|
|
|
<select class="gf-form-input width-8" |
|
|
|
|
|
|
|
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="gf-form-inline"> |
|
|
|
|
|
|
|
<div class="gf-form width-20"/> |
|
|
|
|
|
|
|
<div class="gf-form"> |
|
|
|
|
|
|
|
<button class="btn btn-secondary" |
|
|
|
|
|
|
|
ng-click="ctrl.onAnalyticUnitSave(analyticUnit)" |
|
|
|
|
|
|
|
ng-disabled="!analyticUnit.changed" |
|
|
|
> |
|
|
|
> |
|
|
|
<i class="fa fa-bar-chart" ng-if="!analyticUnit.saving"></i> |
|
|
|
|
|
|
|
<i class="fa fa-spinner fa-spin" ng-if="analyticUnit.saving"></i> |
|
|
|
<i class="fa fa-spinner fa-spin" ng-if="analyticUnit.saving"></i> |
|
|
|
|
|
|
|
<b ng-if="!analyticUnit.saving"> Save </b> |
|
|
|
<b ng-if="analyticUnit.saving" ng-disabled="true"> saving... </b> |
|
|
|
<b ng-if="analyticUnit.saving" ng-disabled="true"> saving... </b> |
|
|
|
</a> |
|
|
|
</button> |
|
|
|
</label> |
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
|
|
<select class="gf-form-input width-12" |
|
|
|
|
|
|
|
ng-model="ctrl.analyticsController.labelingMode" |
|
|
|
|
|
|
|
ng-options="type.value as type.name for type in [ |
|
|
|
|
|
|
|
{ name:'Label Positive', value: 'LABELING' }, |
|
|
|
|
|
|
|
{ name:'Label Negative', value: 'DELETING' }, |
|
|
|
|
|
|
|
{ name:'Unlabel', value: 'UNLABELING' } |
|
|
|
|
|
|
|
]" |
|
|
|
|
|
|
|
ng-if="analyticUnit.selected && !analyticUnit.saving" |
|
|
|
|
|
|
|
ng-disabled="analyticUnit.status === 'LEARNING'" |
|
|
|
|
|
|
|
/> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<label class="gf-form-label"> |
|
|
|
<!-- TODO: Leave one Detect button instead of 2 --> |
|
|
|
<a |
|
|
|
<div class="gf-form" |
|
|
|
ng-if="!analyticUnit.selected" |
|
|
|
ng-if=" |
|
|
|
ng-click="ctrl.onRemove(analyticUnit.id)" |
|
|
|
analyticUnit.detectorType === 'pattern' || |
|
|
|
class="pointer" |
|
|
|
(analyticUnit.detectorType === 'anomaly' && analyticUnit.hasSeasonality) |
|
|
|
|
|
|
|
" |
|
|
|
|
|
|
|
> |
|
|
|
|
|
|
|
<button class="btn btn-secondary" |
|
|
|
|
|
|
|
ng-click="ctrl.onToggleLabelingMode(analyticUnit.id)" |
|
|
|
|
|
|
|
ng-disabled="analyticUnit.status === 'LEARNING' || analyticUnit.saving || analyticUnit.changed || !analyticUnit.selected" |
|
|
|
> |
|
|
|
> |
|
|
|
<i class="fa fa-trash"></i> |
|
|
|
<b> Detect </b> |
|
|
|
</a> |
|
|
|
</button> |
|
|
|
|
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
|
|
<a |
|
|
|
<div class="gf-form" |
|
|
|
ng-if="analyticUnit.selected" |
|
|
|
ng-if=" |
|
|
|
ng-click="ctrl.onCancelLabeling(analyticUnit.id)" |
|
|
|
analyticUnit.detectorType === 'threshold' || |
|
|
|
class="pointer" |
|
|
|
(analyticUnit.detectorType === 'anomaly' && !analyticUnit.hasSeasonality) |
|
|
|
|
|
|
|
" |
|
|
|
|
|
|
|
> |
|
|
|
|
|
|
|
<button class="btn btn-secondary" |
|
|
|
|
|
|
|
ng-click="ctrl.runDetectInCurrentRange(analyticUnit.id)" |
|
|
|
|
|
|
|
ng-disabled="analyticUnit.status === 'LEARNING' || analyticUnit.saving || analyticUnit.changed" |
|
|
|
> |
|
|
|
> |
|
|
|
<i class="fa fa-ban"></i> |
|
|
|
<b> Detect </b> |
|
|
|
</a> |
|
|
|
</button> |
|
|
|
</label> |
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
|
|
<label> |
|
|
|
|
|
|
|
<i ng-if="analyticUnit.status === 'READY'" class="grafana-tip fa fa-check-circle ng-scope" bs-tooltip="'Ready'"></i> |
|
|
|
|
|
|
|
<i ng-if="analyticUnit.status === 'LEARNING'" class="grafana-tip fa fa-leanpub ng-scope" bs-tooltip="'Learning'"></i> |
|
|
|
|
|
|
|
<i ng-if="analyticUnit.status === 'PENDING'" class="grafana-tip fa fa-list-ul ng-scope" bs-tooltip="'Pending'"></i> |
|
|
|
|
|
|
|
<i ng-if="analyticUnit.status === 'FAILED'" class="grafana-tip fa fa-exclamation-circle ng-scope" bs-tooltip="'Error: ' + analyticUnit.error"></i> |
|
|
|
|
|
|
|
</label> |
|
|
|
|
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
|
|
<div class="editor-row" ng-if="ctrl.analyticsController.creatingNew"> |
|
|
|
<div class="gf-form-inline" ng-if="ctrl.analyticsController.creatingNew"> |
|
|
|
<div class="gf-form"> |
|
|
|
<div class="gf-form"> |
|
|
|
<label class="gf-form-label width-4"> Name </label> |
|
|
|
<label class="gf-form-label width-5"> Name </label> |
|
|
|
<input |
|
|
|
<input |
|
|
|
type="text" class="gf-form-input max-width-15" |
|
|
|
type="text" class="gf-form-input width-15" |
|
|
|
ng-model="ctrl.analyticsController.newAnalyticUnit.name" |
|
|
|
ng-model="ctrl.analyticsController.newAnalyticUnit.name" |
|
|
|
> |
|
|
|
> |
|
|
|
|
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<div class="gf-form"> |
|
|
|
<label class="gf-form-label width-8"> Detector Type </label> |
|
|
|
<label class="gf-form-label width-8"> Detector Type </label> |
|
|
|
<div class="gf-form-select-wrapper"> |
|
|
|
<div class="gf-form-select-wrapper"> |
|
|
|
<select class="gf-form-input width-10" |
|
|
|
<select class="gf-form-input width-8" |
|
|
|
ng-model="ctrl.analyticsController.newAnalyticUnit.detectorType" |
|
|
|
ng-model="ctrl.analyticsController.newAnalyticUnit.detectorType" |
|
|
|
ng-options="analyticUnitDetectorType for analyticUnitDetectorType in ctrl.analyticUnitDetectorTypes" |
|
|
|
ng-options="analyticUnitDetectorType for analyticUnitDetectorType in ctrl.analyticUnitDetectorTypes" |
|
|
|
ng-change="ctrl.analyticsController.onAnalyticUnitDetectorChange(ctrl.analyticUnitTypes);" |
|
|
|
ng-change="ctrl.analyticsController.onAnalyticUnitDetectorChange(ctrl.analyticUnitTypes);" |
|
|
|
/> |
|
|
|
/> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
|
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
|
|
<label class="gf-form-label width-8"> Type </label> |
|
|
|
<div class="gf-form"> |
|
|
|
|
|
|
|
<label class="gf-form-label width-5"> Type </label> |
|
|
|
<div class="gf-form-select-wrapper"> |
|
|
|
<div class="gf-form-select-wrapper"> |
|
|
|
<select class="gf-form-input width-10" |
|
|
|
<select class="gf-form-input width-9" |
|
|
|
ng-model="ctrl.analyticsController.newAnalyticUnit.type" |
|
|
|
ng-model="ctrl.analyticsController.newAnalyticUnit.type" |
|
|
|
ng-options=" |
|
|
|
ng-options=" |
|
|
|
type.value as type.name |
|
|
|
type.value as type.name |
|
|
@ -234,23 +320,33 @@ |
|
|
|
" |
|
|
|
" |
|
|
|
/> |
|
|
|
/> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
|
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
|
|
<label class="gf-form-label"> |
|
|
|
<div class="gf-form"> |
|
|
|
<a class="pointer" tabindex="1" ng-click="ctrl.saveNew()"> |
|
|
|
<a class="btn btn-danger" ng-click="ctrl.cancelCreation()"> |
|
|
|
<b ng-if="!ctrl.analyticsController.saving"> create </b> |
|
|
|
<b> Cancel </b> |
|
|
|
<b ng-if="ctrl.analyticsController.saving" ng-disabled="true"> saving... </b> |
|
|
|
</a> |
|
|
|
</a> |
|
|
|
</div> |
|
|
|
</label> |
|
|
|
|
|
|
|
|
|
|
|
<div class="gf-form"> |
|
|
|
|
|
|
|
<a class="btn btn-secondary" ng-click="ctrl.saveNew()"> |
|
|
|
|
|
|
|
<b ng-if="!ctrl.analyticsController.saving"> Create </b> |
|
|
|
|
|
|
|
<b ng-if="ctrl.analyticsController.saving" ng-disabled="true"> Saving... </b> |
|
|
|
|
|
|
|
</a> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
|
|
<div class="gf-form-button-row" ng-if="!ctrl.analyticsController.creatingAnalyticUnit"> |
|
|
|
<div class="gf-form-button-row"> |
|
|
|
<button class="btn btn-inverse width-12" ng-click="ctrl.createNew()"> |
|
|
|
<button |
|
|
|
|
|
|
|
class="btn btn-secondary width-12" |
|
|
|
|
|
|
|
ng-click="ctrl.createNew()" |
|
|
|
|
|
|
|
ng-disabled="ctrl.analyticsController.creatingNew" |
|
|
|
|
|
|
|
> |
|
|
|
<i class="fa fa-plus"></i> |
|
|
|
<i class="fa fa-plus"></i> |
|
|
|
Add Analytic Unit |
|
|
|
Add Analytic Unit |
|
|
|
</button> |
|
|
|
</button> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
<div class="gf-form-button-row"> |
|
|
|
<div class="gf-form-button-row" ng-if="ctrl.analyticsController.analyticUnits.length > 0"> |
|
|
|
<button class="gf-form-label width-12 pointer" ng-click="ctrl.redetectAll()"> |
|
|
|
<button class="gf-form-label width-12 pointer" ng-click="ctrl.redetectAll()"> |
|
|
|
Re-detect all analytic units |
|
|
|
Re-detect all analytic units |
|
|
|
</button> |
|
|
|
</button> |
|
|
|