Skip to content

Commit

Permalink
UI improvements (#310)
Browse files Browse the repository at this point in the history
* disable Add Analytic Unit button

* width fixes

* cancel word instead of icon

* Save button

* Cancel creation

* Disable Detect if not saved
  • Loading branch information
rozetko authored May 20, 2019
1 parent e868fb6 commit d965d0b
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 75 deletions.
18 changes: 14 additions & 4 deletions src/panel/graph_panel/controllers/analytic_controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,11 @@ export class AnalyticController {
}
}

cancelCreation() {
delete this._newAnalyticUnit;
this._creatingNewAnalyticUnit = false;
}

async saveNew(metric: MetricExpanded, datasource: DatasourceRequest) {
this._savingNewAnalyticUnit = true;
const newAnalyticUnit = createAnalyticUnit(this._newAnalyticUnit.toJSON());
Expand Down Expand Up @@ -215,7 +220,7 @@ export class AnalyticController {
} else {
analyticUnit.labeledColor = value;
}
await this.saveAnalyticUnit(analyticUnit);
analyticUnit.changed = true;
}

fetchAnalyticUnitsStatuses() {
Expand Down Expand Up @@ -474,6 +479,10 @@ export class AnalyticController {
await this._analyticService.setAnalyticUnitAlert(analyticUnit);
}

toggleAnalyticUnitChange(analyticUnit: AnalyticUnit, value: boolean): void {
analyticUnit.changed = value;
}

async saveAnalyticUnit(analyticUnit: AnalyticUnit): Promise<void> {
if(analyticUnit.id === null || analyticUnit.id === undefined) {
throw new Error('Cannot save analytic unit without id');
Expand All @@ -482,6 +491,7 @@ export class AnalyticController {
analyticUnit.saving = true;
await this._analyticService.updateAnalyticUnit(analyticUnit.toJSON());
analyticUnit.saving = false;
analyticUnit.changed = false;
}

async getAnalyticUnits(): Promise<any[]> {
Expand Down Expand Up @@ -671,14 +681,14 @@ export class AnalyticController {
return this._tempIdCounted.toString();
}

public async toggleVisibility(id: AnalyticUnitId, value?: boolean) {
public toggleVisibility(id: AnalyticUnitId, value?: boolean) {
const analyticUnit = this._analyticUnitsSet.byId(id);
if(value !== undefined) {
analyticUnit.visible = value;
} else {
analyticUnit.visible = !analyticUnit.visible;
}
await this.saveAnalyticUnit(analyticUnit);
analyticUnit.changed = true;
}

public toggleInspect(id: AnalyticUnitId) {
Expand All @@ -692,7 +702,7 @@ export class AnalyticController {
if(value !== undefined) {
analyticUnit.seasonalityPeriod.value = value;
}
await this.saveAnalyticUnit(analyticUnit);
analyticUnit.changed = true;
}

public onAnalyticUnitDetectorChange(analyticUnitTypes: any) {
Expand Down
10 changes: 9 additions & 1 deletion src/panel/graph_panel/graph_ctrl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -562,6 +562,10 @@ class GraphCtrl extends MetricsPanelCtrl {
this.analyticsController.createNew();
}

cancelCreation() {
this.analyticsController.cancelCreation();
}

redetectAll() {
this.analyticsController.redetectAll();
}
Expand Down Expand Up @@ -600,7 +604,11 @@ class GraphCtrl extends MetricsPanelCtrl {
await this.analyticsController.toggleAnalyticUnitAlert(analyticUnit);
}

async onAnalyticUnitChange(analyticUnit: AnalyticUnit) {
onAnalyticUnitChange(analyticUnit: AnalyticUnit) {
this.analyticsController.toggleAnalyticUnitChange(analyticUnit, true);
}

async onAnalyticUnitSave(analyticUnit: AnalyticUnit) {
await this.analyticsController.saveAnalyticUnit(analyticUnit);
this.refresh();
}
Expand Down
4 changes: 4 additions & 0 deletions src/panel/graph_panel/models/analytic_units/analytic_unit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ export class AnalyticUnit {
private _segmentSet = new SegmentArray<AnalyticSegment>();
private _detectionSpans: DetectionSpan[];
private _inspect = false;
private _changed = false;
private _status: string;
private _error: string;

Expand Down Expand Up @@ -117,6 +118,9 @@ export class AnalyticUnit {
get saving(): boolean { return this._saving; }
set saving(value: boolean) { this._saving = value; }

get changed(): boolean { return this._changed; }
set changed(value: boolean) { this._changed = value; }

get inspect(): boolean { return this._inspect; }
set inspect(value: boolean) { this._inspect = value; }

Expand Down
162 changes: 92 additions & 70 deletions src/panel/graph_panel/partials/tab_analytics.html
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ <h5> Analytic Units </h5>
<div class="gf-form">
<label class="gf-form-label width-5"> Type </label>
<div class="gf-form-select-wrapper">
<select class="gf-form-input width-10"
<select class="gf-form-input width-9"
ng-model="analyticUnit.type"
ng-options="type.value as type.name for type in ctrl.analyticUnitTypes[analyticUnit.detectorType]"
ng-disabled="true"
Expand Down Expand Up @@ -73,7 +73,7 @@ <h5> Analytic Units </h5>
class="gf-form"
style="margin-bottom: 0"
label="Inspect"
label-class="width-7"
label-class="width-5"
on-change="ctrl.onToggleInspect(analyticUnit.id)"
checked="analyticUnit.inspect"
/>
Expand Down Expand Up @@ -127,57 +127,24 @@ <h5> Analytic Units </h5>
</label>
</div>

<div class="gf-form">
<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>
<div class="gf-form" ng-if="!analyticUnit.selected">
<a
class="btn btn-danger"
ng-click="ctrl.onRemove(analyticUnit.id)"
>
<i class="fa fa-trash"></i>
</a>
</div>

<div class="gf-form" ng-if="analyticUnit.selected">
<div class="gf-form-label">
<a
ng-if="analyticUnit.selected"
ng-click="ctrl.onCancelLabeling(analyticUnit.id)"
class="pointer"
ng-click="ctrl.onCancelLabeling(analyticUnit.id)"
>
<i class="fa fa-ban"></i>
</a>
</label>
</div>

<div class="gf-form" ng-if="analyticUnit.selected && !analyticUnit.saving">
<!-- Standard way to add conditions to ng-style: https://stackoverflow.com/a/29470439 -->
<label
class="gf-form-label"
ng-style="analyticUnit.status === 'LEARNING' && { 'cursor': 'not-allowed' }"
ng-disabled="analyticUnit.status === 'LEARNING'"
>
<a class="pointer"
ng-click="ctrl.onToggleLabelingMode(analyticUnit.id)"
ng-disabled="analyticUnit.status === 'LEARNING'"
>
<i class="fa fa-spinner fa-spin" ng-if="analyticUnit.saving"></i>
<b ng-if="!analyticUnit.saving"> Detect </b>
<b ng-if="analyticUnit.saving" ng-disabled="true"> saving... </b>
</a>
</label>
</div>

<div class="gf-form"
ng-if="
analyticUnit.detectorType === 'threshold' ||
(analyticUnit.detectorType === 'anomaly' && !analyticUnit.hasSeasonality)
"
>
<label class="gf-form-label">
<a class="pointer" ng-click="ctrl.runDetectInCurrentRange(analyticUnit.id)">
<i class="fa fa-spinner fa-spin" ng-if="analyticUnit.saving"></i>
<b ng-if="!analyticUnit.saving"> Detect </b>
<b ng-if="analyticUnit.saving" ng-disabled="true"> saving... </b>
Cancel
</a>
</label>
</div>
</div>

<div class="gf-form">
Expand All @@ -195,27 +162,26 @@ <h5> Analytic Units </h5>
<!-- 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 width-5"
<select class="gf-form-input"
ng-class="{
'width-5': analyticUnit.condition !== 'NO_DATA',
'width-10': 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-5"
<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>

<div class="gf-form" ng-if="analyticUnit.detectorType === 'anomaly' && !analyticUnit.selected">
<div class="gf-form" ng-if="analyticUnit.detectorType === 'anomaly'">
<label class="gf-form-label width-5"> Alpha </label>
<input class="gf-form-input width-10"
ng-hide="analyticUnit.selected"
<input class="gf-form-input width-9"
min="0"
max="1"
type="number"
Expand All @@ -224,7 +190,7 @@ <h5> Analytic Units </h5>
/>
</div>

<div class="gf-form" ng-if="analyticUnit.detectorType === 'anomaly' && !analyticUnit.selected">
<div class="gf-form" ng-if="analyticUnit.detectorType === 'anomaly'">
<label class="gf-form-label width-6"> Confidence </label>
<input class="gf-form-input width-5"
min="0"
Expand All @@ -234,7 +200,7 @@ <h5> Analytic Units </h5>
/>
</div>

<div class="gf-form" ng-if="analyticUnit.detectorType === 'anomaly' && !analyticUnit.selected">
<div class="gf-form" ng-if="analyticUnit.detectorType === 'anomaly'">
<!-- TODO: Remove hack with "margin-bottom: 0" -->
<gf-form-switch
class="gf-form"
Expand All @@ -248,7 +214,7 @@ <h5> Analytic Units </h5>

<div
class="gf-form"
ng-if="analyticUnit.detectorType === 'anomaly' && analyticUnit.hasSeasonality && !analyticUnit.selected"
ng-if="analyticUnit.detectorType === 'anomaly' && analyticUnit.hasSeasonality"
>
<label class="gf-form-label width-9"> Seasonality Period </label>
<input
Expand All @@ -263,8 +229,7 @@ <h5> Analytic Units </h5>
<div class="gf-form"
ng-if="
analyticUnit.detectorType === 'anomaly' &&
analyticUnit.hasSeasonality &&
!analyticUnit.selected
analyticUnit.hasSeasonality
"
>
<div class="gf-form-select-wrapper">
Expand All @@ -277,47 +242,104 @@ <h5> Analytic Units </h5>
</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-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>
</button>
</div>

<!-- TODO: Leave one Detect button instead of 2 -->
<div class="gf-form"
ng-if="
analyticUnit.detectorType === 'pattern' ||
(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.segments.length"
>
<b> Detect </b>
</button>
</div>

<div class="gf-form"
ng-if="
analyticUnit.detectorType === 'threshold' ||
(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"
>
<b> Detect </b>
</button>
</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">
<label class="gf-form-label width-5"> Name </label>
<input
type="text" class="gf-form-input width-15"
ng-model="ctrl.analyticsController.newAnalyticUnit.name"
>
</div>

<div class="gf-form">
<label class="gf-form-label width-8"> Detector Type </label>
<div class="gf-form-select-wrapper">
<select class="gf-form-input width-7"
<select class="gf-form-input width-8"
ng-model="ctrl.analyticsController.newAnalyticUnit.detectorType"
ng-options="analyticUnitDetectorType for analyticUnitDetectorType in ctrl.analyticUnitDetectorTypes"
ng-change="ctrl.analyticsController.onAnalyticUnitDetectorChange(ctrl.analyticUnitTypes);"
/>
</div>
</div>

<div class="gf-form">
<label class="gf-form-label width-5"> Type </label>
<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-options="
type.value as type.name
for type in ctrl.analyticUnitTypes[ctrl.analyticsController.newAnalyticUnit.detectorType]
"
/>
</div>
</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 class="gf-form">
<a class="btn btn-danger" ng-click="ctrl.cancelCreation()">
<b> Cancel </b>
</a>
</div>

<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 class="gf-form-button-row" ng-if="!ctrl.analyticsController.creatingAnalyticUnit">
<button class="btn btn-secondary width-12" ng-click="ctrl.createNew()">
<div class="gf-form-button-row">
<button
class="btn btn-secondary width-12"
ng-click="ctrl.createNew()"
ng-disabled="ctrl.analyticsController.creatingNew"
>
<i class="fa fa-plus"></i>
Add Analytic Unit
</button>
Expand Down

0 comments on commit d965d0b

Please sign in to comment.