2018-07-27 13:27:28 -07:00
|
|
|
import Component from '@ember/component';
|
2018-08-02 11:27:27 -07:00
|
|
|
import { get, computed, setProperties, getProperties } from '@ember/object';
|
2018-07-27 13:27:28 -07:00
|
|
|
import { task, TaskInstance } from 'ember-concurrency';
|
2018-08-01 15:42:47 -07:00
|
|
|
import ComputedProperty from '@ember/object/computed';
|
|
|
|
|
import { IChartDatum } from 'wherehows-web/typings/app/visualization/charts';
|
2018-08-02 11:27:27 -07:00
|
|
|
import healthCategories from 'wherehows-web/mirage/fixtures/health-categories';
|
|
|
|
|
import healthSeverity from 'wherehows-web/mirage/fixtures/health-severity';
|
2018-08-02 10:20:40 -07:00
|
|
|
import healthDetail from 'wherehows-web/mirage/fixtures/health-detail';
|
|
|
|
|
import { IHealthScore } from 'wherehows-web/typings/api/datasets/health';
|
2018-07-27 13:27:28 -07:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* This is the container component for the dataset health tab. It should contain the health bar graphs and a table
|
|
|
|
|
* depicting the detailed health scores. Aside from fetching the data, it also handles click interactions between
|
|
|
|
|
* the graphs and the table in terms of filtering and displaying of data
|
|
|
|
|
*/
|
|
|
|
|
export default class DatasetHealthContainer extends Component {
|
|
|
|
|
/**
|
|
|
|
|
* The urn identifier for the dataset
|
|
|
|
|
* @type {string}
|
|
|
|
|
*/
|
|
|
|
|
urn: string;
|
|
|
|
|
|
2018-08-01 15:35:21 -07:00
|
|
|
/**
|
|
|
|
|
* Sets the classes for the rendered html element for the component
|
|
|
|
|
* @type {Array<string>}
|
|
|
|
|
*/
|
|
|
|
|
classNames = ['dataset-health'];
|
2018-08-02 11:27:27 -07:00
|
|
|
|
2018-08-01 15:35:21 -07:00
|
|
|
/**
|
2018-08-02 11:27:27 -07:00
|
|
|
* The current filter for the category chart. Clicking on a bar in the chart changes this value and will cause
|
|
|
|
|
* the table component to filter out certain rows. Since we only allow one filter at a time, only this or
|
|
|
|
|
* currentSeverityFilter should have a truthy value at any given point.
|
|
|
|
|
* @type {string}
|
2018-08-01 15:35:21 -07:00
|
|
|
*/
|
2018-08-02 11:27:27 -07:00
|
|
|
currentCategoryFilter = '';
|
2018-08-01 15:42:47 -07:00
|
|
|
|
2018-08-02 11:27:27 -07:00
|
|
|
/**
|
|
|
|
|
* The current filter for the severity chart. Clicking on a bar in the chart changes this value and will cause
|
|
|
|
|
* the table component to filter out certain rows. Since we only allow one filter at a time, only this or
|
|
|
|
|
* currentCategoryFilter should have a truthy value at any given point.
|
|
|
|
|
* @type {string}
|
|
|
|
|
*/
|
|
|
|
|
currentSeverityFilter = '';
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Raw fetched data for the category metrics
|
|
|
|
|
* @type {Array<pending>}
|
|
|
|
|
*/
|
|
|
|
|
categoryMetrics: Array<IChartDatum> = [];
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Raw fetched data for the category metrics
|
|
|
|
|
* @type {Array<pending>}
|
|
|
|
|
*/
|
|
|
|
|
severityMetrics: Array<IChartDatum> = [];
|
|
|
|
|
|
2018-08-02 10:20:40 -07:00
|
|
|
/**
|
|
|
|
|
* Fetched data for the health score detailed data.
|
|
|
|
|
* @type {Array<IHealthScore>}
|
|
|
|
|
*/
|
|
|
|
|
tableData: Array<IHealthScore> = [];
|
|
|
|
|
|
2018-08-02 11:27:27 -07:00
|
|
|
/**
|
|
|
|
|
* Modified categoryMetrics to add properties that will help us render our actual charts without modifying the original
|
|
|
|
|
* data
|
|
|
|
|
* @type {ComputedProperty<Array<IChartDatum>>}
|
|
|
|
|
*/
|
|
|
|
|
renderedCategories: ComputedProperty<Array<IChartDatum>> = computed(
|
|
|
|
|
'categoryMetrics',
|
|
|
|
|
'currentCategoryFilter',
|
|
|
|
|
function(this: DatasetHealthContainer): Array<IChartDatum> {
|
|
|
|
|
const { categoryMetrics, currentCategoryFilter } = getProperties(
|
|
|
|
|
this,
|
|
|
|
|
'categoryMetrics',
|
|
|
|
|
'currentCategoryFilter'
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
return categoryMetrics.map(category => ({
|
|
|
|
|
...category,
|
|
|
|
|
isFaded: !!currentCategoryFilter && category.name !== currentCategoryFilter
|
|
|
|
|
}));
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Modified severityMetrics to add properties that will help us render our actual charts
|
|
|
|
|
* @type {ComputedProperty<Array<IChartDatum>>}
|
|
|
|
|
*/
|
|
|
|
|
renderedSeverity: ComputedProperty<Array<IChartDatum>> = computed(
|
|
|
|
|
'severityMetrics',
|
|
|
|
|
'currentSeverityFilter',
|
|
|
|
|
function(this: DatasetHealthContainer): Array<IChartDatum> {
|
|
|
|
|
const { severityMetrics, currentSeverityFilter } = getProperties(
|
|
|
|
|
this,
|
|
|
|
|
'severityMetrics',
|
|
|
|
|
'currentSeverityFilter'
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
return severityMetrics.map(severity => ({
|
|
|
|
|
...severity,
|
|
|
|
|
isFaded: !!currentSeverityFilter && severity.name !== currentSeverityFilter,
|
|
|
|
|
customColorClass: `severity-chart__bar--${severity.name.toLowerCase()}`
|
|
|
|
|
}));
|
|
|
|
|
}
|
|
|
|
|
);
|
2018-08-01 15:35:21 -07:00
|
|
|
|
2018-07-27 13:27:28 -07:00
|
|
|
didInsertElement() {
|
|
|
|
|
get(this, 'getContainerDataTask').perform();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
didUpdateAttrs() {
|
|
|
|
|
get(this, 'getContainerDataTask').perform();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* An async parent task to group all data tasks for this container component
|
|
|
|
|
* @type {Task<TaskInstance<Promise<any>>, (a?: any) => TaskInstance<TaskInstance<Promise<any>>>>}
|
|
|
|
|
*/
|
|
|
|
|
getContainerDataTask = task(function*(this: DatasetHealthContainer): IterableIterator<TaskInstance<Promise<any>>> {
|
2018-08-02 11:27:27 -07:00
|
|
|
// Pretend like we're getting data from somehwere
|
|
|
|
|
const healthData = {
|
|
|
|
|
categories: healthCategories,
|
2018-08-02 10:20:40 -07:00
|
|
|
severity: healthSeverity,
|
|
|
|
|
detail: healthDetail
|
2018-08-02 11:27:27 -07:00
|
|
|
};
|
2018-07-30 16:55:08 -07:00
|
|
|
|
2018-08-02 11:27:27 -07:00
|
|
|
setProperties(this, {
|
|
|
|
|
categoryMetrics: healthData.categories,
|
2018-08-02 10:20:40 -07:00
|
|
|
severityMetrics: healthData.severity,
|
|
|
|
|
tableData: healthData.detail
|
2018-08-02 11:27:27 -07:00
|
|
|
});
|
2018-08-01 15:42:47 -07:00
|
|
|
});
|
|
|
|
|
|
2018-08-02 11:27:27 -07:00
|
|
|
/**
|
|
|
|
|
* Triggered when the user clicks on one of the bars in the summary charts child component, will trigger
|
|
|
|
|
* a filter for whatever bar they select, unless it already is one in which case we will remove the filter
|
|
|
|
|
* @param this - Explicit this declaration for typescript
|
|
|
|
|
* @param filterType - Whether we are filtering by category or severity
|
|
|
|
|
* @param filterDatum - Passed in to the action by the child component, contains the tag to be filtered for
|
|
|
|
|
*/
|
|
|
|
|
onFilterSelect(this: DatasetHealthContainer, filterType: string, filterDatum: IChartDatum): void {
|
|
|
|
|
const { currentCategoryFilter, currentSeverityFilter } = getProperties(
|
|
|
|
|
this,
|
|
|
|
|
'currentCategoryFilter',
|
|
|
|
|
'currentSeverityFilter'
|
|
|
|
|
);
|
|
|
|
|
const newFilterName = filterDatum.name;
|
|
|
|
|
|
|
|
|
|
setProperties(this, {
|
|
|
|
|
currentCategoryFilter: filterType === 'category' && newFilterName !== currentCategoryFilter ? newFilterName : '',
|
|
|
|
|
currentSeverityFilter: filterType === 'severity' && newFilterName !== currentSeverityFilter ? newFilterName : ''
|
|
|
|
|
});
|
|
|
|
|
}
|
2018-07-27 13:27:28 -07:00
|
|
|
}
|