This is an automated email from the ASF dual-hosted git repository. jihao 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 ca8545b [TE] frontend - abachuk/alert-details-ui-tweaks - formatting alert header (#6210) ca8545b is described below commit ca8545b29218e79910a35cd592a547d17cb945d3 Author: Alex Bachuk <a...@bachuk.com> AuthorDate: Thu Nov 5 16:40:50 2020 -0500 [TE] frontend - abachuk/alert-details-ui-tweaks - formatting alert header (#6210) * refactoring alert details breakdown to <dl> * styling edit and share buttons * adding html title tags, header layout change * minor changes, cleanup * configuring the linter with single quote formatting * cleanup eslintrc * fixing unclosed string * removing single quote eslint rule to not break some unit tests until we standardize the linters * fixing indent issue before in the class name authored-by: Alex Bachuk <abac...@linkedin.com> --- thirdeye/thirdeye-frontend/.eslintrc.js | 44 +++-- .../self-serve-alert-yaml-details/template.hbs | 148 +++++++-------- .../pods/components/timeseries-chart/component.js | 205 ++++++++++++++------- .../app/pods/home/index/template.hbs | 127 ++++++------- .../app/pods/manage/explore/template.hbs | 25 +-- .../app/styles/components/button.scss | 34 ++-- .../app/styles/shared/_styles.scss | 40 ++-- .../share-custom-template/component-test.js | 34 ++-- .../thirdeye-frontend/tests/utils/constants.js | 4 +- 9 files changed, 358 insertions(+), 303 deletions(-) diff --git a/thirdeye/thirdeye-frontend/.eslintrc.js b/thirdeye/thirdeye-frontend/.eslintrc.js index 1c01456..d086263 100644 --- a/thirdeye/thirdeye-frontend/.eslintrc.js +++ b/thirdeye/thirdeye-frontend/.eslintrc.js @@ -1,36 +1,34 @@ module.exports = { globals: { - server: true, + server: true }, root: true, parserOptions: { ecmaVersion: 2018, - sourceType: 'module', + sourceType: 'module' }, - plugins: [ - 'ember' - ], - extends: [ - 'eslint:recommended', - 'plugin:ember/recommended' - ], + plugins: ['ember'], + extends: ['eslint:recommended', 'plugin:ember/recommended'], env: { browser: true, es6: true }, rules: { - "eol-last": ["warn", "always"], - "indent": ["warn", 2, { "SwitchCase": 1 }], - "space-in-parens": ["warn", "never"], - "no-trailing-spaces": ["warn"], - "comma-dangle": ["warn", "never"], - "comma-spacing": ["warn", { "before": false, "after": true }], - "semi": ["warn", "always"], - "comma-style": ["warn", "last"], - "no-unused-vars": ["warn", { "vars": "all", "args": "after-used", "ignoreRestSiblings": false }], - // TODO: fix all warnings and change rules back to "error" - "ember/avoid-leaking-state-in-ember-objects": ["warn"], - "ember/no-attrs-in-components": ["warn"] + 'eol-last': ['warn', 'always'], + indent: ['warn', 2, { SwitchCase: 1 }], + 'space-in-parens': ['warn', 'never'], + 'no-trailing-spaces': ['warn'], + 'comma-dangle': ['warn', 'never'], + 'comma-spacing': ['warn', { before: false, after: true }], + semi: ['warn', 'always'], + 'comma-style': ['warn', 'last'], + 'no-unused-vars': [ + 'warn', + { vars: 'all', args: 'after-used', ignoreRestSiblings: false }, + ], + // TODO: fix all warnings and change rules back to 'error' + 'ember/avoid-leaking-state-in-ember-objects': ['warn'], + 'ember/no-attrs-in-components': ['warn'] }, overrides: [ // node files @@ -58,6 +56,6 @@ module.exports = { env: { embertest: true } - } - ] + }, + ], }; diff --git a/thirdeye/thirdeye-frontend/app/pods/components/self-serve-alert-yaml-details/template.hbs b/thirdeye/thirdeye-frontend/app/pods/components/self-serve-alert-yaml-details/template.hbs index 7a92159..9a62b22 100644 --- a/thirdeye/thirdeye-frontend/app/pods/components/self-serve-alert-yaml-details/template.hbs +++ b/thirdeye/thirdeye-frontend/app/pods/components/self-serve-alert-yaml-details/template.hbs @@ -1,103 +1,79 @@ -<div class="te-search-results__header"> - <div class="te-search-results__title-group"> +<div class="te-search-results__header row"> + <div class="te-search-results__title-group col-md-10 col-xs-9"> <div class="te-search-results__title"> - <span title={{alertData.detectionName}}>{{alertData.detectionName}}</span> + <h3 class="te-search-results__title-name" title={{alertData.detectionName}}>{{alertData.detectionName}}</h3> {{#if (eq displayMode "list")}} - {{#link-to "manage.explore" alertData.id}} - <div class="te-search-results__title-name" title={{alertData.detectionName}}>{{alertData.detectionName}}</div> - {{/link-to}} + {{#link-to "manage.explore" alertData.id}} + <div class="te-search-results__title-name" title={{alertData.detectionName}}>{{alertData.detectionName}}</div> + {{/link-to}} {{/if}} - <h4 class="te-alert-page__subtitle">{{alertData.description}}</h4> {{#if isLoadError}} - <div class="te-search-results__tag {{if (eq displayMode "list") "te-search-results__tag--list"}} {{if alertData.isActive "te-search-results__tag--active"}}"> - Error - </div> + <div + class="te-search-results__tag {{if (eq displayMode "list") "te-search-results__tag--list"}} {{if alertData.isActive "te-search-results__tag--active"}}"> + Error + </div> {{else}} - <div class="te-search-results__tag {{if (eq displayMode "list") "te-search-results__tag--list"}} {{if alertData.isActive "te-search-results__tag--active"}}"> - {{if alertData.isActive "Active" "Inactive"}} - </div> - {{#x-toggle + <div + class="te-search-results__tag {{if (eq displayMode "list") "te-search-results__tag--list"}} {{if alertData.isActive "te-search-results__tag--active"}}"> + {{if alertData.isActive "Active" "Inactive"}} + </div> + {{#x-toggle value=alertData.isActive classNames="te-toggle te-toggle--form te-toggle--left report-toggle activation-toggle" theme="ios" id="active-toggle" showLabels=false name="activeToggle" - onToggle=(action "toggleAlertActivation") - as |toggle|}} - {{toggle.switch theme='ios' onLabel='diff on' offLabel='diff off'}} - {{/x-toggle}} + onToggle=(action "toggleAlertActivation") + as |toggle|}} + {{toggle.switch theme='ios' onLabel='diff on' offLabel='diff off'}} + {{/x-toggle}} {{/if}} </div> </div> - {{yield}} + <div class="col-md-2 col-xs-3"> + <div class="pull-right">{{yield}}</div> + </div> </div> - +<h4 class="te-alert-page__subtitle">{{alertData.description}}</h4> {{#if (not isLoadError)}} - <ul class="te-search-results__list te-search-results__list--details-block row"> - <div class="col-xs-12 col-sm-5"> - <li class="te-search-results__row"> - <div class="te-search-results__option te-search-results__option--{{modeSubClass}} te-search-results__option--left">Metric</div> - <div class="te-search-results__value{{valueClassSuffix}}" title={{alertData.metric}}>{{alertData.metric}}</div> - </li> - <li class="te-search-results__row"> - <div class="te-search-results__option te-search-results__option--{{modeSubClass}} te-search-results__option--left">Dataset</div> - <div class="te-search-results__value{{valueClassSuffix}}" title={{alertData.dataset}}> - <span class="{{unless alertData.dataset 'te-search-results__prop--missing' 'te-search-results__prop'}}"> - {{if alertData.dataset alertData.dataset 'N/A'}} - </span> - </div> - </li> - <li class="te-search-results__row"> - <div class="te-search-results__option te-search-results__option--{{modeSubClass}} te-search-results__option--left">Filtered By</div> - <div class="te-search-results__value{{valueClassSuffix}}" title={{alertData.filters}}> - <span class="{{unless alertData.filters 'te-search-results__prop--missing' 'te-search-results__prop'}}"> - {{if alertData.filters alertData.filters 'N/A'}} - </span> - </div> - </li> - <li class="te-search-results__row"> - <div class="te-search-results__option te-search-results__option--{{modeSubClass}} te-search-results__option--left">Breakdown By</div> - <div class="te-search-results__value{{valueClassSuffix}}" title={{alertData.dimensionExploration}}> - <span class="{{unless alertData.dimensionExploration 'te-search-results__prop--missing' 'te-search-results__prop'}}"> - {{if alertData.dimensionExploration alertData.dimensionExploration 'N/A'}} - </span> - </div> - </li> - </div> - <div class="col-xs-12 col-sm-7"> - <li class="te-search-results__row"> - <div class="te-search-results__option te-search-results__option--{{modeSubClass}} te-search-results__option--left">Created By</div> - <div class="te-search-results__value{{valueClassSuffix}}" title={{alertData.createdBy}}> - <span class="{{unless alertData.createdBy 'te-search-results__prop--missing' 'te-search-results__prop'}}"> - {{if alertData.createdBy alertData.createdBy 'N/A'}} - </span> - </div> - </li> - <li class="te-search-results__row"> - <div class="te-search-results__option te-search-results__option--{{modeSubClass}} te-search-results__option--left">Updated By</div> - <div class="te-search-results__value{{valueClassSuffix}}" title={{alertData.updatedBy}}> - <span class="{{unless alertData.updatedBy 'te-search-results__prop--missing' 'te-search-results__prop'}}"> - {{if alertData.updatedBy alertData.updatedBy 'N/A'}} - </span> - </div> - </li> - <li class="te-search-results__row"> - <div class="te-search-results__option te-search-results__option--{{modeSubClass}} te-search-results__option--left">Last detection</div> - <div class="te-search-results__value{{valueClassSuffix}}" title={{alertData.lastDetectionTime}}> - <span class="{{unless alertData.lastDetectionTime 'te-search-results__prop--missing' 'te-search-results__prop'}}"> - {{if alertData.lastDetectionTime alertData.lastDetectionTime 'N/A'}} - </span> - </div> - </li> - <li class="te-search-results__row"> - <div class="te-search-results__option te-search-results__option--{{modeSubClass}} te-search-results__option--left">Subscribed Groups</div> - <div class="te-search-results__value{{valueClassSuffix}}" title={{subscribedGroups}}> - <span class="{{unless subscribedGroups 'te-search-results__prop--missing' 'te-search-results__prop'}}"> - {{if subscribedGroups subscribedGroups 'N/A'}} - </span> - </div> - </li> - </div> - </ul> +<div class="te-alert-detail-breakdown row"> + <dl class="col-xs-12 col-sm-5 row"> + <dt class="col-md-4">Metric</dt> + <dd class="col-md-8 te-search-results__value{{valueClassSuffix}}" title={{alertData.metric}}>{{alertData.metric}} + </dd> + + <dt class="col-md-4">Dataset</dt> + <dd class="col-md-8 te-search-results__value{{valueClassSuffix}}" title={{alertData.dataset}}> + {{if alertData.dataset alertData.dataset 'N/A'}} + </dd> + + <dt class="col-md-4">Filtered By</dt> + <dd class="col-md-8 te-search-results__value{{valueClassSuffix}}" title={{alertData.filters}}> + {{if alertData.filters alertData.filters 'N/A'}}</dd> + + <dt class="col-md-4">Breakdown By</dt> + <dd class="col-md-8 te-search-results__value{{valueClassSuffix}}" title={{alertData.dimensionExploration}}> + {{if alertData.dimensionExploration alertData.dimensionExploration 'N/A'}}</dd> + </dl> + + <dl class="col-xs-12 col-sm-5 row"> + <dt class="col-md-4">Created By</dt> + <dd class="col-md-8 te-search-results__value{{valueClassSuffix}}" title={{alertData.createdBy}}> + {{if alertData.createdBy alertData.createdBy 'N/A'}}</dd> + + <dt class="col-md-4">Updated By</dt> + <dd class="col-md-8 te-search-results__value{{valueClassSuffix}}" title={{alertData.updatedBy}}> + {{if alertData.updatedBy alertData.updatedBy 'N/A'}}</dd> + + <dt class="col-md-4">Last detection</dt> + <dd class="col-md-8 te-search-results__value{{valueClassSuffix}}" title={{alertData.lastDetectionTime}}> + {{if alertData.lastDetectionTime alertData.lastDetectionTime 'N/A'}}</dd> + + <dt class="col-md-4">Subscribed Groups</dt> + <dd class="col-md-8 te-search-results__value{{valueClassSuffix}}" title={{subscribedGroups}}> + {{if subscribedGroups subscribedGroups 'N/A'}} + </dd> + </dl> +</div> {{/if}} diff --git a/thirdeye/thirdeye-frontend/app/pods/components/timeseries-chart/component.js b/thirdeye/thirdeye-frontend/app/pods/components/timeseries-chart/component.js index 574f1a9..337a692 100644 --- a/thirdeye/thirdeye-frontend/app/pods/components/timeseries-chart/component.js +++ b/thirdeye/thirdeye-frontend/app/pods/components/timeseries-chart/component.js @@ -86,20 +86,24 @@ export default Component.extend({ pink: '#FF1B90' }, - subchart: { // on init only + subchart: { + // on init only show: true }, - zoom: { // on init only + zoom: { + // on init only enabled: true, onzoom: null }, - point: { // on init only + point: { + // on init only show: true }, - line: { // on init only + line: { + // on init only connectNull: false }, @@ -109,18 +113,27 @@ export default Component.extend({ const cache = this.get('_seriesCache') || {}; const series = this.get('series') || {}; const colorMapping = this.get('colorMapping'); - const { axis, legend, tooltip, focusedIds } = this.getProperties('axis', 'legend', 'tooltip', 'focusedIds'); + const { axis, legend, tooltip, focusedIds } = this.getProperties( + 'axis', + 'legend', + 'tooltip', + 'focusedIds' + ); const seriesKeys = Object.keys(series).sort(); - const addedKeys = seriesKeys.filter(sid => !cache[sid]); - const changedKeys = seriesKeys.filter(sid => cache[sid] && !_.isEqual(cache[sid], series[sid])); - const deletedKeys = Object.keys(cache).filter(sid => !series[sid]); - const regionKeys = seriesKeys.filter(sid => series[sid] && series[sid].type == 'region'); + const addedKeys = seriesKeys.filter((sid) => !cache[sid]); + const changedKeys = seriesKeys.filter( + (sid) => cache[sid] && !_.isEqual(cache[sid], series[sid]) + ); + const deletedKeys = Object.keys(cache).filter((sid) => !series[sid]); + const regionKeys = seriesKeys.filter( + (sid) => series[sid] && series[sid].type == 'region' + ); // keys containing '-region' should not appear in the graph legend. - const noLegendKeys = seriesKeys.filter(sid => (sid.includes('-region'))); + const noLegendKeys = seriesKeys.filter((sid) => sid.includes('-region')); - const regions = regionKeys.map(sid => { + const regions = regionKeys.map((sid) => { const t = series[sid].timestamps; let region = { start: t[0], end: t[t.length - 1] }; @@ -132,42 +145,72 @@ export default Component.extend({ }); const unloadKeys = deletedKeys.concat(noLegendKeys); - const unload = unloadKeys.concat(unloadKeys.map(sid => `${sid}-timestamps`)); + const unload = unloadKeys.concat( + unloadKeys.map((sid) => `${sid}-timestamps`) + ); - const loadKeys = addedKeys.concat(changedKeys).filter(sid => !noLegendKeys.includes(sid)); + const loadKeys = addedKeys + .concat(changedKeys) + .filter((sid) => !noLegendKeys.includes(sid)); const xs = {}; - loadKeys.forEach(sid => xs[sid] = `${sid}-timestamps`); + loadKeys.forEach((sid) => (xs[sid] = `${sid}-timestamps`)); - const values = loadKeys.map(sid => [sid].concat(series[sid].values)); + const values = loadKeys.map((sid) => [sid].concat(series[sid].values)); - const timestamps = loadKeys.map(sid => [`${sid}-timestamps`].concat(series[sid].timestamps)); + const timestamps = loadKeys.map((sid) => + [`${sid}-timestamps`].concat(series[sid].timestamps) + ); const columns = values.concat(timestamps); const colors = {}; - loadKeys.filter(sid => series[sid].color).forEach(sid => colors[sid] = colorMapping[series[sid].color]); + loadKeys + .filter((sid) => series[sid].color) + .forEach((sid) => (colors[sid] = colorMapping[series[sid].color])); const types = {}; - loadKeys.filter(sid => series[sid].type).forEach(sid => types[sid] = series[sid].type); + loadKeys + .filter((sid) => series[sid].type) + .forEach((sid) => (types[sid] = series[sid].type)); const axes = {}; - loadKeys.filter(sid => 'axis' in series[sid]).forEach(sid => axes[sid] = series[sid].axis); + loadKeys + .filter((sid) => 'axis' in series[sid]) + .forEach((sid) => (axes[sid] = series[sid].axis)); // keep the lower bound line in graph but remove in from the legend legend.hide = ['lowerBound', 'old-anomaly-edges', 'new-anomaly-edges']; - const config = { unload, xs, columns, types, regions, tooltip, focusedIds, colors, axis, axes, legend }; + const config = { + unload, + xs, + columns, + types, + regions, + tooltip, + focusedIds, + colors, + axis, + axes, + legend + }; return config; }, _makeAxisRange(axis) { const range = { min: {}, max: {} }; - Object.keys(axis).filter(key => 'min' in axis[key]).forEach(key => range['min'][key] = axis[key]['min']); - Object.keys(axis).filter(key => 'max' in axis[key]).forEach(key => range['max'][key] = axis[key]['max']); + Object.keys(axis) + .filter((key) => 'min' in axis[key]) + .forEach((key) => (range['min'][key] = axis[key]['min'])); + Object.keys(axis) + .filter((key) => 'max' in axis[key]) + .forEach((key) => (range['max'][key] = axis[key]['max'])); return range; }, _updateCache() { // debounce: do not trigger if chart object already destroyed - if (this.isDestroyed) { return; } + if (this.isDestroyed) { + return; + } const series = this.get('series') || {}; this.set('_seriesCache', _.cloneDeep(series)); @@ -176,7 +219,7 @@ export default Component.extend({ /** * Updates the focused entity on the chart */ - _updateFocusedIds: function() { + _updateFocusedIds: function () { const ids = this.get('focusedIds'); if (!_.isEmpty(ids)) { @@ -213,69 +256,91 @@ export default Component.extend({ this._updateCache(); }, - _shadeBounds(){ + _shadeBounds() { const parentElement = this.api.internal.config.bindto; - d3.select(parentElement).select(".confidence-bounds").remove(); - d3.select(parentElement).select(".sub-confidence-bounds").remove(); - d3.select(parentElement).select('.timeseries-graph__slider-circle').remove(); - d3.select(parentElement).selectAll('timeseries-graph__slider-line').remove(); + d3.select(parentElement).select('.confidence-bounds').remove(); + d3.select(parentElement).select('.sub-confidence-bounds').remove(); + d3.select(parentElement) + .select('.timeseries-graph__slider-circle') + .remove(); + d3.select(parentElement) + .selectAll('timeseries-graph__slider-line') + .remove(); const chart = this.api; - if (chart && chart.legend && chart.internal && chart.internal.data && chart.internal.data.targets) { + if ( + chart && + chart.legend && + chart.internal && + chart.internal.data && + chart.internal.data.targets + ) { if (chart.internal.data.targets.length > 24) { chart.legend.hide(); } } // key is 'Upper and lower bound' because we delete the lowerBound key for the legend. - if(chart && chart.internal && chart.internal.data && chart.internal.data.xs && Array.isArray(chart.internal.data.xs['Upper and lower bound'])) { - const indices = d3.range(chart.internal.data.xs['Upper and lower bound'].length); + if ( + chart && + chart.internal && + chart.internal.data && + chart.internal.data.xs && + Array.isArray(chart.internal.data.xs['Upper and lower bound']) + ) { + const indices = d3.range( + chart.internal.data.xs['Upper and lower bound'].length + ); const yscale = chart.internal.y; const xscale = chart.internal.x; const yscaleSub = chart.internal.subY; const xscaleSub = chart.internal.subX; const xVals = chart.internal.data.xs['Upper and lower bound']; - let upperBoundVals = chart.internal.data.targets.find(target => { + let upperBoundVals = chart.internal.data.targets.find((target) => { return target.id === 'Upper and lower bound'; }); - let lowerBoundVals = chart.internal.data.targets.find(target => { + let lowerBoundVals = chart.internal.data.targets.find((target) => { return target.id === 'lowerBound'; }); if (upperBoundVals && lowerBoundVals) { - upperBoundVals = upperBoundVals.values.map(e => e.value); - lowerBoundVals = lowerBoundVals.values.map(e => e.value); + upperBoundVals = upperBoundVals.values.map((e) => e.value); + lowerBoundVals = lowerBoundVals.values.map((e) => e.value); // If all upper bound vals are null, we assume that there is only a lower bound - if (upperBoundVals.every(val => val === null)) { - let currentVals = chart.internal.data.targets.find(target => { + if (upperBoundVals.every((val) => val === null)) { + let currentVals = chart.internal.data.targets.find((target) => { return target.id === 'Current'; }); if (currentVals) { - currentVals = currentVals.values.map(e => e.value); + currentVals = currentVals.values.map((e) => e.value); const currentMax = Math.max(...currentVals); upperBoundVals = upperBoundVals.map(() => 2 * currentMax); } } - const area_main = d3.area() + const area_main = d3 + .area() .curve(d3.curveLinear) - .x(d => xscale(xVals[d])) - .y0(d => yscale(lowerBoundVals[d])) - .y1(d => yscale(upperBoundVals[d])); + .x((d) => xscale(xVals[d])) + .y0((d) => yscale(lowerBoundVals[d])) + .y1((d) => yscale(upperBoundVals[d])); - const area_sub = d3.area() + const area_sub = d3 + .area() .curve(d3.curveLinear) - .x(d => xscaleSub(xVals[d])) - .y0(d => yscaleSub(lowerBoundVals[d])) - .y1(d => yscaleSub(upperBoundVals[d])); + .x((d) => xscaleSub(xVals[d])) + .y0((d) => yscaleSub(lowerBoundVals[d])) + .y1((d) => yscaleSub(upperBoundVals[d])); let i = 0; const bothCharts = d3.select(parentElement).selectAll('.c3-chart-bars'); - bothCharts.each(function() { + bothCharts.each(function () { if (i === 0 && this) { - d3.select(this).insert('path') + d3.select(this) + .insert('path') .datum(indices) .attr('class', 'confidence-bounds') .attr('d', area_main); } else if (i === 1 && this) { - d3.select(this).insert('path') + d3.select(this) + .insert('path') .datum(indices) .attr('class', 'sub-confidence-bounds') .attr('d', area_sub); @@ -287,32 +352,36 @@ export default Component.extend({ // add resize buttons after shading bounds const resizeButtons = d3.selectAll('.resize'); - resizeButtons.append('circle') + resizeButtons + .append('circle') .attr('class', 'timeseries-graph__slider-circle') .attr('cx', 0) .attr('cy', 30) .attr('r', 10) .attr('fill', '#0091CA'); - resizeButtons.append('line') + resizeButtons + .append('line') .attr('class', 'timeseries-graph__slider-line') - .attr("x1", 0) - .attr("y1", 27) - .attr("x2", 0) - .attr("y2", 33); + .attr('x1', 0) + .attr('y1', 27) + .attr('x2', 0) + .attr('y2', 33); - resizeButtons.append('line') + resizeButtons + .append('line') .attr('class', 'timeseries-graph__slider-line') - .attr("x1", -5) - .attr("y1", 27) - .attr("x2", -5) - .attr("y2", 33); + .attr('x1', -5) + .attr('y1', 27) + .attr('x2', -5) + .attr('y2', 33); - resizeButtons.append('line') + resizeButtons + .append('line') .attr('class', 'timeseries-graph__slider-line') - .attr("x1", 5) - .attr("y1", 27) - .attr("x2", 5) - .attr("y2", 33); + .attr('x1', 5) + .attr('y1', 27) + .attr('x2', 5) + .attr('y2', 33); }, didUpdateAttrs() { @@ -327,7 +396,7 @@ export default Component.extend({ } }, - didRender(){ + didRender() { this._super(...arguments); later(() => { @@ -342,7 +411,7 @@ export default Component.extend({ */ notifyPhantomJS() { if (typeof window.callPhantom === 'function') { - window.callPhantom({message: 'ready'}); + window.callPhantom({ message: 'ready' }); } }, diff --git a/thirdeye/thirdeye-frontend/app/pods/home/index/template.hbs b/thirdeye/thirdeye-frontend/app/pods/home/index/template.hbs index 7fa2f59..be4ea77 100644 --- a/thirdeye/thirdeye-frontend/app/pods/home/index/template.hbs +++ b/thirdeye/thirdeye-frontend/app/pods/home/index/template.hbs @@ -11,29 +11,29 @@ selectAction=(action "onRangeSelection") }} {{#if appOrSubGroup}} - {{#link-to "home.share-dashboard" (query-params appName=appName subGroup=subGroup duration=duration startDate=startDate endDate=endDate feedbackType=feedbackType shareId=null) tagName="button" type="button" class="pull-right te-button te-button--outline"}} - Share - {{/link-to}} + {{#link-to "home.share-dashboard" (query-params appName=appName subGroup=subGroup duration=duration startDate=startDate endDate=endDate feedbackType=feedbackType shareId=null) tagName="button" type="button" class="btn pull-right te-button te-button--outline"}} + Share + {{/link-to}} {{/if}} </header> <article class="dashboard-container__body"> <section class="dashboard-container__application-header"> <div class="dashboard-container__application-or-subgroup"> - <strong>Anomalies filter by: </strong> + <strong>Anomalies filter by: </strong> {{#each anomaliesByOptions as |option|}} - <div class="dashboard-container__radio-button-item"> - {{#radio-button value=option groupValue=anomaliesBySelected changed=(action "onAnomaliesBy")}} - <span class="te-radio__option">{{option}}</span> - {{/radio-button}} - </div> + <div class="dashboard-container__radio-button-item"> + {{#radio-button value=option groupValue=anomaliesBySelected changed=(action "onAnomaliesBy")}} + <span class="te-radio__option">{{option}}</span> + {{/radio-button}} + </div> {{/each}} </div> {{#if byApplication}} - <div class="dashboard-container__application-header-dropdown"> - <label class="te-label te-label--small">Application</label> - {{#power-select + <div class="dashboard-container__application-header-dropdown"> + <label class="te-label te-label--small">Application</label> + {{#power-select options=sortedApplications selected=appNameSelected searchField="application" @@ -41,13 +41,13 @@ placeholder="Please pick an application" onchange=(action "selectApplication") as |app|}} - {{app.application}} - {{/power-select}} - </div> + {{app.application}} + {{/power-select}} + </div> {{else}} - <div class="dashboard-container__application-header-dropdown"> - <label class="te-label te-label--small">Subscription Group</label> - {{#power-select + <div class="dashboard-container__application-header-dropdown"> + <label class="te-label te-label--small">Subscription Group</label> + {{#power-select options=sortedSubscriptionGroups selected=subGroupSelected searchField="name" @@ -55,27 +55,27 @@ placeholder="Please pick a subscription group" onchange=(action "selectSubscriptionGroup") as |subGroup|}} - {{subGroup.name}} - {{/power-select}} - </div> + {{subGroup.name}} + {{/power-select}} + </div> {{/if}} <div> {{#if byApplication}} - <h3 class="dashboard-container__title">{{appName}}</h3> + <h3 class="dashboard-container__title">{{appName}}</h3> {{else}} - <h3 class="dashboard-container__title">{{subGroup}}</h3> + <h3 class="dashboard-container__title">{{subGroup}}</h3> {{/if}} </div> </section> - {{#if isLoading}} + {{#if isLoading}} <div class="dashboard-container__spinner-wrapper"> {{ember-spinner lines=30 radius=20 length=0 width=10 opacity=0 trail=75 color='blue'}} </div> - {{/if}} + {{/if}} - {{#if areAnomaliesCurrent}} + {{#if areAnomaliesCurrent}} <section> {{stats-cards stats=stats}} </section> @@ -93,34 +93,36 @@ onchange=(action "onFilterBy" feedbackType) as |feedbackType| }} - {{feedbackType}} + {{feedbackType}} {{/power-select}} <a class="pull-right thirdeye-link" {{action 'toggleAllAccordions'}}> {{#if toggleCollapsed}} - Expand all <i class="glyphicon glyphicon-menu-down"></i> + Expand all <i class="glyphicon glyphicon-menu-down"></i> {{else}} - Collapse all <i class="glyphicon glyphicon-menu-up"></i> + Collapse all <i class="glyphicon glyphicon-menu-up"></i> {{/if}} </a> </div> {{#bs-accordion as |accordion|}} - {{#each-in filteredAnomalyMapping as |metric humanizedEntityList|}} - {{#accordion.item value=metric as |aitem|}} - {{#aitem.title}} - <section class="dashboard-container__title">Metric: - <span>{{metric}} ({{humanizedEntityList.length}} {{if (gt humanizedEntityList.length 1) "anomalies" "anomaly"}})</span> - <span><i class="glyphicon glyphicon-menu-{{if toggleCollapsed "down" "up"}}"></i></span> - </section> - {{/aitem.title}} - {{#aitem.body collapsed=toggleCollapsed}} - {{#if isReportAnomalyEnabled}} - <div class="pull-left"> - <i class="glyphicon glyphicon-edit dashboard-container__icon"></i> Report missing anomaly in <span class="anomalies-table__text anomalies-table__text--stronger">alert page</span> for: </div> - <div class="pull-left dashboard-container__alert-selector"> - {{#with (get model.alertsByMetric metric) as |alertList|}} - {{#power-select + {{#each-in filteredAnomalyMapping as |metric humanizedEntityList|}} + {{#accordion.item value=metric as |aitem|}} + {{#aitem.title}} + <section class="dashboard-container__title">Metric: + <span>{{metric}} ({{humanizedEntityList.length}} + {{if (gt humanizedEntityList.length 1) "anomalies" "anomaly"}})</span> + <span><i class="glyphicon glyphicon-menu-{{if toggleCollapsed "down" "up"}}"></i></span> + </section> + {{/aitem.title}} + {{#aitem.body collapsed=toggleCollapsed}} + {{#if isReportAnomalyEnabled}} + <div class="pull-left"> + <i class="glyphicon glyphicon-edit dashboard-container__icon"></i> Report missing anomaly in <span + class="anomalies-table__text anomalies-table__text--stronger">alert page</span> for: </div> + <div class="pull-left dashboard-container__alert-selector"> + {{#with (get model.alertsByMetric metric) as |alertList|}} + {{#power-select triggerId=metric id=metric triggerClass="te-form__select te-form__select--shortened" @@ -131,15 +133,16 @@ onchange=(action "onSelectAlert" metric) as |alertOption| }} - {{alertOption}} - {{/power-select}} - {{/with}} - </div> - <div class="te-button te-button--outline pull-left dashboard-container__go-link"> - <a class="thirdeye-link thirdeye-link--terciary" href="#" {{action "onClickReport" metric humanizedEntityList}}>GO</a> - </div> - {{/if}} - {{models-table + {{alertOption}} + {{/power-select}} + {{/with}} + </div> + <div class="te-button te-button--outline pull-left dashboard-container__go-link"> + <a class="thirdeye-link thirdeye-link--terciary" href="#" + {{action "onClickReport" metric humanizedEntityList}}>GO</a> + </div> + {{/if}} + {{models-table data=humanizedEntityList columns=columns customClasses=classes @@ -150,23 +153,23 @@ pageSize=5 showComponentFooter=true }} - {{/aitem.body}} - {{/accordion.item}} - {{!-- TODO: leave to decide if after poc we need it - lohuynh + {{/aitem.body}} + {{/accordion.item}} + {{!-- TODO: leave to decide if after poc we need it - lohuynh {{#if (gt humanizedEntityList.length 5)}} <a href="{{get (get model.redirectLink metric) alert}}" class="dashboard-container__redirect-link"> See More </a> {{/if}} --}} - {{else}} - {{partial 'partials/home'}} - {{/each-in}} + {{else}} + {{partial 'partials/home'}} + {{/each-in}} {{/bs-accordion}} </section> - {{else}} + {{else}} {{partial 'partials/home'}} - {{/if}} + {{/if}} </article> </div> -{{outlet}} +{{outlet}} \ No newline at end of file diff --git a/thirdeye/thirdeye-frontend/app/pods/manage/explore/template.hbs b/thirdeye/thirdeye-frontend/app/pods/manage/explore/template.hbs index 1938545..a0599f7 100644 --- a/thirdeye/thirdeye-frontend/app/pods/manage/explore/template.hbs +++ b/thirdeye/thirdeye-frontend/app/pods/manage/explore/template.hbs @@ -6,11 +6,11 @@ isLoadError=isLoadError toggleActivation=(action "toggleActivation") }} - <div class="te-search-results__cta"> - {{#link-to "manage.yaml" model.alertId}} - <button class="te-button te-button--outline">Edit</button> - {{/link-to}} - </div> + <div class="te-search-results__cta"> + {{#link-to "manage.yaml" model.alertId}} + <button class="te-button te-button--outline btn">Edit</button> + {{/link-to}} + </div> {{/self-serve-alert-yaml-details}} </div> </section> @@ -18,13 +18,14 @@ <section class="te-page__bottom"> <div class="container"> {{#if isLoadError}} - <div class="te-alert-page-pending"> - <img src="{{rootURL}}assets/images/te-alert-error.png" class="te-alert-page-pending__image te-alert-page-pending__image--error" alt="error"> - <h2 class="te-alert-page-pending__title">Oops, something went wrong</h2> - <p class="te-alert-page-pending__text">{{errorText}}</p> - </div> + <div class="te-alert-page-pending"> + <img src="{{rootURL}}assets/images/te-alert-error.png" + class="te-alert-page-pending__image te-alert-page-pending__image--error" alt="error"> + <h2 class="te-alert-page-pending__title">Oops, something went wrong</h2> + <p class="te-alert-page-pending__text">{{errorText}}</p> + </div> {{else}} - {{alert-details + {{alert-details isPreviewMode=false alertYaml=model.detectionYaml showDetails=true @@ -40,4 +41,4 @@ }} {{/if}} </div> -</section> +</section> \ No newline at end of file diff --git a/thirdeye/thirdeye-frontend/app/styles/components/button.scss b/thirdeye/thirdeye-frontend/app/styles/components/button.scss index 5a61682..d840dcc 100644 --- a/thirdeye/thirdeye-frontend/app/styles/components/button.scss +++ b/thirdeye/thirdeye-frontend/app/styles/components/button.scss @@ -2,11 +2,12 @@ .te-button { border-radius: 2px; - border: 1px solid #339BC7; + border: 1px solid #339bc7; margin: 0 1px; font-size: 17px; line-height: 20px; font-weight: 600; + transition: background-color 0.3s ease; &--small { height: 32px; @@ -14,22 +15,22 @@ } &--cancel { - background-color: #FFF; - color: #339BC7; + background-color: #fff; + color: #339bc7; a { - color: #339BC7; + color: #339bc7; } &:hover, &:focus, &:active, a:hover { - color: #339BC7; + color: #339bc7; text-decoration: none; } } &--muted { - background-color: #FFF; + background-color: #fff; border-color: app-shade(black, 0.55); color: app-shade(black, 0.55); a { @@ -38,8 +39,8 @@ &:hover, &:focus, &:active, - a:hover, { - background-color: rgba(207,207,207,.25); + a:hover { + background-color: rgba(207, 207, 207, 0.25); border-color: app-shade(black, 0.75); color: app-shade(black, 0.75); text-decoration: none; @@ -49,20 +50,20 @@ &--submit { margin-left: 4px; background-color: $te-blue-7; - color: #FFF; + color: #fff; &:hover, &:focus, &:active, a:hover { - color: #FFF; + color: #fff; text-decoration: none; background-color: $te-blue-8; } } &--link { - border-color: #FFF; + border-color: #fff; color: $te-blue; cursor: pointer; text-decoration: none; @@ -88,14 +89,19 @@ } &--link-white { - border-color: #FFF; - color: #FFF; + border-color: #fff; + color: #fff; background-color: inherit; text-decoration: none; } &--outline { color: $te-blue; + background-color: transparent; + &:hover { + background-color: $te-blue; + color: #fff; + } } } @@ -106,7 +112,7 @@ font-size: 17px; line-height: 20px; font-weight: 600; - border-color: #FFF; + border-color: #fff; color: $te-blue; cursor: pointer; text-decoration: none; diff --git a/thirdeye/thirdeye-frontend/app/styles/shared/_styles.scss b/thirdeye/thirdeye-frontend/app/styles/shared/_styles.scss index 85a27a3..b3c34b4 100644 --- a/thirdeye/thirdeye-frontend/app/styles/shared/_styles.scss +++ b/thirdeye/thirdeye-frontend/app/styles/shared/_styles.scss @@ -54,7 +54,7 @@ body { .te-table-global-filter { display: inline-block; padding-bottom: 5px; - padding-right:5px; + padding-right: 5px; } .te-column-dropdown { @@ -340,7 +340,7 @@ body { background-color: rgba(0, 0, 0, 0.03); } - &:hover:not(:disabled){ + &:hover:not(:disabled) { border-color: app-shade(black, 0.55); } @@ -392,7 +392,7 @@ body { font-size: $te-font-size-small; color: $te-link-blue; font-weight: 600; - letter-spacing: .03em; + letter-spacing: 0.03em; float: right; margin: -15px 10px 0 0; cursor: pointer; @@ -448,17 +448,17 @@ body { &__number { color: black; &--good { - color: #4B9D27; + color: #4b9d27; font-weight: normal; } &--average { - color: #F5A623; + color: #f5a623; font-weight: normal; } &--poor { - color: #FF4B51; + color: #ff4b51; font-weight: normal; } } @@ -590,7 +590,6 @@ body { } &__val-glyph { - &--middle { padding: 26px 10px 0 9px; font-size: 19px; @@ -722,7 +721,7 @@ body { &__title { font-size: 40px; font-weight: 100; - letter-spacing: .02em; + letter-spacing: 0.02em; } &__text { @@ -751,9 +750,15 @@ body { } } +.te-alert-page { + &__subtitle { + margin: 0 0 $te-content-container-margin 0; + } +} + .glyphicon-spin { - -webkit-animation: spin 1000ms infinite linear; - animation: spin 1000ms infinite linear; + -webkit-animation: spin 1000ms infinite linear; + animation: spin 1000ms infinite linear; } .te-search-results { @@ -780,10 +785,6 @@ body { } &__header { - display: flex; - justify-content: space-between; - align-items: center; - margin-bottom: 14px; } &__row { @@ -821,8 +822,6 @@ body { &__value { overflow: hidden; text-overflow: ellipsis; - color: black; - max-height: 19px; } &__value-solo { @@ -844,13 +843,16 @@ body { &__title { min-width: 95px; + display: flex; } &__title-name { overflow: hidden; text-overflow: ellipsis; - max-width: 660px; + max-width: 80%; display: inline-block; + font-weight: 600; + margin: 0 $te-spacing 0 0; } &__edit-button { @@ -884,7 +886,7 @@ body { background-color: app-shade(black, 3); font-size: 13px; text-transform: uppercase; - letter-spacing: .08em; + letter-spacing: 0.08em; line-height: 20px; border-radius: 3px; padding: 4px 8px; @@ -894,6 +896,7 @@ body { width: auto; font-weight: bold; border: 2px solid; + cursor: default; &--list { margin: 3px 10px 0 0; @@ -940,7 +943,6 @@ body { } &__a-tag { - &--good { text-decoration: none !important; color: $te-good !important; diff --git a/thirdeye/thirdeye-frontend/tests/integration/pods/components/share-custom-template/component-test.js b/thirdeye/thirdeye-frontend/tests/integration/pods/components/share-custom-template/component-test.js index 93b104e..c079019 100644 --- a/thirdeye/thirdeye-frontend/tests/integration/pods/components/share-custom-template/component-test.js +++ b/thirdeye/thirdeye-frontend/tests/integration/pods/components/share-custom-template/component-test.js @@ -1,6 +1,6 @@ import $ from 'jquery'; import { module, test } from 'qunit'; -import { run } from "@ember/runloop"; +import { run } from '@ember/runloop'; import { setupRenderingTest } from 'ember-qunit'; import { render } from '@ember/test-helpers'; import hbs from 'htmlbars-inline-precompile'; @@ -18,23 +18,23 @@ module('Integration | Component | share custom template', function(hooks) { start: '1539626400000', end: '1539626400000', shareConfig: { - groupName: 'someGroup', - appName: 'someApp', - chart: 'table', - title: 'Title of metrics', - entities: [ - [ - { type: 'label', value: 'Column name1', index: 0}, - { type: 'label', value: 'Column name2', index: 0}, - { type: 'label', value: 'Column name3', index: 0} - ], - [ - { type: 'label', value: 'Email', index: 1}, - { type: 'change', metrics: ['thirdeye:metric:11111'], offsets: ['current', 'wo1w'], summary: ['69.0M', '-2.03'], index: 1}, - { type: 'change', metrics: ['thirdeye:metric:22222'], offsets: ['current', 'wo1w'], summary: ['69.0M', '-2.03'], index: 1} - ] + groupName: 'someGroup', + appName: 'someApp', + chart: 'table', + title: 'Title of metrics', + entities: [ + [ + { type: 'label', value: 'Column name1', index: 0}, + { type: 'label', value: 'Column name2', index: 0}, + { type: 'label', value: 'Column name3', index: 0} + ], + [ + { type: 'label', value: 'Email', index: 1}, + { type: 'change', metrics: ['thirdeye:metric:11111'], offsets: ['current', 'wo1w'], summary: ['69.0M', '-2.03'], index: 1}, + { type: 'change', metrics: ['thirdeye:metric:22222'], offsets: ['current', 'wo1w'], summary: ['69.0M', '-2.03'], index: 1} ] - } + ] + } }); // Rendering the component diff --git a/thirdeye/thirdeye-frontend/tests/utils/constants.js b/thirdeye/thirdeye-frontend/tests/utils/constants.js index d304868..2b51b14 100644 --- a/thirdeye/thirdeye-frontend/tests/utils/constants.js +++ b/thirdeye/thirdeye-frontend/tests/utils/constants.js @@ -1,4 +1,4 @@ -import { isPresent } from "@ember/utils"; +import { isPresent } from '@ember/utils'; /** * General self-serve element selectors @@ -69,7 +69,7 @@ export const selfServeConst = { LINK_TUNE_ALERT: '.te-self-serve__side-link:contains("Customize sensitivity")', // Tuning Page Elements - LINK_ALERT_PAGE: '.te-button:contains("Back to overview")', + LINK_ALERT_PAGE: '.te-button:contains("Back to overview")' }; --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@pinot.apache.org For additional commands, e-mail: commits-h...@pinot.apache.org