From 6f9ac9245b1a4f35d65ab54fecc62df7cdd23411 Mon Sep 17 00:00:00 2001 From: rozetko Date: Tue, 18 Sep 2018 21:36:16 +0300 Subject: [PATCH] WIP Display anti-segments #66 (#67) * WIP * Render deleted segments and trash icon in tooltip --- src/controllers/analytic_controller.ts | 26 +++++++++++++++++++----- src/graph_tooltip.ts | 28 +++++++++++++++++--------- src/models/analytic_unit.ts | 10 ++++++--- src/module.ts | 1 + src/services/analytic_service.ts | 10 ++++----- 5 files changed, 53 insertions(+), 22 deletions(-) diff --git a/src/controllers/analytic_controller.ts b/src/controllers/analytic_controller.ts index 0ba38e5..7e9272c 100644 --- a/src/controllers/analytic_controller.ts +++ b/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_DARK = 'white'; const LABELED_SEGMENT_BORDER_COLOR = 'black'; +const DELETED_SEGMENT_FILL_COLOR = 'black'; +const DELETED_SEGMENT_BORDER_COLOR = 'black'; export class AnalyticController { @@ -59,7 +61,7 @@ export class AnalyticController { this._analyticUnitsSet.items.forEach(at => { var segs = at.segments.findSegments(point, rangeDist); segs.forEach(s => { - result.push({ anomalyType: at, segment: s }); + result.push({ analyticUnit: at, segment: s }); }) }) return result; @@ -125,7 +127,8 @@ export class AnalyticController { var newIds = await this._saveLabelingData(); this._labelingDataAddedSegments.getSegments().forEach((s, i) => { this.labelingAnomaly.segments.updateId(s.id, newIds[i]); - }) + }); + this.labelingAnomaly.saving = false; var anomaly = this.labelingAnomaly; @@ -138,7 +141,7 @@ export class AnalyticController { this.labelingAnomaly.segments.remove(s.id); }); this._labelingDataDeletedSegments.getSegments().forEach(s => { - this.labelingAnomaly.segments.addSegment(s); + s.deleted = false; }); this.dropLabeling(); } @@ -254,18 +257,32 @@ export class AnalyticController { let labeledSegmentBorderColor = tinycolor(LABELED_SEGMENT_BORDER_COLOR).toRgbString(); 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 => { let segmentBorderColor; + let segmentFillColor = fillColor; + if(s.labeled) { segmentBorderColor = labeledSegmentBorderColor; } else { segmentBorderColor = borderColor; } + if(this.labelingDeleteMode) { + if(s.deleted) { + segmentBorderColor = deletedSegmentBorderColor; + segmentFillColor = deletedSegmentFillColor; + } + } + var expanded = s.expandDist(rangeDist, 0.01); options.grid.markings.push({ xaxis: { from: expanded.from, to: expanded.to }, - color: fillColor + color: segmentFillColor }); options.grid.markings.push({ xaxis: { from: expanded.from, to: expanded.from }, @@ -281,7 +298,6 @@ export class AnalyticController { } deleteLabelingAnomalySegmentsInRange(from: number, to: number) { - console.log('deleteLabelingAnomalySegmentsInRange was called') var allRemovedSegs = this.labelingAnomaly.removeSegmentsInRange(from, to); allRemovedSegs.forEach(s => { if(!this._labelingDataAddedSegments.has(s.id)) { diff --git a/src/graph_tooltip.ts b/src/graph_tooltip.ts index 2391662..2370651 100644 --- a/src/graph_tooltip.ts +++ b/src/graph_tooltip.ts @@ -10,7 +10,7 @@ export class GraphTooltip { private _lastItem = undefined; constructor( - private $elem: JQuery, private dashboard, + private $elem: JQuery, private dashboard, private scope, private getSeriesFn, private _anomalySegmentsSearcher: AnalyticSegmentsSearcher ) { @@ -53,7 +53,7 @@ export class GraphTooltip { } pos.pageX = this.$elem.offset().left + pointOffset.left; 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(); if (!isVisible) { this.clear(plot); @@ -148,7 +148,7 @@ export class GraphTooltip { } }; - + destroy() { this._visible = false; this.$tooltip.remove(); @@ -199,21 +199,31 @@ export class GraphTooltip { segments.forEach(s => { var from = this.dashboard.formatDate(s.segment.from, '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 += `
- - ${s.anomalyType.name}: + + ${s.analyticUnit.name}:
- + ${from} — ${to}
`; - - }); return result; } diff --git a/src/models/analytic_unit.ts b/src/models/analytic_unit.ts index 349029e..fd0fc90 100644 --- a/src/models/analytic_unit.ts +++ b/src/models/analytic_unit.ts @@ -8,13 +8,13 @@ import { ANALYTIC_UNIT_COLORS } from '../colors'; 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 AnalyticUnitId = string; 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); if(!_.isBoolean(labeled)) { throw new Error('labeled value is not boolean'); @@ -85,7 +85,11 @@ export class AnalyticUnit { } 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 { return this._segmentSet; } diff --git a/src/module.ts b/src/module.ts index f090d4a..26f3e1c 100644 --- a/src/module.ts +++ b/src/module.ts @@ -576,6 +576,7 @@ class GraphCtrl extends MetricsPanelCtrl { return; } this.analyticsController.toggleDeleteMode(); + this.refresh(); } onAnomalyAlertChange(anomalyType: AnalyticUnit) { diff --git a/src/services/analytic_service.ts b/src/services/analytic_service.ts index ad06f95..3784821 100644 --- a/src/services/analytic_service.ts +++ b/src/services/analytic_service.ts @@ -42,15 +42,15 @@ export class AnalyticService { ): Promise { const getJSONs = (segs: SegmentsSet) => segs.getSegments().map(segment => ({ - "from": segment.from, - "to": segment.to + from: segment.from, + to: segment.to })); var payload = { id, addedSegments: getJSONs(addedSegments), removedSegments: removedSegments.getSegments().map(s => s.id) - } + }; var data = await this._backendSrv.patch(this._backendURL + '/segments', payload); if(data.addedIds === undefined) { @@ -75,8 +75,8 @@ export class AnalyticService { if(data.segments === undefined) { throw new Error('Server didn`t return segments array'); } - var segments = data.segments as { id: SegmentId, from: number, to: number, labeled: boolean }[]; - return segments.map(s => new AnalyticSegment(s.labeled, s.id, s.from, s.to)); + 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, s.deleted)); } async * getStatusGenerator(id: AnalyticUnitId, duration: number) {