mirror of
https://github.com/valitydev/redash.git
synced 2024-11-08 01:48:54 +00:00
175 lines
5.1 KiB
JavaScript
175 lines
5.1 KiB
JavaScript
import moment from 'moment';
|
|
import { isEmpty, isArray, reduce } from 'underscore';
|
|
|
|
import filtersTemplate from './filters.html';
|
|
|
|
import registerEditVisualizationDialog from './edit-visualization-dialog';
|
|
import counterVisualization from './counter';
|
|
import tableVisualization from './table';
|
|
import chartVisualization from './chart';
|
|
import sunburstVisualization from './sunburst';
|
|
import sankeyVisualization from './sankey';
|
|
import wordCloudVisualization from './word-cloud';
|
|
import boxPlotVisualization from './box-plot';
|
|
import cohortVisualization from './cohort';
|
|
import mapVisualization from './map';
|
|
import pivotVisualization from './pivot';
|
|
|
|
function VisualizationProvider() {
|
|
this.visualizations = {};
|
|
this.visualizationTypes = {};
|
|
const defaultConfig = {
|
|
defaultOptions: {},
|
|
skipTypes: false,
|
|
editorTemplate: null,
|
|
};
|
|
|
|
this.registerVisualization = (config) => {
|
|
const visualization = Object.assign({}, defaultConfig, config);
|
|
|
|
// TODO: this is prone to errors; better refactor.
|
|
if (isEmpty(this.visualizations)) {
|
|
this.defaultVisualization = visualization;
|
|
}
|
|
|
|
this.visualizations[config.type] = visualization;
|
|
|
|
if (!config.skipTypes) {
|
|
this.visualizationTypes[config.name] = config.type;
|
|
}
|
|
};
|
|
|
|
this.getSwitchTemplate = (property) => {
|
|
const pattern = /(<[a-zA-Z0-9-]*?)( |>)/;
|
|
|
|
let mergedTemplates = reduce(this.visualizations, (templates, visualization) => {
|
|
if (visualization[property]) {
|
|
const ngSwitch = `$1 ng-switch-when="${visualization.type}" $2`;
|
|
const template = visualization[property].replace(pattern, ngSwitch);
|
|
|
|
return `${templates}\n${template}`;
|
|
}
|
|
|
|
return templates;
|
|
}, '');
|
|
|
|
mergedTemplates = `<div ng-switch on="visualization.type">${mergedTemplates}</div>`;
|
|
|
|
return mergedTemplates;
|
|
};
|
|
|
|
this.$get = ($resource) => {
|
|
const Visualization = $resource('api/visualizations/:id', { id: '@id' });
|
|
Visualization.visualizations = this.visualizations;
|
|
Visualization.visualizationTypes = this.visualizationTypes;
|
|
Visualization.renderVisualizationsTemplate = this.getSwitchTemplate('renderTemplate');
|
|
Visualization.editorTemplate = this.getSwitchTemplate('editorTemplate');
|
|
Visualization.defaultVisualization = this.defaultVisualization;
|
|
|
|
return Visualization;
|
|
};
|
|
}
|
|
|
|
function VisualizationName(Visualization) {
|
|
return {
|
|
restrict: 'E',
|
|
scope: {
|
|
visualization: '=',
|
|
},
|
|
template: '{{name}}',
|
|
replace: false,
|
|
link(scope) {
|
|
if (Visualization.visualizations[scope.visualization.type]) {
|
|
const defaultName = Visualization.visualizations[scope.visualization.type].name;
|
|
if (defaultName !== scope.visualization.name) {
|
|
scope.name = scope.visualization.name;
|
|
}
|
|
}
|
|
},
|
|
};
|
|
}
|
|
|
|
function VisualizationRenderer(Visualization) {
|
|
return {
|
|
restrict: 'E',
|
|
scope: {
|
|
visualization: '=',
|
|
queryResult: '=',
|
|
},
|
|
// TODO: using switch here (and in the options editor) might introduce errors and bad
|
|
// performance wise. It's better to eventually show the correct template based on the
|
|
// visualization type and not make the browser render all of them.
|
|
template: `<filters></filters>\n${Visualization.renderVisualizationsTemplate}`,
|
|
replace: false,
|
|
link(scope) {
|
|
scope.$watch('queryResult && queryResult.getFilters()', (filters) => {
|
|
if (filters) {
|
|
scope.filters = filters;
|
|
}
|
|
});
|
|
},
|
|
};
|
|
}
|
|
|
|
function VisualizationOptionsEditor(Visualization) {
|
|
return {
|
|
restrict: 'E',
|
|
template: Visualization.editorTemplate,
|
|
replace: false,
|
|
scope: {
|
|
visualization: '=',
|
|
query: '=',
|
|
queryResult: '=',
|
|
},
|
|
};
|
|
}
|
|
|
|
function Filters() {
|
|
return {
|
|
restrict: 'E',
|
|
template: filtersTemplate,
|
|
};
|
|
}
|
|
|
|
function FilterValueFilter(clientConfig) {
|
|
return (value, filter) => {
|
|
let firstValue = value;
|
|
if (isArray(value)) {
|
|
firstValue = value[0];
|
|
}
|
|
|
|
// TODO: deduplicate code with table.js:
|
|
if (filter.column.type === 'date') {
|
|
if (firstValue && moment.isMoment(firstValue)) {
|
|
return firstValue.format(clientConfig.dateFormat);
|
|
}
|
|
} else if (filter.column.type === 'datetime') {
|
|
if (firstValue && moment.isMoment(firstValue)) {
|
|
return firstValue.format(clientConfig.dateTimeFormat);
|
|
}
|
|
}
|
|
|
|
return firstValue;
|
|
};
|
|
}
|
|
|
|
export default function (ngModule) {
|
|
ngModule.provider('Visualization', VisualizationProvider);
|
|
ngModule.directive('visualizationRenderer', VisualizationRenderer);
|
|
ngModule.directive('visualizationOptionsEditor', VisualizationOptionsEditor);
|
|
ngModule.directive('visualizationName', VisualizationName);
|
|
ngModule.directive('filters', Filters);
|
|
ngModule.filter('filterValue', FilterValueFilter);
|
|
registerEditVisualizationDialog(ngModule);
|
|
chartVisualization(ngModule);
|
|
counterVisualization(ngModule);
|
|
sunburstVisualization(ngModule);
|
|
sankeyVisualization(ngModule);
|
|
wordCloudVisualization(ngModule);
|
|
boxPlotVisualization(ngModule);
|
|
cohortVisualization(ngModule);
|
|
mapVisualization(ngModule);
|
|
pivotVisualization(ngModule);
|
|
tableVisualization(ngModule);
|
|
}
|