Browse Source

WIP Display anti-segments #66 (#67)

* WIP

* Render deleted segments and trash icon in tooltip
master
rozetko 6 years ago committed by Alexey Velikiy
parent
commit
6f9ac9245b
  1. 26
      src/controllers/analytic_controller.ts
  2. 28
      src/graph_tooltip.ts
  3. 10
      src/models/analytic_unit.ts
  4. 1
      src/module.ts
  5. 10
      src/services/analytic_service.ts

26
src/controllers/analytic_controller.ts

@ -24,6 +24,8 @@ export const REGION_STROKE_ALPHA = 0.9;
export const REGION_DELETE_COLOR_LIGHT = '#d1d1d1'; export const REGION_DELETE_COLOR_LIGHT = '#d1d1d1';
export const REGION_DELETE_COLOR_DARK = 'white'; export const REGION_DELETE_COLOR_DARK = 'white';
const LABELED_SEGMENT_BORDER_COLOR = 'black'; const LABELED_SEGMENT_BORDER_COLOR = 'black';
const DELETED_SEGMENT_FILL_COLOR = 'black';
const DELETED_SEGMENT_BORDER_COLOR = 'black';
export class AnalyticController { export class AnalyticController {
@ -59,7 +61,7 @@ export class AnalyticController {
this._analyticUnitsSet.items.forEach(at => { this._analyticUnitsSet.items.forEach(at => {
var segs = at.segments.findSegments(point, rangeDist); var segs = at.segments.findSegments(point, rangeDist);
segs.forEach(s => { segs.forEach(s => {
result.push({ anomalyType: at, segment: s }); result.push({ analyticUnit: at, segment: s });
}) })
}) })
return result; return result;
@ -125,7 +127,8 @@ export class AnalyticController {
var newIds = await this._saveLabelingData(); var newIds = await this._saveLabelingData();
this._labelingDataAddedSegments.getSegments().forEach((s, i) => { this._labelingDataAddedSegments.getSegments().forEach((s, i) => {
this.labelingAnomaly.segments.updateId(s.id, newIds[i]); this.labelingAnomaly.segments.updateId(s.id, newIds[i]);
}) });
this.labelingAnomaly.saving = false; this.labelingAnomaly.saving = false;
var anomaly = this.labelingAnomaly; var anomaly = this.labelingAnomaly;
@ -138,7 +141,7 @@ export class AnalyticController {
this.labelingAnomaly.segments.remove(s.id); this.labelingAnomaly.segments.remove(s.id);
}); });
this._labelingDataDeletedSegments.getSegments().forEach(s => { this._labelingDataDeletedSegments.getSegments().forEach(s => {
this.labelingAnomaly.segments.addSegment(s); s.deleted = false;
}); });
this.dropLabeling(); this.dropLabeling();
} }
@ -254,18 +257,32 @@ export class AnalyticController {
let labeledSegmentBorderColor = tinycolor(LABELED_SEGMENT_BORDER_COLOR).toRgbString(); let labeledSegmentBorderColor = tinycolor(LABELED_SEGMENT_BORDER_COLOR).toRgbString();
labeledSegmentBorderColor = addAlphaToRGB(labeledSegmentBorderColor, REGION_STROKE_ALPHA); labeledSegmentBorderColor = addAlphaToRGB(labeledSegmentBorderColor, REGION_STROKE_ALPHA);
let deletedSegmentFillColor = tinycolor(DELETED_SEGMENT_FILL_COLOR).toRgbString();
deletedSegmentFillColor = addAlphaToRGB(deletedSegmentFillColor, REGION_STROKE_ALPHA);
let deletedSegmentBorderColor = tinycolor(DELETED_SEGMENT_BORDER_COLOR).toRgbString();
deletedSegmentBorderColor = addAlphaToRGB(deletedSegmentBorderColor, REGION_STROKE_ALPHA);
segments.forEach(s => { segments.forEach(s => {
let segmentBorderColor; let segmentBorderColor;
let segmentFillColor = fillColor;
if(s.labeled) { if(s.labeled) {
segmentBorderColor = labeledSegmentBorderColor; segmentBorderColor = labeledSegmentBorderColor;
} else { } else {
segmentBorderColor = borderColor; segmentBorderColor = borderColor;
} }
if(this.labelingDeleteMode) {
if(s.deleted) {
segmentBorderColor = deletedSegmentBorderColor;
segmentFillColor = deletedSegmentFillColor;
}
}
var expanded = s.expandDist(rangeDist, 0.01); var expanded = s.expandDist(rangeDist, 0.01);
options.grid.markings.push({ options.grid.markings.push({
xaxis: { from: expanded.from, to: expanded.to }, xaxis: { from: expanded.from, to: expanded.to },
color: fillColor color: segmentFillColor
}); });
options.grid.markings.push({ options.grid.markings.push({
xaxis: { from: expanded.from, to: expanded.from }, xaxis: { from: expanded.from, to: expanded.from },
@ -281,7 +298,6 @@ export class AnalyticController {
} }
deleteLabelingAnomalySegmentsInRange(from: number, to: number) { deleteLabelingAnomalySegmentsInRange(from: number, to: number) {
console.log('deleteLabelingAnomalySegmentsInRange was called')
var allRemovedSegs = this.labelingAnomaly.removeSegmentsInRange(from, to); var allRemovedSegs = this.labelingAnomaly.removeSegmentsInRange(from, to);
allRemovedSegs.forEach(s => { allRemovedSegs.forEach(s => {
if(!this._labelingDataAddedSegments.has(s.id)) { if(!this._labelingDataAddedSegments.has(s.id)) {

28
src/graph_tooltip.ts

@ -10,7 +10,7 @@ export class GraphTooltip {
private _lastItem = undefined; private _lastItem = undefined;
constructor( constructor(
private $elem: JQuery<HTMLElement>, private dashboard, private $elem: JQuery<HTMLElement>, private dashboard,
private scope, private getSeriesFn, private scope, private getSeriesFn,
private _anomalySegmentsSearcher: AnalyticSegmentsSearcher private _anomalySegmentsSearcher: AnalyticSegmentsSearcher
) { ) {
@ -53,7 +53,7 @@ export class GraphTooltip {
} }
pos.pageX = this.$elem.offset().left + pointOffset.left; pos.pageX = this.$elem.offset().left + pointOffset.left;
pos.pageY = this.$elem.offset().top + this.$elem.height() * pos.panelRelY; pos.pageY = this.$elem.offset().top + this.$elem.height() * pos.panelRelY;
var isVisible = pos.pageY >= $(window).scrollTop() && var isVisible = pos.pageY >= $(window).scrollTop() &&
pos.pageY <= $(window).innerHeight() + $(window).scrollTop(); pos.pageY <= $(window).innerHeight() + $(window).scrollTop();
if (!isVisible) { if (!isVisible) {
this.clear(plot); this.clear(plot);
@ -148,7 +148,7 @@ export class GraphTooltip {
} }
}; };
destroy() { destroy() {
this._visible = false; this._visible = false;
this.$tooltip.remove(); this.$tooltip.remove();
@ -199,21 +199,31 @@ export class GraphTooltip {
segments.forEach(s => { segments.forEach(s => {
var from = this.dashboard.formatDate(s.segment.from, 'HH:mm:ss.SSS'); var from = this.dashboard.formatDate(s.segment.from, 'HH:mm:ss.SSS');
var to = this.dashboard.formatDate(s.segment.to, 'HH:mm:ss.SSS'); var to = this.dashboard.formatDate(s.segment.to, 'HH:mm:ss.SSS');
if(s.segment.deleted && !s.analyticUnit.deleteMode) {
return;
}
let icon;
if (s.segment.labeled) {
icon = 'fa-thumb-tack';
} else if (s.segment.deleted) {
icon = 'fa-trash';
} else {
icon = 'fa-search-plus';
}
result += ` result += `
<div class="graph-tooltip-list-item"> <div class="graph-tooltip-list-item">
<div class="graph-tooltip-series-name"> <div class="graph-tooltip-series-name">
<i class="fa fa-exclamation" style="color:${s.anomalyType.color}"></i> <i class="fa fa-exclamation" style="color:${s.analyticUnit.color}"></i>
${s.anomalyType.name}: ${s.analyticUnit.name}:
</div> </div>
<div class="graph-tooltip-value"> <div class="graph-tooltip-value">
<i class="fa ${ s.segment.labeled ? "fa-thumb-tack" : "fa-search-plus" }" aria-hidden="true"></i> <i class="fa ${ icon }" aria-hidden="true"></i>
${from} ${to} ${from} ${to}
</div> </div>
</div> </div>
`; `;
}); });
return result; return result;
} }

10
src/models/analytic_unit.ts

@ -8,13 +8,13 @@ import { ANALYTIC_UNIT_COLORS } from '../colors';
import _ from 'lodash'; import _ from 'lodash';
export type AnalyticSegmentPair = { anomalyType: AnalyticUnit, segment: AnalyticSegment }; export type AnalyticSegmentPair = { analyticUnit: AnalyticUnit, segment: AnalyticSegment };
export type AnalyticSegmentsSearcher = (point: number, rangeDist: number) => AnalyticSegmentPair[]; export type AnalyticSegmentsSearcher = (point: number, rangeDist: number) => AnalyticSegmentPair[];
export type AnalyticUnitId = string; export type AnalyticUnitId = string;
export class AnalyticSegment extends Segment { export class AnalyticSegment extends Segment {
constructor(public labeled: boolean, id: SegmentId, from: number, to: number) { constructor(public labeled: boolean, id: SegmentId, from: number, to: number, public deleted = false) {
super(id, from, to); super(id, from, to);
if(!_.isBoolean(labeled)) { if(!_.isBoolean(labeled)) {
throw new Error('labeled value is not boolean'); throw new Error('labeled value is not boolean');
@ -85,7 +85,11 @@ export class AnalyticUnit {
} }
removeSegmentsInRange(from: number, to: number): AnalyticSegment[] { removeSegmentsInRange(from: number, to: number): AnalyticSegment[] {
return this._segmentSet.removeInRange(from, to); let deletedSegments = this._segmentSet.removeInRange(from, to);
deletedSegments.forEach(s => {
s.deleted = true;
});
return deletedSegments;
} }
get segments(): SegmentsSet<AnalyticSegment> { return this._segmentSet; } get segments(): SegmentsSet<AnalyticSegment> { return this._segmentSet; }

1
src/module.ts

@ -576,6 +576,7 @@ class GraphCtrl extends MetricsPanelCtrl {
return; return;
} }
this.analyticsController.toggleDeleteMode(); this.analyticsController.toggleDeleteMode();
this.refresh();
} }
onAnomalyAlertChange(anomalyType: AnalyticUnit) { onAnomalyAlertChange(anomalyType: AnalyticUnit) {

10
src/services/analytic_service.ts

@ -42,15 +42,15 @@ export class AnalyticService {
): Promise<SegmentId[]> { ): Promise<SegmentId[]> {
const getJSONs = (segs: SegmentsSet<Segment>) => segs.getSegments().map(segment => ({ const getJSONs = (segs: SegmentsSet<Segment>) => segs.getSegments().map(segment => ({
"from": segment.from, from: segment.from,
"to": segment.to to: segment.to
})); }));
var payload = { var payload = {
id, id,
addedSegments: getJSONs(addedSegments), addedSegments: getJSONs(addedSegments),
removedSegments: removedSegments.getSegments().map(s => s.id) removedSegments: removedSegments.getSegments().map(s => s.id)
} };
var data = await this._backendSrv.patch(this._backendURL + '/segments', payload); var data = await this._backendSrv.patch(this._backendURL + '/segments', payload);
if(data.addedIds === undefined) { if(data.addedIds === undefined) {
@ -75,8 +75,8 @@ export class AnalyticService {
if(data.segments === undefined) { if(data.segments === undefined) {
throw new Error('Server didn`t return segments array'); throw new Error('Server didn`t return segments array');
} }
var segments = data.segments as { id: SegmentId, from: number, to: number, labeled: boolean }[]; var segments = data.segments as { id: SegmentId, from: number, to: number, labeled: boolean, deleted: boolean }[];
return segments.map(s => new AnalyticSegment(s.labeled, s.id, s.from, s.to)); return segments.map(s => new AnalyticSegment(s.labeled, s.id, s.from, s.to, s.deleted));
} }
async * getStatusGenerator(id: AnalyticUnitId, duration: number) { async * getStatusGenerator(id: AnalyticUnitId, duration: number) {

Loading…
Cancel
Save