This commit is contained in:
David Douglas 2017-08-10 18:50:29 +01:00
Родитель 67c2b5a190
Коммит 8f01541d80
4 изменённых файлов: 168 добавлений и 47 удалений

Просмотреть файл

@ -181,11 +181,11 @@ class SettingsStore extends AbstractStoreModel<ISettingsStoreState> implements I
const forkedQueryComponents = dependencyProperty.split('-');
const params = datasources[datasource].config.params;
const isForked = !params.query && !!params.table;
const isForked = params && !params.query && !!params.table;
if (!isForked) {
// unforked
queryFn = params.query;
queryFn = params && params.query || 'n/a';
} else {
// forked
if (!params.queries[queryId] && forkedQueryComponents.length === 2) {

Просмотреть файл

@ -0,0 +1,84 @@
import * as _ from 'lodash';
import utils from '../../index';
import { DataFormatTypes, IDataFormat, formatWarn, getPrefix } from '../common';
import { IDataSourcePlugin } from '../../../data-sources/plugins/DataSourcePlugin';
/**
* Applies selected filters to sample JSON data
* Returns filtered data using a prefix.
*
* @param format {
* type: 'filtered_samples',
* args: {
* prefix: string - a prefix string for the filtered sample data (defaults to 'filtered').
* }
* }
* @param state Current received state from data source
* @param dependencies Dependencies for the plugin
* @param plugin The entire plugin (for id generation, params etc...)
* @param prevState The previous state to compare for changing filters
*/
export function filtered_samples (
format: string | IDataFormat,
state: any,
dependencies: IDictionary,
plugin: IDataSourcePlugin,
prevState: any) {
let result = {};
if (typeof format === 'string') {
return formatWarn('format should be an object with args', 'bars', plugin);
}
const args = format.args || {};
const prefix = args['prefix'] || 'filtered';
const params = plugin.getParams();
const filters = params.filters;
// Check for active filters selected
const hasSelectedFilters = filters.some(filter => (
dependencies[filter.dependency] && dependencies[filter.dependency].length > 0)
);
// Apply filter to sample data
Object.keys(dependencies).forEach(key => {
// Skip filters
if (filters.find(f => f.dependency === key)) {
return;
}
// Apply filter data
const values = dependencies[key];
let filteredData = {};
// Return early if no active filters
if (!hasSelectedFilters) {
filteredData[prefix + '_' + key] = values;
Object.assign(result, filteredData);
return;
}
// Get active selected filters
const activeFilters = filters.reduce((acc, filter) => {
if (dependencies[filter.dependency].length > 0) {
acc.push(filter);
}
return acc;
}, []);
// Apply active selected filters to sample data
const filteredValues = values.filter(value => {
return activeFilters.every(filter => {
const queryProperty = filter.queryProperty;
const selectedFilters = dependencies[filter.dependency];
return value[queryProperty] === selectedFilters.find(selectedFilter => selectedFilter === value[queryProperty]);
});
});
filteredData[prefix + '_' + key] = filteredValues;
Object.assign(result, filteredData);
});
return result;
}

Просмотреть файл

@ -5,4 +5,5 @@ export * from './formats/flags';
export * from './formats/retention';
export * from './formats/scorecard';
export * from './formats/timeline';
export * from './formats/timespan';
export * from './formats/timespan';
export * from './formats/filtered-samples';

Просмотреть файл

@ -28,62 +28,98 @@ export const config: IDashboardConfig = /*return*/ {
}
},
dataSources: [
{
id: 'filter1',
type: 'Sample',
format: 'filter',
params: {
samples: {
'values': [
{value: 'en'},
{value: 'fr'},
{value: 'de'}
]
}
}
},
{
id: 'filter2',
type: 'Sample',
format: 'filter',
params: {
samples: {
'values': [
{value: 'skype'},
{value: 'messenger'},
{value: 'slack'}
]
}
}
},
{
id: 'samples',
type: 'Sample',
dependencies: {
selectedFilter: 'filters:filter-selected',
selectedFilter1: 'filter1:values-selected',
selectedFilter2: 'filter2:values-selected',
},
params: {
samples: {
data_for_pie: [
{ name: 'value1', value: 1, category: 'app' },
{ name: 'value2', value: 2, category: 'bot' },
{ name: 'value3', value: 3, category: 'bot' },
{ name: 'value4', value: 4, category: 'web' },
{ name: 'value5', value: 5, category: 'web' },
{ name: 'value6', value: 6, category: 'web' },
{ name: 'value6', value: 6, category: 'web' }
{ name: 'skype-en', value: 9, locale: 'en', channel: 'skype' },
{ name: 'skype-fr', value: 8, locale: 'fr', channel: 'skype' },
{ name: 'skype-de', value: 7, locale: 'de', channel: 'skype' },
{ name: 'messenger-en', value: 6, locale: 'en', channel: 'messenger' },
{ name: 'messenger-fr', value: 5, locale: 'fr', channel: 'messenger' },
{ name: 'messenger-de', value: 4, locale: 'de', channel: 'messenger' },
{ name: 'slack-en', value: 3, locale: 'en', channel: 'slack' },
{ name: 'slack-fr', value: 2, locale: 'fr', channel: 'slack' },
{ name: 'slack-de', value: 1, locale: 'de', channel: 'slack' }
]
},
filters: [{ dependency: 'selectedFilter', queryProperty: 'category' }],
filters: [
{ dependency: 'selectedFilter1', queryProperty: 'locale' },
{ dependency: 'selectedFilter2', queryProperty: 'channel' }
],
},
format: {
type: 'filtered_samples'
},
calculated: (state, dependencies) => {
const {data_for_pie} = state;
const {selectedFilter} = dependencies;
let {filtered_data_value, filtered_data_subvalue} = state;
let filtered_data_for_pie = data_for_pie;
if (selectedFilter && selectedFilter.length > 0) {
filtered_data_for_pie = data_for_pie.filter(i => i.category === selectedFilter.find(f => f === i.category) );
}
filtered_data_value = filtered_data_for_pie.length;
filtered_data_subvalue = filtered_data_for_pie.reduce((a,c) => a + c.value, 0);
return {
'filtered_data_value': filtered_data_value || 0,
'filtered_data_subvalue': filtered_data_subvalue || 0,
'filtered_data_for_pie': filtered_data_for_pie
};
}
},
{
id: 'filters',
id: 'scorecard',
type: 'Sample',
params: {
samples: {
'filter-categories': ['web', 'app', 'bot'],
'filter-selected': []
}
dependencies: {
filteredData: 'samples:filtered_data_for_pie',
},
calculated: (state, dependencies) => {
const {filteredData} = state;
const filteredDataValue = filteredData && filteredData.reduce((a, c) => a + c.value, 0) || 0;
const filteredDataSubvalue = filteredData && filteredData.length || 0;
return {
'filtered_data_value': filteredDataValue,
'filtered_data_subvalue': filteredDataSubvalue,
};
}
}
],
filters: [
{
type: 'MenuFilter',
title: 'Filter',
subtitle: 'Select category',
title: 'Locale',
subtitle: 'Select locale',
icon: 'forum',
dependencies: { selectedValues: 'filters:filter-selected', values: 'filters:filter-categories' },
actions: { onChange: 'filters:updateSelectedValues:filter-selected' },
source: 'filter1',
actions: { onChange: 'filter1:updateSelectedValues:values-selected' },
first: true
},
{
type: 'MenuFilter',
title: 'Channel',
subtitle: 'Select channel',
icon: 'forum',
source: 'filter2',
actions: { onChange: 'filter2:updateSelectedValues:values-selected' },
first: true
},
],
@ -95,7 +131,7 @@ export const config: IDashboardConfig = /*return*/ {
subtitle: 'Description of pie sample 1',
size: { w: 5, h: 8 },
dependencies: { values: 'samples:filtered_data_for_pie' },
props: { showLegend: true }
props: { entityType: 'Sessions', showLegend: true }
},
{
id: 'pie_sample2',
@ -104,34 +140,34 @@ export const config: IDashboardConfig = /*return*/ {
subtitle: 'Hover on the values to see the difference from sample 1',
size: { w: 5, h: 8 },
dependencies: { values: 'samples:filtered_data_for_pie' },
props: { showLegend: true, compact: true }
props: { entityType: 'Sessions', showLegend: true, compact: true }
},
{
id: 'scorecard_sample1',
id: 'scorecard1',
type: 'Scorecard',
title: 'Value',
size: { w: 1, h: 3 },
dependencies: {
value: 'samples:filtered_data_value',
value: 'scorecard:filtered_data_value',
color: '::#2196F3',
icon: '::av_timer'
}
},
{
id: 'scorecard_sample2',
id: 'scorecard2',
type: 'Scorecard',
title: 'Same Value',
size: { w: 1, h: 3 },
dependencies: {
value: 'samples:filtered_data_value',
value: 'scorecard:filtered_data_value',
color: '::#2196F3',
icon: '::av_timer',
subvalue: 'samples:filtered_data_subvalue'
subvalue: 'scorecard:filtered_data_subvalue'
},
props: {
subheading: 'Total value'
subheading: 'segments'
}
}
],
dialogs: []
}
};