This is an automated email from the ASF dual-hosted git repository.

xhsun pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-pinot.git


The following commit(s) were added to refs/heads/master by this push:
     new 1e3e38c  [TE] frontend - harleyjj/alert-details - add basic forecast 
display capability to Alert Overview (#5236)
1e3e38c is described below

commit 1e3e38c645d969295e7d824f43cfa356ad671352
Author: Harley Jackson <[email protected]>
AuthorDate: Mon Apr 13 10:24:20 2020 -0700

    [TE] frontend - harleyjj/alert-details - add basic forecast display 
capability to Alert Overview (#5236)
---
 .../app/pods/components/alert-details/component.js | 66 ++++++++++++++++++---
 .../app/pods/components/alert-details/template.hbs | 11 ++++
 thirdeye/thirdeye-frontend/app/styles/app.scss     |  1 +
 .../app/styles/components/alert-details.scss       | 35 +++++++++++
 .../app/utils/manage-alert-utils.js                | 67 ++++++++++++++++++++--
 5 files changed, 167 insertions(+), 13 deletions(-)

diff --git 
a/thirdeye/thirdeye-frontend/app/pods/components/alert-details/component.js 
b/thirdeye/thirdeye-frontend/app/pods/components/alert-details/component.js
index 4cff2c6..c63c6fc 100644
--- a/thirdeye/thirdeye-frontend/app/pods/components/alert-details/component.js
+++ b/thirdeye/thirdeye-frontend/app/pods/components/alert-details/component.js
@@ -47,6 +47,7 @@ export default Component.extend({
   notifications: service('toast'),
   timeseries: null,
   analysisRange: [moment().subtract(2, 'day').startOf('day').valueOf(), 
moment().add(1, 'day').startOf('day').valueOf()],
+  displayRange: [moment().subtract(2, 'day').startOf('day').valueOf(), 
moment().add(1, 'day').startOf('day').valueOf()],
   isPendingData: false,
   colorMapping: colorMapping,
   zoom: {
@@ -346,8 +347,16 @@ export default Component.extend({
 
   axis: computed(
     'analysisRange',
+    'displayRange',
+    'selectedBaseline',
     function () {
-      const analysisRange = get(this, 'analysisRange');
+      const {
+        analysisRange,
+        displayRange,
+        selectedBaseline
+      } = this.getProperties('analysisRange', 'displayRange', 
'selectedBaseline');
+
+      const useRange = (selectedBaseline === 'predicted') ? displayRange : 
analysisRange;
 
       return {
         y: {
@@ -364,8 +373,8 @@ export default Component.extend({
         x: {
           type: 'timeseries',
           show: true,
-          min: analysisRange[0],
-          max: analysisRange[1],
+          min: useRange[0],
+          max: useRange[1],
           tick: {
             fit: false,
             format: (d) => {
@@ -444,21 +453,56 @@ export default Component.extend({
     }
   ),
 
+  isTrainingDisplayed: computed(
+    'analysisRange',
+    'displayRange',
+    'selectedBaseline',
+    function() {
+      const {
+        analysisRange, displayRange, selectedBaseline
+      } = this.getProperties('analysisRange', 'displayRange', 
'selectedBaseline');
+      return !(analysisRange[0] === displayRange[0] || selectedBaseline !== 
'predicted');
+    }
+  ),
+
+  trainingMessage: computed(
+    'analysisRange',
+    'displayRange',
+    'isTrainingMessage',
+    function() {
+      const {
+        analysisRange, displayRange
+      } = this.getProperties('analysisRange', 'displayRange');
+      return `Training + Forecast 
(${moment(displayRange[0]).format(TABLE_DATE_FORMAT)} - 
${moment(analysisRange[1]).format(TABLE_DATE_FORMAT)})`;
+    }
+  ),
+
   series: computed(
     'filteredAnomaliesOld.@each',
     'filteredAnomaliesCurrent.@each',
     'timeseries',
     'baseline',
-    'analysisRange',
     'selectedRule',
     'metricUrn',
+    'isTrainingDisplayed',
     function () {
       const {
-        filteredAnomaliesOld, filteredAnomaliesCurrent, timeseries, baseline, 
showRules, isPreviewMode
+        filteredAnomaliesOld, filteredAnomaliesCurrent, timeseries, baseline,
+        analysisRange, displayRange, showRules, isPreviewMode, 
isTrainingDisplayed
       } = getProperties(this, 'filteredAnomaliesOld', 
'filteredAnomaliesCurrent',
-        'timeseries', 'baseline', 'showRules', 'isPreviewMode');
+        'timeseries', 'baseline', 'analysisRange', 'displayRange', 'showRules',
+        'isPreviewMode', 'isTrainingDisplayed');
+
+      const region = !isTrainingDisplayed ? {} :
+        {
+          timestamps: [displayRange[0], analysisRange[0]],
+          values: [1, 1],
+          type: 'region',
+          axis: 'y2'
+        };
 
       const series = {};
+      series['training-region'] = region;
       // Should be displayed in Create Mode of Preview with one set of 
anomalies
       let anomaliesCurrentLabel = 'Current Settings Anomalies';
       let anomaliesOldLabel = 'Current Anomalies';
@@ -783,7 +827,7 @@ export default Component.extend({
         uiDateFormat: UI_DATE_FORMAT,
         activeRangeStart: moment(startDate).format(DISPLAY_DATE_FORMAT),
         activeRangeEnd: moment(endDate).format(DISPLAY_DATE_FORMAT),
-        timeRangeOptions: setUpTimeRangeOptions(TIME_RANGE_OPTIONS, duration),
+        timeRangeOptions: setUpTimeRangeOptions(TIME_RANGE_OPTIONS, duration, 
!this.get('isPreviewMode')),
         timePickerIncrement: TIME_PICKER_INCREMENT,
         predefinedRanges
       };
@@ -886,6 +930,7 @@ export default Component.extend({
     if (!isPreviewMode) {
       this.setProperties({
         analysisRange: [moment().subtract(timeWindowSize, 
'milliseconds').startOf('day').valueOf(), moment().add(1, 
'day').startOf('day').valueOf()],
+        displayRange: [moment().subtract(timeWindowSize, 
'milliseconds').startOf('day').valueOf(), moment().add(1, 
'day').startOf('day').valueOf()],
         duration: (timeWindowSize === 172800000) ? '48h' : 'custom',
         selectedDimension: 'Choose a dimension',
         // For now, we will only show predicted and bounds on daily and 
minutely metrics with no dimensions, for the Alert Overview page
@@ -898,6 +943,7 @@ export default Component.extend({
     } else {
       this.setProperties({
         analysisRange: [moment().subtract(timeWindowSize, 
'milliseconds').startOf('day').valueOf(), moment().add(1, 
'day').startOf('day').valueOf()],
+        displayRange: [moment().subtract(timeWindowSize, 
'milliseconds').startOf('day').valueOf(), moment().add(1, 
'day').startOf('day').valueOf()],
         duration: 'custom',
         selectedBaseline: 'predicted'
       });
@@ -1120,7 +1166,8 @@ export default Component.extend({
           this.setProperties({
             timeseries: seriesSet.predictedTimeSeries,
             baseline: seriesSet.predictedTimeSeries,
-            isLoadingTimeSeries: false
+            isLoadingTimeSeries: false,
+            displayRange: [seriesSet.predictedTimeSeries.timestamp[0] || 
analysisRange[0], analysisRange[1]]
           });
         } else {
           const urlBaseline = 
`/rootcause/metric/timeseries?urn=${metricUrn}&start=${analysisRange[0]}&end=${analysisRange[1]}&offset=${selectedBaseline}&timezone=${timeZone}`;
@@ -1130,7 +1177,8 @@ export default Component.extend({
               this.setProperties({
                 timeseries: seriesSet.predictedTimeSeries,
                 baseline: res,
-                isLoadingTimeSeries: false
+                isLoadingTimeSeries: false,
+                displayRange: [seriesSet.predictedTimeSeries.timestamp[0] || 
analysisRange[0], analysisRange[1]]
               });
             });
         }
diff --git 
a/thirdeye/thirdeye-frontend/app/pods/components/alert-details/template.hbs 
b/thirdeye/thirdeye-frontend/app/pods/components/alert-details/template.hbs
index 5c9aaab..7b1982f 100644
--- a/thirdeye/thirdeye-frontend/app/pods/components/alert-details/template.hbs
+++ b/thirdeye/thirdeye-frontend/app/pods/components/alert-details/template.hbs
@@ -210,6 +210,17 @@
               {{/if}}
             </div>
 
+            {{#if isTrainingDisplayed}}
+              <div class="col-xs-12 no-padding">
+                  <div class="alert-details-msg-forecast">
+                    <p>{{material-design-icon
+                      name='error-outline'
+                    }} {{trainingMessage}}
+                    </p>
+                  </div>
+              </div>
+            {{/if}}
+
             {{!-- Missing anomaly modal --}}
             {{#te-modal
               cancelButtonText="Cancel"
diff --git a/thirdeye/thirdeye-frontend/app/styles/app.scss 
b/thirdeye/thirdeye-frontend/app/styles/app.scss
index 7139ba0..1c470dd 100644
--- a/thirdeye/thirdeye-frontend/app/styles/app.scss
+++ b/thirdeye/thirdeye-frontend/app/styles/app.scss
@@ -31,6 +31,7 @@ body {
 @import 'wrapper/styles';
 
 // Components
+@import 'components/alert-details';
 @import 'components/anomaly-id';
 @import 'components/anomaly-graph';
 @import 'components/te-navbar';
diff --git 
a/thirdeye/thirdeye-frontend/app/styles/components/alert-details.scss 
b/thirdeye/thirdeye-frontend/app/styles/components/alert-details.scss
new file mode 100644
index 0000000..5ec68b7
--- /dev/null
+++ b/thirdeye/thirdeye-frontend/app/styles/components/alert-details.scss
@@ -0,0 +1,35 @@
+.alert-details {
+  .mdi-error-outline {
+    width: 19px;
+
+    &::before {
+      font-size: 16px;
+    }
+  }
+
+  .alert-details-msg-forecast {
+    color: grey;
+
+    &__icon {
+      font-size: 20px;
+      &--error {
+        padding-right: 5px;
+      }
+    }
+
+    &__tooltip-link {
+      text-decoration: underline;
+
+      &:hover {
+        cursor: pointer;
+      }
+    }
+  }
+
+  .col-xs-12 {
+    &.no-padding {
+      padding-left: 0px;
+      padding-right: 0px;
+    }
+  }
+}
diff --git a/thirdeye/thirdeye-frontend/app/utils/manage-alert-utils.js 
b/thirdeye/thirdeye-frontend/app/utils/manage-alert-utils.js
index 24bdf4d..c61e672 100644
--- a/thirdeye/thirdeye-frontend/app/utils/manage-alert-utils.js
+++ b/thirdeye/thirdeye-frontend/app/utils/manage-alert-utils.js
@@ -141,8 +141,8 @@ export function enhanceAnomalies(rawAnomalies, 
severityScores) {
  * @param {String} duration - the selected time span that is default
  * @return {Array}
  */
-export function setUpTimeRangeOptions(datesKeys, duration) {
-  const newRangeArr = [];
+export function setUpTimeRangeOptions(datesKeys, duration, forecast=false) {
+  let newRangeArr = [];
 
   const defaultCustomRange = {
     name: 'Custom',
@@ -150,11 +150,20 @@ export function setUpTimeRangeOptions(datesKeys, 
duration) {
     start: null,
     isActive: !datesKeys.includes(duration)
   };
+  newRangeArr = forecast ? futureAndPast(datesKeys, duration, newRangeArr) : 
pastOnly(datesKeys, duration, newRangeArr);
+  newRangeArr.push(defaultCustomRange);
+  return newRangeArr;
+}
 
+/**
+ * Helper function for setUpTimeRangeOptions when returning past ranges only
+ * @returns {Array}
+ */
+function pastOnly(datesKeys, duration, newRangeArr) {
   const dateKeyMap = new Map(
     [
       [ '1m', ['Last 30 Days', 1, 'month'] ],
-      [ '3m', ['3 Months', 3, 'month'] ],
+      [ '3m', ['Last 3 Months', 3, 'month'] ],
       [ '2w', ['Last 2 Weeks', 2, 'week'] ],
       [ '1w', ['Last Week', 1, 'week'] ],
       [ '2d', ['Yesterday', 2, 'day'] ],
@@ -193,8 +202,58 @@ export function setUpTimeRangeOptions(datesKeys, duration) 
{
     const isActive = duration === value;
     newRangeArr.push({ name: label, value, start, end, isActive });
   });
+  return newRangeArr;
+}
 
-  newRangeArr.push(defaultCustomRange);
+/**
+ * Helper function for setUpTimeRangeOptions when returning past and future 
options
+ * @returns {Array}
+ */
+function futureAndPast(datesKeys, duration, newRangeArr) {
+  const dateKeyMap = new Map(
+    [
+      [ '1m', ['Next 30 Days', 1, 'month'] ],
+      [ '3m', ['Next 3 Months', 3, 'month'] ],
+      [ '2w', ['Next 2 Weeks', 2, 'week'] ],
+      [ '1w', ['Next Week', 1, 'week'] ],
+      [ '2d', ['Tomorrow', 2, 'day'] ],
+      [ '1d', ['Next 24 Hours', 24, 'hour'] ],
+      [ '48h', ['Next 48 Hours', 48, 'hour'] ],
+      [ 'today', ['Today'] ]
+    ]);
+
+  newRangeArr = pastOnly(datesKeys, duration, newRangeArr);
+
+  datesKeys.forEach((value) => {
+    const currVal = dateKeyMap.get(value);
+    const label = currVal[0];
+    let start;
+    let end;
+    // overrides map above
+    switch(label) {
+      case 'Today':
+        start = moment().startOf('day');
+        end = start.add(1, 'days');
+        break;
+      case 'Tomorrow':
+        start = moment().startOf('day');
+        end = moment().add(2, 'day').startOf('day');
+        break;
+      case 'Next 24 Hours':
+        start = moment().startOf('hour');
+        end = moment().add(24, 'hour').startOf('hour');
+        break;
+      case 'Next 48 Hours':
+        start = moment().startOf('hour');
+        end = moment().add(48, 'hour').startOf('hour');
+        break;
+      default:
+        start = moment().startOf('day');
+        end = moment().add(currVal[1], currVal[2]).startOf('day');
+    }
+    const isActive = duration === value;
+    newRangeArr.push({ name: label, value, start, end, isActive });
+  });
   return newRangeArr;
 }
 


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to