18 changed files with 558 additions and 320 deletions
@ -1,12 +1 @@
|
||||
<h3 class="page-heading">Enter your Hastic config</h3> |
||||
<div class="gf-form-group"> |
||||
<div class="gf-form"> |
||||
<label class="gf-form-label width-10">Hastic server url</label> |
||||
<input |
||||
type="text" |
||||
class="gf-form-input max-width-20" |
||||
ng-model="ctrl.appModel.jsonData.hasticServerUrl" |
||||
ng-blur="ctrl.normalizeUrl" |
||||
/> |
||||
</div> |
||||
</div> |
||||
|
||||
|
@ -0,0 +1,33 @@
|
||||
import { normalizeUrl } from '../utlis'; |
||||
import configTemplate from './partials/config.html'; |
||||
|
||||
|
||||
export class HasticConfigCtrl { |
||||
public static template = configTemplate; |
||||
public ACCESS_OPTIONS = [ |
||||
{ key: 'proxy', value: 'Server (Default)' }, |
||||
{ key: 'direct', value: 'Browser' } |
||||
]; |
||||
|
||||
public showAccessHelp = false; |
||||
|
||||
constructor(private $scope: any) { |
||||
if(this.$scope.current === undefined) { |
||||
this.$scope.current = { |
||||
url: '', |
||||
access: 'proxy' |
||||
}; |
||||
} |
||||
} |
||||
|
||||
normalizeUrl() { |
||||
if(this.$scope.current.url === '') { |
||||
return; |
||||
} |
||||
this.$scope.current.url = normalizeUrl(this.$scope.current.url); |
||||
} |
||||
|
||||
toggleAccessHelp() { |
||||
this.showAccessHelp = !this.showAccessHelp; |
||||
} |
||||
} |
@ -0,0 +1,37 @@
|
||||
import HasticAPI from './hastic_api'; |
||||
|
||||
import { BackendSrv } from 'grafana/app/core/services/backend_srv'; |
||||
|
||||
export class HasticDatasource { |
||||
private hastic: HasticAPI; |
||||
|
||||
/** @ngInject */ |
||||
constructor(instanceSettings: any, backendSrv: BackendSrv) { |
||||
this.hastic = new HasticAPI(instanceSettings, backendSrv); |
||||
} |
||||
|
||||
async query(options: any) { |
||||
console.log(options); |
||||
} |
||||
|
||||
async testDatasource() { |
||||
try { |
||||
await this.hastic.get('/'); |
||||
// TODO: check if it is hastic
|
||||
return { |
||||
status: 'success', title: 'Success', |
||||
message: 'Datasource is working' |
||||
}; |
||||
} catch(err) { |
||||
console.error(err); |
||||
return { |
||||
status: 'error', title: 'Error', |
||||
message: 'Hastic connection error' |
||||
}; |
||||
} |
||||
} |
||||
|
||||
metricFindQuery(options: any) { |
||||
return []; |
||||
} |
||||
} |
@ -0,0 +1,29 @@
|
||||
import { BackendSrv } from 'grafana/app/core/services/backend_srv'; |
||||
|
||||
export default class HasticAPI { |
||||
private url: string; |
||||
|
||||
constructor(instanceSettings: any, private backendSrv: BackendSrv) { |
||||
this.url = instanceSettings.url; |
||||
} |
||||
|
||||
get(url: string, params?: any) { |
||||
return this._query('GET', url, params); |
||||
} |
||||
|
||||
private async _query(method: string, url: string, data?: any) { |
||||
method = method.toUpperCase(); |
||||
let options: any = { |
||||
method, |
||||
url: this.url + url |
||||
}; |
||||
if(method === 'GET' || method === 'DELETE') { |
||||
options.params = data; |
||||
} else { |
||||
options.data = data; |
||||
} |
||||
|
||||
const response = await this.backendSrv.datasourceRequest(options); |
||||
return response.data; |
||||
} |
||||
} |
@ -0,0 +1,10 @@
|
||||
import { HasticDatasource } from './datasource'; |
||||
import { HasticQueryCtrl } from './query_ctrl'; |
||||
import { HasticConfigCtrl } from './config_ctrl'; |
||||
|
||||
|
||||
export { |
||||
HasticDatasource as Datasource, |
||||
HasticConfigCtrl as ConfigCtrl, |
||||
HasticQueryCtrl as QueryCtrl |
||||
}; |
@ -0,0 +1,87 @@
|
||||
<div class="gf-form-group"> |
||||
<h3 class="page-heading">HTTP</h3> |
||||
<div class="gf-form-group"> |
||||
<div class="gf-form-inline"> |
||||
<div class="gf-form max-width-30"> |
||||
<span class="gf-form-label width-10">Hastic Server URL</span> |
||||
<input |
||||
class="gf-form-input" type="text" |
||||
placeholder="http://localhost:8000" |
||||
ng-model='ctrl.current.url' |
||||
min-length="0" |
||||
ng-pattern="/^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/" |
||||
required |
||||
ng-blur="ctrl.normalizeUrl()" |
||||
/> |
||||
<info-popover mode="right-absolute"> |
||||
<p>Specify a complete Hastic Server HTTP URL (for example http://your_hastic_server:8000)</p> |
||||
<span ng-show="ctrl.current.access === 'direct'"> |
||||
Your access method is <em>Browser</em>, this means the URL |
||||
needs to be accessible from the browser. |
||||
</span> |
||||
<span ng-show="ctrl.current.access === 'proxy'"> |
||||
Your access method is <em>Server</em>, this means the URL |
||||
needs to be accessible from the grafana backend/server. |
||||
</span> |
||||
</info-popover> |
||||
</div> |
||||
</div> |
||||
|
||||
<div class="gf-form-inline"> |
||||
<div class="gf-form max-width-30"> |
||||
<span class="gf-form-label width-10">Access</span> |
||||
<div class="gf-form-select-wrapper max-width-24"> |
||||
<select |
||||
class="gf-form-input" |
||||
ng-model="ctrl.current.access" |
||||
ng-options="f.key as f.value for f in ctrl.ACCESS_OPTIONS" |
||||
/> |
||||
</div> |
||||
</div> |
||||
<div class="gf-form"> |
||||
<label class="gf-form-label query-keyword pointer" ng-click="ctrl.toggleAccessHelp()"> |
||||
Help |
||||
<i class="fa fa-caret-down" ng-show="ctrl.showAccessHelp"></i> |
||||
<i class="fa fa-caret-right" ng-hide="ctrl.showAccessHelp"> </i> |
||||
</label> |
||||
</div> |
||||
</div> |
||||
|
||||
<div class="grafana-info-box m-t-2" ng-show="ctrl.showAccessHelp"> |
||||
<p> |
||||
Access mode controls how requests to the data source will be handled. |
||||
<strong><i>Server</i></strong> access mode should be the preferred way if nothing else stated. |
||||
</p> |
||||
<div class="alert-title">Server access mode (Default):</div> |
||||
<p> |
||||
All requests will be made from the browser to Grafana backend/server which in turn will |
||||
forward the requests to the data source and by that circumvent possible |
||||
Cross-Origin Resource Sharing (CORS) requirements. |
||||
The URL needs to be accessible from the grafana backend/server if you select this access mode. |
||||
</p> |
||||
<div class="alert-title">Browser access mode:</div> |
||||
<p> |
||||
All requests will be made from the browser directly to the data source and may be subject to |
||||
Cross-Origin Resource Sharing (CORS) requirements. The URL needs to be accessible from the browser |
||||
if you select this access mode. |
||||
</p> |
||||
</div> |
||||
|
||||
<div class="gf-form-inline" ng-if="ctrl.current.access=='proxy'"> |
||||
<div class="gf-form"> |
||||
<span class="gf-form-label width-10">Whitelisted Cookies</span> |
||||
<bootstrap-tagsinput |
||||
ng-model="ctrl.current.jsonData.keepCookies" |
||||
width-class="width-20" tagclass="label label-tag" |
||||
placeholder="Add Name" |
||||
/> |
||||
<info-popover mode="right-absolute"> |
||||
Grafana Proxy deletes forwarded cookies by default. Specify cookies by name |
||||
that should be forwarded to the data source. |
||||
</info-popover> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
|
||||
|
@ -0,0 +1,12 @@
|
||||
{ |
||||
"type": "datasource", |
||||
"name": "Hastic Datasource", |
||||
"id": "corpglory-hastic-datasource", |
||||
"metrics": true, |
||||
"info": { |
||||
"logos": { |
||||
"small": "../corpglory-hastic-app/img/icn-graph-panel.png", |
||||
"large": "../corpglory-hastic-app/img/icn-graph-panel.png" |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,12 @@
|
||||
import template from './partials/query_ctrl.html'; |
||||
|
||||
import { QueryCtrl } from 'grafana/app/plugins/sdk'; |
||||
|
||||
export class HasticQueryCtrl extends QueryCtrl { |
||||
static template = template; |
||||
|
||||
/** @ngInject */ |
||||
constructor($scope, $injector) { |
||||
super($scope, $injector); |
||||
} |
||||
} |
@ -1,210 +1,224 @@
|
||||
<div class="gf-form-button-row" ng-if="ctrl.analyticsController.serverStatus === false"> |
||||
<h5>Hastic server at "{{ctrl.backendURL}}" is not available</h5> |
||||
<button class="btn btn-inverse" ng-click="ctrl.runBackendConnectivityCheck()"> |
||||
<i class="fa fa-plug"></i> |
||||
Reconnect to Hastic server |
||||
</button> |
||||
<div class="gf-form-group"> |
||||
<div class="gf-form"> |
||||
<label class="gf-form-label">Select Hastic datasource</label> |
||||
<select class="gf-form-input max-width-15" |
||||
ng-model="ctrl.panel.hasticDatasource" |
||||
ng-options="ds.id as ds.name for ds in ctrl.hasticDatasources" |
||||
ng-change="ctrl.onHasticDatasourceChange()" |
||||
/> |
||||
</div> |
||||
</div> |
||||
|
||||
<div ng-if="ctrl.analyticsController.serverStatus === true"> |
||||
<h5> Analytic Units </h5> |
||||
<div class="editor-row"> |
||||
<div class="gf-form" ng-repeat="analyticUnit in ctrl.analyticsController.analyticUnits"> |
||||
|
||||
<label class="gf-form-label width-5"> |
||||
<i class="fa fa-info" bs-tooltip="'Analytic unit id: ' + analyticUnit.id"></i> |
||||
Name |
||||
</label> |
||||
<input |
||||
type="text" class="gf-form-input max-width-15" |
||||
ng-model="analyticUnit.name" |
||||
ng-change="ctrl.onAnalyticUnitNameChange(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> |
||||
|
||||
<!-- |
||||
<label class="gf-form-label width-6"> Confidence </label> |
||||
<input |
||||
type="number" class="gf-form-input width-5 ng-valid ng-scope ng-empty ng-dirty ng-valid-number ng-touched" |
||||
placeholder="auto" bs-tooltip="'Override automatic decimal precision for legend and tooltips'" |
||||
data-placement="right" ng-model="ctrl.panel.decimals" ng-change="ctrl.render()" ng-model-onblur="" data-original-title="" title="" |
||||
/> |
||||
--> |
||||
|
||||
<label class="gf-form-label width-8"> Positive Color </label> |
||||
<span class="gf-form-label"> |
||||
<color-picker |
||||
color="analyticUnit.labeledColor" |
||||
onChange="ctrl.onColorChange.bind(ctrl, analyticUnit.id, false)" |
||||
/> |
||||
</span> |
||||
|
||||
<!-- Hack to avoid Grafana's .gf-form-label + .gf-form-label css. Fix for https://github.com/hastic/hastic-grafana-app/issues/192 --> |
||||
<div ng-if="analyticUnit.detectorType === 'pattern'"></div> |
||||
|
||||
<label ng-if="analyticUnit.detectorType === 'pattern'" class="gf-form-label width-8"> Negative Color </label> |
||||
<span ng-if="analyticUnit.detectorType === 'pattern'" class="gf-form-label"> |
||||
<color-picker |
||||
color="analyticUnit.deletedColor" |
||||
onChange="ctrl.onColorChange.bind(ctrl, analyticUnit.id, true)" |
||||
/> |
||||
</span> |
||||
|
||||
<label |
||||
class="gf-form-label" |
||||
ng-if="analyticUnit.detectorType === 'pattern'" |
||||
ng-style="analyticUnit.status === 'LEARNING' && { 'cursor': 'not-allowed' }" |
||||
> |
||||
<a class="pointer" tabindex="1" |
||||
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> |
||||
<b ng-if="analyticUnit.saving" ng-disabled="true"> saving... </b> |
||||
</a> |
||||
</label> |
||||
|
||||
<select class="gf-form-input width-10" |
||||
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'" |
||||
/> |
||||
|
||||
<select class="gf-form-input width-7" |
||||
ng-model="ctrl.analyticsController.getThreshold(analyticUnit.id).condition" |
||||
ng-options="type for type in ctrl.analyticsController.conditions" |
||||
ng-if="analyticUnit.detectorType === 'threshold'" |
||||
/> |
||||
<input |
||||
class="gf-form-input width-5" |
||||
type="number" |
||||
ng-model="ctrl.analyticsController.getThreshold(analyticUnit.id).value" |
||||
ng-if=" |
||||
analyticUnit.detectorType === 'threshold' && |
||||
ctrl.analyticsController.getThreshold(analyticUnit.id).condition != 'NO_DATA' |
||||
" |
||||
/> |
||||
<!-- TODO set .saving flag to thresholds, when learning is in progress --> |
||||
<button |
||||
class="btn btn-inverse" |
||||
ng-if="analyticUnit.detectorType === 'threshold'" |
||||
ng-click="ctrl.analyticsController.sendThresholdParamsToServer(analyticUnit.id)" |
||||
ng-disabled="analyticUnit.status === 'PENDING' || analyticUnit.status === 'LEARNING'" |
||||
> |
||||
Apply |
||||
</button> |
||||
<div class="gf-form"> |
||||
<div class="gf-form-button-row" ng-if="ctrl.analyticsController.serverStatus === false"> |
||||
<h5>Hastic server at "{{ctrl.backendURL}}" is not available</h5> |
||||
<button class="btn btn-inverse" ng-click="ctrl.runBackendConnectivityCheck()"> |
||||
<i class="fa fa-plug"></i> |
||||
Reconnect to Hastic server |
||||
</button> |
||||
</div> |
||||
|
||||
<label class="gf-form-label" ng-hide="analyticUnit.selected"> |
||||
<a |
||||
ng-if="analyticUnit.visible" |
||||
bs-tooltip="'Hide. It`s visible now.'" |
||||
ng-click="ctrl.onToggleVisibility(analyticUnit.id)" |
||||
class="pointer" |
||||
> |
||||
<i class="fa fa-eye"></i> |
||||
</a> |
||||
|
||||
<a |
||||
ng-if="!analyticUnit.visible" |
||||
bs-tooltip="'Show. It`s hidden now.'" |
||||
ng-click="ctrl.onToggleVisibility(analyticUnit.id)" |
||||
class="pointer" |
||||
<div ng-if="ctrl.analyticsController.serverStatus === true"> |
||||
<h5> Analytic Units </h5> |
||||
<div class="editor-row"> |
||||
<div class="gf-form" ng-repeat="analyticUnit in ctrl.analyticsController.analyticUnits"> |
||||
|
||||
<label class="gf-form-label width-5"> |
||||
<i class="fa fa-info" bs-tooltip="'Analytic unit id: ' + analyticUnit.id"></i> |
||||
Name |
||||
</label> |
||||
<input |
||||
type="text" class="gf-form-input max-width-15" |
||||
ng-model="analyticUnit.name" |
||||
ng-change="ctrl.onAnalyticUnitNameChange(analyticUnit)" |
||||
> |
||||
<i class="fa fa-eye-slash"></i> |
||||
</a> |
||||
</label> |
||||
|
||||
<label class="gf-form-label"> |
||||
<a |
||||
ng-if="!analyticUnit.selected" |
||||
ng-click="ctrl.onRemove(analyticUnit.id)" |
||||
class="pointer" |
||||
> |
||||
<i class="fa fa-trash"></i> |
||||
</a> |
||||
|
||||
<a |
||||
ng-if="analyticUnit.selected" |
||||
ng-click="ctrl.onCancelLabeling(analyticUnit.id)" |
||||
class="pointer" |
||||
<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> |
||||
|
||||
<!-- |
||||
<label class="gf-form-label width-6"> Confidence </label> |
||||
<input |
||||
type="number" class="gf-form-input width-5 ng-valid ng-scope ng-empty ng-dirty ng-valid-number ng-touched" |
||||
placeholder="auto" bs-tooltip="'Override automatic decimal precision for legend and tooltips'" |
||||
data-placement="right" ng-model="ctrl.panel.decimals" ng-change="ctrl.render()" ng-model-onblur="" data-original-title="" title="" |
||||
/> |
||||
--> |
||||
|
||||
<label class="gf-form-label width-8"> Positive Color </label> |
||||
<span class="gf-form-label"> |
||||
<color-picker |
||||
color="analyticUnit.labeledColor" |
||||
onChange="ctrl.onColorChange.bind(ctrl, analyticUnit.id, false)" |
||||
/> |
||||
</span> |
||||
|
||||
<!-- Hack to avoid Grafana's .gf-form-label + .gf-form-label css. Fix for https://github.com/hastic/hastic-grafana-app/issues/192 --> |
||||
<div ng-if="analyticUnit.detectorType === 'pattern'"></div> |
||||
|
||||
<label ng-if="analyticUnit.detectorType === 'pattern'" class="gf-form-label width-8"> Negative Color </label> |
||||
<span ng-if="analyticUnit.detectorType === 'pattern'" class="gf-form-label"> |
||||
<color-picker |
||||
color="analyticUnit.deletedColor" |
||||
onChange="ctrl.onColorChange.bind(ctrl, analyticUnit.id, true)" |
||||
/> |
||||
</span> |
||||
|
||||
<label |
||||
class="gf-form-label" |
||||
ng-if="analyticUnit.detectorType === 'pattern'" |
||||
ng-style="analyticUnit.status === 'LEARNING' && { 'cursor': 'not-allowed' }" |
||||
> |
||||
<i class="fa fa-ban"></i> |
||||
</a> |
||||
</label> |
||||
|
||||
<label> |
||||
<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> |
||||
<a class="pointer" tabindex="1" |
||||
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> |
||||
<b ng-if="analyticUnit.saving" ng-disabled="true"> saving... </b> |
||||
</a> |
||||
</label> |
||||
|
||||
</div> |
||||
</div> |
||||
|
||||
<div class="editor-row" ng-if="ctrl.analyticsController.creatingNew"> |
||||
<div class="gf-form"> |
||||
<label class="gf-form-label width-4"> Name </label> |
||||
<input |
||||
type="text" class="gf-form-input max-width-15" |
||||
ng-model="ctrl.analyticsController.newAnalyticUnit.name" |
||||
> |
||||
|
||||
<label class="gf-form-label width-8"> Detector Type </label> |
||||
<div class="gf-form-select-wrapper"> |
||||
<select class="gf-form-input width-10" |
||||
ng-model="ctrl.analyticsController.newAnalyticUnit.detectorType" |
||||
ng-options="analyticUnitDetectorType for analyticUnitDetectorType in ctrl.analyticUnitDetectorTypes" |
||||
ng-change="ctrl.analyticsController.onAnalyticUnitDetectorChange(ctrl.analyticUnitTypes);" |
||||
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'" |
||||
/> |
||||
</div> |
||||
|
||||
<label class="gf-form-label width-8"> Type </label> |
||||
<div class="gf-form-select-wrapper"> |
||||
<select class="gf-form-input width-10" |
||||
ng-model="ctrl.analyticsController.newAnalyticUnit.type" |
||||
ng-options=" |
||||
type.value as type.name |
||||
for type in ctrl.analyticUnitTypes[ctrl.analyticsController.newAnalyticUnit.detectorType] |
||||
<select class="gf-form-input width-7" |
||||
ng-model="ctrl.analyticsController.getThreshold(analyticUnit.id).condition" |
||||
ng-options="type for type in ctrl.analyticsController.conditions" |
||||
ng-if="analyticUnit.detectorType === 'threshold'" |
||||
/> |
||||
<input |
||||
class="gf-form-input width-5" |
||||
type="number" |
||||
ng-model="ctrl.analyticsController.getThreshold(analyticUnit.id).value" |
||||
ng-if=" |
||||
analyticUnit.detectorType === 'threshold' && |
||||
ctrl.analyticsController.getThreshold(analyticUnit.id).condition != 'NO_DATA' |
||||
" |
||||
/> |
||||
<!-- TODO set .saving flag to thresholds, when learning is in progress --> |
||||
<button |
||||
class="btn btn-inverse" |
||||
ng-if="analyticUnit.detectorType === 'threshold'" |
||||
ng-click="ctrl.analyticsController.sendThresholdParamsToServer(analyticUnit.id)" |
||||
ng-disabled="analyticUnit.status === 'PENDING' || analyticUnit.status === 'LEARNING'" |
||||
> |
||||
Apply |
||||
</button> |
||||
|
||||
<label class="gf-form-label" ng-hide="analyticUnit.selected"> |
||||
<a |
||||
ng-if="analyticUnit.visible" |
||||
bs-tooltip="'Hide. It`s visible now.'" |
||||
ng-click="ctrl.onToggleVisibility(analyticUnit.id)" |
||||
class="pointer" |
||||
> |
||||
<i class="fa fa-eye"></i> |
||||
</a> |
||||
|
||||
<a |
||||
ng-if="!analyticUnit.visible" |
||||
bs-tooltip="'Show. It`s hidden now.'" |
||||
ng-click="ctrl.onToggleVisibility(analyticUnit.id)" |
||||
class="pointer" |
||||
> |
||||
<i class="fa fa-eye-slash"></i> |
||||
</a> |
||||
</label> |
||||
|
||||
<label class="gf-form-label"> |
||||
<a |
||||
ng-if="!analyticUnit.selected" |
||||
ng-click="ctrl.onRemove(analyticUnit.id)" |
||||
class="pointer" |
||||
> |
||||
<i class="fa fa-trash"></i> |
||||
</a> |
||||
|
||||
<a |
||||
ng-if="analyticUnit.selected" |
||||
ng-click="ctrl.onCancelLabeling(analyticUnit.id)" |
||||
class="pointer" |
||||
> |
||||
<i class="fa fa-ban"></i> |
||||
</a> |
||||
</label> |
||||
|
||||
<label> |
||||
<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 class="editor-row" ng-if="ctrl.analyticsController.creatingNew"> |
||||
<div class="gf-form"> |
||||
<label class="gf-form-label width-4"> Name </label> |
||||
<input |
||||
type="text" class="gf-form-input max-width-15" |
||||
ng-model="ctrl.analyticsController.newAnalyticUnit.name" |
||||
> |
||||
|
||||
<label class="gf-form-label"> |
||||
<a class="pointer" tabindex="1" ng-click="ctrl.saveNew()"> |
||||
<b ng-if="!ctrl.analyticsController.saving"> create </b> |
||||
<b ng-if="ctrl.analyticsController.saving" ng-disabled="true"> saving... </b> |
||||
</a> |
||||
</label> |
||||
<label class="gf-form-label width-8"> Detector Type </label> |
||||
<div class="gf-form-select-wrapper"> |
||||
<select class="gf-form-input width-10" |
||||
ng-model="ctrl.analyticsController.newAnalyticUnit.detectorType" |
||||
ng-options="analyticUnitDetectorType for analyticUnitDetectorType in ctrl.analyticUnitDetectorTypes" |
||||
ng-change="ctrl.analyticsController.onAnalyticUnitDetectorChange(ctrl.analyticUnitTypes);" |
||||
/> |
||||
</div> |
||||
|
||||
<label class="gf-form-label width-8"> Type </label> |
||||
<div class="gf-form-select-wrapper"> |
||||
<select class="gf-form-input width-10" |
||||
ng-model="ctrl.analyticsController.newAnalyticUnit.type" |
||||
ng-options=" |
||||
type.value as type.name |
||||
for type in ctrl.analyticUnitTypes[ctrl.analyticsController.newAnalyticUnit.detectorType] |
||||
" |
||||
/> |
||||
</div> |
||||
|
||||
<label class="gf-form-label"> |
||||
<a class="pointer" tabindex="1" ng-click="ctrl.saveNew()"> |
||||
<b ng-if="!ctrl.analyticsController.saving"> create </b> |
||||
<b ng-if="ctrl.analyticsController.saving" ng-disabled="true"> saving... </b> |
||||
</a> |
||||
</label> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
|
||||
<div class="gf-form-button-row" ng-if="!ctrl.analyticsController.creatingAnalyticUnit"> |
||||
<button class="btn btn-inverse" ng-click="ctrl.createNew()"> |
||||
<i class="fa fa-plus"></i> |
||||
Add Analytic Unit |
||||
</button> |
||||
</div> |
||||
<div class="gf-form-button-row"> |
||||
<button class="gf-form-label width-10 pointer" ng-click="ctrl.showHelp = !ctrl.showHelp"> |
||||
Show Help |
||||
<i class="fa fa-caret-down" ng-show="ctrl.showHelp"></i> |
||||
<i class="fa fa-caret-right" ng-hide="ctrl.showHelp"></i> |
||||
</button> |
||||
<div class="gf-form-button-row" ng-if="!ctrl.analyticsController.creatingAnalyticUnit"> |
||||
<button class="btn btn-inverse" ng-click="ctrl.createNew()"> |
||||
<i class="fa fa-plus"></i> |
||||
Add Analytic Unit |
||||
</button> |
||||
</div> |
||||
<div class="gf-form-button-row"> |
||||
<button class="gf-form-label width-10 pointer" ng-click="ctrl.showHelp = !ctrl.showHelp"> |
||||
Show Help |
||||
<i class="fa fa-caret-down" ng-show="ctrl.showHelp"></i> |
||||
<i class="fa fa-caret-right" ng-hide="ctrl.showHelp"></i> |
||||
</button> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
|
||||
<div class="gf-form" ng-show="ctrl.showHelp" ng-bind-html="ctrl.analyticsController.helpSectionText"></div> |
||||
|
||||
|
Loading…
Reference in new issue