refactor barchart

This commit is contained in:
Lee moon soo 2016-10-05 09:48:35 +09:00
parent 06c3e78312
commit c76a92b7d8
8 changed files with 420 additions and 314 deletions

View file

@ -111,25 +111,24 @@
{
id: 'multiBarChart',
name: 'Bar Chart',
icon: 'fa fa-bar-chart'
icon: 'fa fa-bar-chart',
transformation: 'pivot'
}
];
/**
* Holds class actual runtime instance and related infos of built-in visualizations
* Holds class and actual runtime instance and related infos of built-in visualizations
*/
var builtInVisualizations = {
'table': {
class: zeppelin.TableVisualization,
transformation: undefined,
instance: undefined // created from setGraphMode()
},
'multiBarChart': {
class: zeppelin.BarchartVisualization,
transformation: zeppelin.Pivot,
instance: undefined
}
};
};
/**
* TableData instance
@ -157,7 +156,7 @@
if ($scope.getResultType() === 'TABLE') {
var TableData = zeppelin.TableData;
tableData = new TableData();
tableData.loadParagraphResult($scope.paragraph.result);
tableData.loadParagraphResult($scope.paragraph.result);
$scope.setGraphMode($scope.getGraphMode(), false, false);
} else if ($scope.getResultType() === 'HTML') {
$scope.renderHtml();
@ -983,8 +982,6 @@
var graphContainerEl = angular.element('#p' + $scope.paragraph.id + '_graph');
graphContainerEl.height(height);
var data = $scope.paragraph.result;
if (!type) {
type = 'table';
}
@ -1003,7 +1000,7 @@
// instantiate visualization
var Visualization = builtInViz.class;
builtInViz.instance = new Visualization(targetEl);
builtInViz.instance = new Visualization(targetEl, $scope.paragraph.config.graph);
builtInViz.instance.render(tableData);
} catch (err) {
console.log('Graph drawing error %o', err);
@ -1013,7 +1010,7 @@
}
};
$timeout(retryRenderer);
} else {
} else if (refresh) {
builtInViz.instance.targetEl.height(height);
builtInViz.instance.render(tableData);
}
@ -1021,8 +1018,8 @@
if (!type || type === 'table') {
//setTable($scope.paragraph.result, refresh);
} else {
setD3Chart(type, $scope.paragraph.result, refresh);
} else if (type === 'nomore') {
setD3Chart(type, tableData, refresh);
}
}
};
@ -1268,9 +1265,9 @@
for (var i = 0; i < list.length; i++) {
// remove non existing column
var found = false;
for (var j = 0; j < tableData.columnNames.length; j++) {
for (var j = 0; j < tableData.columns.length; j++) {
var a = list[i];
var b = tableData.columnNames[j];
var b = tableData.columns[j];
if (a.index === b.index && a.name === b.name) {
found = true;
break;
@ -1286,9 +1283,9 @@
for (var f in fields) {
if (fields[f]) {
var found = false;
for (var i = 0; i < tableData.columnNames.length; i++) {
for (var i = 0; i < tableData.columns.length; i++) {
var a = fields[f];
var b = tableData.columnNames[i];
var b = tableData.columns[i];
if (a.index === b.index && a.name === b.name) {
found = true;
break;
@ -1314,20 +1311,20 @@
/* select default key and value if there're none selected */
var selectDefaultColsForGraphOption = function() {
if ($scope.paragraph.config.graph.keys.length === 0 && $scope.paragraph.result.columnNames.length > 0) {
$scope.paragraph.config.graph.keys.push($scope.paragraph.result.columnNames[0]);
if ($scope.paragraph.config.graph.keys.length === 0 && tableData.columns.length > 0) {
$scope.paragraph.config.graph.keys.push(tableData.columns[0]);
}
if ($scope.paragraph.config.graph.values.length === 0 && $scope.paragraph.result.columnNames.length > 1) {
$scope.paragraph.config.graph.values.push($scope.paragraph.result.columnNames[1]);
if ($scope.paragraph.config.graph.values.length === 0 && tableData.columns.length > 1) {
$scope.paragraph.config.graph.values.push(tableData.columns[1]);
}
if (!$scope.paragraph.config.graph.scatter.xAxis && !$scope.paragraph.config.graph.scatter.yAxis) {
if ($scope.paragraph.result.columnNames.length > 1) {
$scope.paragraph.config.graph.scatter.xAxis = $scope.paragraph.result.columnNames[0];
$scope.paragraph.config.graph.scatter.yAxis = $scope.paragraph.result.columnNames[1];
} else if ($scope.paragraph.result.columnNames.length === 1) {
$scope.paragraph.config.graph.scatter.xAxis = $scope.paragraph.result.columnNames[0];
if (tableData.columns.length > 1) {
$scope.paragraph.config.graph.scatter.xAxis = tableData.columns[0];
$scope.paragraph.config.graph.scatter.yAxis = tableData.columns[1];
} else if (tableData.columns.length === 1) {
$scope.paragraph.config.graph.scatter.xAxis = tableData.columns[0];
}
}
};
@ -1910,8 +1907,8 @@
$scope.exportToDSV = function(delimiter) {
var dsv = '';
for (var titleIndex in $scope.paragraph.result.columnNames) {
dsv += $scope.paragraph.result.columnNames[titleIndex].name + delimiter;
for (var titleIndex in tableData.columns) {
dsv += tableData.columns[titleIndex].name + delimiter;
}
dsv = dsv.substring(0, dsv.length - 1) + '\n';
for (var r in $scope.paragraph.result.msgTable) {
@ -2304,9 +2301,9 @@
if (newType === 'TABLE') {
if (oldType !== 'TABLE' || resultRefreshed) {
var TableData = new zeppelin.TableData;
var TableData = zeppelin.TableData;
tableData = new TableData();
tableData.loadParagraphResult($scope.paragraph.result);
tableData.loadParagraphResult($scope.paragraph.result);
clearUnknownColsFromGraphOption();
selectDefaultColsForGraphOption();
}

View file

@ -0,0 +1,165 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
'use strict';
var zeppelin = zeppelin || {};
/**
* pivot table data and return d3 chart data
*/
zeppelin.PivotTransformation = function(config) {
zeppelin.Transformation.call(this, config);
};
zeppelin.PivotTransformation.prototype = Object.create(zeppelin.Transformation.prototype);
/**
* Method will be invoked when tableData or config changes
*/
zeppelin.PivotTransformation.prototype.transform = function(tableData) {
return this.pivot(
tableData,
this.config.keys,
this.config.groups,
this.config.values);
};
zeppelin.PivotTransformation.prototype.pivot = function(data, keys, groups, values) {
var aggrFunc = {
sum: function(a, b) {
var varA = (a !== undefined) ? (isNaN(a) ? 1 : parseFloat(a)) : 0;
var varB = (b !== undefined) ? (isNaN(b) ? 1 : parseFloat(b)) : 0;
return varA + varB;
},
count: function(a, b) {
var varA = (a !== undefined) ? parseInt(a) : 0;
var varB = (b !== undefined) ? 1 : 0;
return varA + varB;
},
min: function(a, b) {
var varA = (a !== undefined) ? (isNaN(a) ? 1 : parseFloat(a)) : 0;
var varB = (b !== undefined) ? (isNaN(b) ? 1 : parseFloat(b)) : 0;
return Math.min(varA,varB);
},
max: function(a, b) {
var varA = (a !== undefined) ? (isNaN(a) ? 1 : parseFloat(a)) : 0;
var varB = (b !== undefined) ? (isNaN(b) ? 1 : parseFloat(b)) : 0;
return Math.max(varA,varB);
},
avg: function(a, b, c) {
var varA = (a !== undefined) ? (isNaN(a) ? 1 : parseFloat(a)) : 0;
var varB = (b !== undefined) ? (isNaN(b) ? 1 : parseFloat(b)) : 0;
return varA + varB;
}
};
var aggrFuncDiv = {
sum: false,
count: false,
min: false,
max: false,
avg: true
};
var schema = {};
var rows = {};
for (var i = 0; i < data.rows.length; i++) {
var row = data.rows[i];
var s = schema;
var p = rows;
for (var k = 0; k < keys.length; k++) {
var key = keys[k];
// add key to schema
if (!s[key.name]) {
s[key.name] = {
order: k,
index: key.index,
type: 'key',
children: {}
};
}
s = s[key.name].children;
// add key to row
var keyKey = row[key.index];
if (!p[keyKey]) {
p[keyKey] = {};
}
p = p[keyKey];
}
for (var g = 0; g < groups.length; g++) {
var group = groups[g];
var groupKey = row[group.index];
// add group to schema
if (!s[groupKey]) {
s[groupKey] = {
order: g,
index: group.index,
type: 'group',
children: {}
};
}
s = s[groupKey].children;
// add key to row
if (!p[groupKey]) {
p[groupKey] = {};
}
p = p[groupKey];
}
for (var v = 0; v < values.length; v++) {
var value = values[v];
var valueKey = value.name + '(' + value.aggr + ')';
// add value to schema
if (!s[valueKey]) {
s[valueKey] = {
type: 'value',
order: v,
index: value.index
};
}
// add value to row
if (!p[valueKey]) {
p[valueKey] = {
value: (value.aggr !== 'count') ? row[value.index] : 1,
count: 1
};
} else {
p[valueKey] = {
value: aggrFunc[value.aggr](p[valueKey].value, row[value.index], p[valueKey].count + 1),
count: (aggrFuncDiv[value.aggr]) ? p[valueKey].count + 1 : p[valueKey].count
};
}
}
}
console.log('schema=%o, rows=%o', schema, rows);
return {
keys: keys,
groups: groups,
values: values,
schema: schema,
rows: rows
};
};

View file

@ -88,275 +88,3 @@ zeppelin.TableData.prototype.parseTableCell = function(cell) {
}
return cell;
};
zeppelin.TableData.prototype.pivot = function(keys, groups, values, allowTextXAxis, fillMissingValues, chartType) {
var aggrFunc = {
sum: function(a, b) {
var varA = (a !== undefined) ? (isNaN(a) ? 1 : parseFloat(a)) : 0;
var varB = (b !== undefined) ? (isNaN(b) ? 1 : parseFloat(b)) : 0;
return varA + varB;
},
count: function(a, b) {
var varA = (a !== undefined) ? parseInt(a) : 0;
var varB = (b !== undefined) ? 1 : 0;
return varA + varB;
},
min: function(a, b) {
var varA = (a !== undefined) ? (isNaN(a) ? 1 : parseFloat(a)) : 0;
var varB = (b !== undefined) ? (isNaN(b) ? 1 : parseFloat(b)) : 0;
return Math.min(varA,varB);
},
max: function(a, b) {
var varA = (a !== undefined) ? (isNaN(a) ? 1 : parseFloat(a)) : 0;
var varB = (b !== undefined) ? (isNaN(b) ? 1 : parseFloat(b)) : 0;
return Math.max(varA,varB);
},
avg: function(a, b, c) {
var varA = (a !== undefined) ? (isNaN(a) ? 1 : parseFloat(a)) : 0;
var varB = (b !== undefined) ? (isNaN(b) ? 1 : parseFloat(b)) : 0;
return varA + varB;
}
};
var aggrFuncDiv = {
sum: false,
count: false,
min: false,
max: false,
avg: true
};
var schema = {};
var rows = {};
for (var i = 0; i < this.rows.length; i++) {
var row = this.rows[i];
var s = schema;
var p = rows;
for (var k = 0; k < keys.length; k++) {
var key = keys[k];
// add key to schema
if (!s[key.name]) {
s[key.name] = {
order: k,
index: key.index,
type: 'key',
children: {}
};
}
s = s[key.name].children;
// add key to row
var keyKey = row[key.index];
if (!p[keyKey]) {
p[keyKey] = {};
}
p = p[keyKey];
}
for (var g = 0; g < groups.length; g++) {
var group = groups[g];
var groupKey = row[group.index];
// add group to schema
if (!s[groupKey]) {
s[groupKey] = {
order: g,
index: group.index,
type: 'group',
children: {}
};
}
s = s[groupKey].children;
// add key to row
if (!p[groupKey]) {
p[groupKey] = {};
}
p = p[groupKey];
}
for (var v = 0; v < values.length; v++) {
var value = values[v];
var valueKey = value.name + '(' + value.aggr + ')';
// add value to schema
if (!s[valueKey]) {
s[valueKey] = {
type: 'value',
order: v,
index: value.index
};
}
// add value to row
if (!p[valueKey]) {
p[valueKey] = {
value: (value.aggr !== 'count') ? row[value.index] : 1,
count: 1
};
} else {
p[valueKey] = {
value: aggrFunc[value.aggr](p[valueKey].value, row[value.index], p[valueKey].count + 1),
count: (aggrFuncDiv[value.aggr]) ? p[valueKey].count + 1 : p[valueKey].count
};
}
}
}
console.log("schema=%o, rows=%o", schema, rows);
return {
schema: schema,
rows: rows
}
};
zeppelin.TableData.prototype._buildTableDataFromPivot = function(schema, rows, keys, groups, values, values, allowTextXAxis, fillMissingValues, chartType) {
// construct table data
var d3g = [];
var concat = function(o, n) {
if (!o) {
return n;
} else {
return o + '.' + n;
}
};
var getSchemaUnderKey = function(key, s) {
for (var c in key.children) {
s[c] = {};
getSchemaUnderKey(key.children[c], s[c]);
}
};
var traverse = function(sKey, s, rKey, r, func, rowName, rowValue, colName) {
//console.log("TRAVERSE sKey=%o, s=%o, rKey=%o, r=%o, rowName=%o, rowValue=%o, colName=%o", sKey, s, rKey, r, rowName, rowValue, colName);
if (s.type === 'key') {
rowName = concat(rowName, sKey);
rowValue = concat(rowValue, rKey);
} else if (s.type === 'group') {
colName = concat(colName, rKey);
} else if (s.type === 'value' && sKey === rKey || valueOnly) {
colName = concat(colName, rKey);
func(rowName, rowValue, colName, r);
}
for (var c in s.children) {
if (fillMissingValues && s.children[c].type === 'group' && r[c] === undefined) {
var cs = {};
getSchemaUnderKey(s.children[c], cs);
traverse(c, s.children[c], c, cs, func, rowName, rowValue, colName);
continue;
}
for (var j in r) {
if (s.children[c].type === 'key' || c === j) {
traverse(c, s.children[c], j, r[j], func, rowName, rowValue, colName);
}
}
}
};
var valueOnly = (keys.length === 0 && groups.length === 0 && values.length > 0);
var noKey = (keys.length === 0);
var isMultiBarChart = (chartType === 'multiBarChart');
var sKey = Object.keys(schema)[0];
var rowNameIndex = {};
var rowIdx = 0;
var colNameIndex = {};
var colIdx = 0;
var rowIndexValue = {};
for (var k in rows) {
traverse(sKey, schema[sKey], k, rows[k], function(rowName, rowValue, colName, value) {
//console.log("RowName=%o, row=%o, col=%o, value=%o", rowName, rowValue, colName, value);
if (rowNameIndex[rowValue] === undefined) {
rowIndexValue[rowIdx] = rowValue;
rowNameIndex[rowValue] = rowIdx++;
}
if (colNameIndex[colName] === undefined) {
colNameIndex[colName] = colIdx++;
}
var i = colNameIndex[colName];
if (noKey && isMultiBarChart) {
i = 0;
}
if (!d3g[i]) {
d3g[i] = {
values: [],
key: (noKey && isMultiBarChart) ? 'values' : colName
};
}
var xVar = isNaN(rowValue) ? ((allowTextXAxis) ? rowValue : rowNameIndex[rowValue]) : parseFloat(rowValue);
var yVar = 0;
if (xVar === undefined) { xVar = colName; }
if (value !== undefined) {
yVar = isNaN(value.value) ? 0 : parseFloat(value.value) / parseFloat(value.count);
}
d3g[i].values.push({
x: xVar,
y: yVar
});
});
}
// clear aggregation name, if possible
var namesWithoutAggr = {};
var colName;
var withoutAggr;
// TODO - This part could use som refactoring - Weird if/else with similar actions and variable names
for (colName in colNameIndex) {
withoutAggr = colName.substring(0, colName.lastIndexOf('('));
if (!namesWithoutAggr[withoutAggr]) {
namesWithoutAggr[withoutAggr] = 1;
} else {
namesWithoutAggr[withoutAggr]++;
}
}
if (valueOnly) {
for (var valueIndex = 0; valueIndex < d3g[0].values.length; valueIndex++) {
colName = d3g[0].values[valueIndex].x;
if (!colName) {
continue;
}
withoutAggr = colName.substring(0, colName.lastIndexOf('('));
if (namesWithoutAggr[withoutAggr] <= 1) {
d3g[0].values[valueIndex].x = withoutAggr;
}
}
} else {
for (var d3gIndex = 0; d3gIndex < d3g.length; d3gIndex++) {
colName = d3g[d3gIndex].key;
withoutAggr = colName.substring(0, colName.lastIndexOf('('));
if (namesWithoutAggr[withoutAggr] <= 1) {
d3g[d3gIndex].key = withoutAggr;
}
}
// use group name instead of group.value as a column name, if there're only one group and one value selected.
if (groups.length === 1 && values.length === 1) {
for (d3gIndex = 0; d3gIndex < d3g.length; d3gIndex++) {
colName = d3g[d3gIndex].key;
colName = colName.split('.').slice(0, -1).join('.');
d3g[d3gIndex].key = colName;
}
}
}
return {
xLabels: rowIndexValue,
d3g: d3g
};
};

View file

@ -19,12 +19,17 @@ var zeppelin = zeppelin || {};
/**
* Base class for visualization
*/
zeppelin.Transformation = function() {
zeppelin.Transformation = function(config) {
this.config = config;
};
/**
* Method will be invoked when tableData or config changes
*/
zeppelin.Transformation.prototype.transform = function(tableData, config) {
zeppelin.Transformation.prototype.transform = function(tableData) {
// override this
};
zeppelin.Transformation.prototype.setConfig = function(config) {
this.config = config;
};

View file

@ -17,8 +17,11 @@
/**
* Visualize data in table format
*/
zeppelin.BarchartVisualization = function(targetEl) {
zeppelin.Nvd3ChartVisualization.call(this, targetEl);
zeppelin.BarchartVisualization = function(targetEl, config) {
zeppelin.Nvd3ChartVisualization.call(this, targetEl, config);
var PivotTransformation = zeppelin.PivotTransformation;
this.pivot = new PivotTransformation(config);
};
zeppelin.BarchartVisualization.prototype = Object.create(zeppelin.Nvd3ChartVisualization.prototype);
@ -27,8 +30,29 @@ zeppelin.BarchartVisualization.prototype.type = function() {
return 'multiBarChart';
};
zeppelin.BarchartVisualization.prototype.getTransformation = function() {
return this.pivot;
};
zeppelin.BarchartVisualization.prototype.render = function(tableData) {
var pivot = this.pivot.transform(tableData);
var d3Data = this.d3DataFromPivot(
pivot.schema,
pivot.rows,
pivot.keys,
pivot.groups,
pivot.values,
true,
false,
true);
zeppelin.Nvd3ChartVisualization.prototype.render.call(this, d3Data);
};
zeppelin.BarchartVisualization.prototype.configureChart = function(chart) {
// override this to configure chart
var self = this;
chart.yAxis.axisLabelDistance(50);
chart.yAxis.tickFormat(function(d) {return this.yAxisTickFormat(d);});
chart.yAxis.tickFormat(function(d) {return self.yAxisTickFormat(d);});
console.log('configure chart');
};

View file

@ -17,23 +17,51 @@
/**
* Visualize data in table format
*/
zeppelin.Nvd3ChartVisualization = function(targetEl) {
zeppelin.Visualization.call(this, targetEl);
zeppelin.Nvd3ChartVisualization = function(targetEl, config) {
zeppelin.Visualization.call(this, targetEl, config);
this.targetEl.append("<svg></svg>");
};
zeppelin.Nvd3ChartVisualization.prototype = Object.create(zeppelin.Visualization.prototype);
zeppelin.Nvd3ChartVisualization.prototype.render = function(tableData) {
zeppelin.Nvd3ChartVisualization.prototype.render = function(data) {
var type = this.type();
console.log('chart type = %o', type);
var d3g = data.d3g;
if (!this.chart) {
this.chart = nv.models[type]();
}
tableData.pivot(['key'],[],['value']);
this.configureChart(this.chart);
var animationDuration = 300;
var numberOfDataThreshold = 150;
var height = this.targetEl.height();
// turn off animation when dataset is too large. (for performance issue)
// still, since dataset is large, the chart content sequentially appears like animated.
try {
if (d3g[0].values.length > numberOfDataThreshold) {
animationDuration = 0;
}
} catch (ignoreErr) {
}
d3.select('#' + this.targetEl[0].id + ' svg')
.attr('height', height)
.datum(d3g)
.transition()
.duration(animationDuration)
.call(this.chart);
d3.select('#' + this.targetEl[0].id + ' svg').style.height = height + 'px';
this.chart.update();
nv.utils.windowResize(this.chart.update);
};
zeppelin.Nvd3ChartVisualization.prototype.onResize = function() {
if (this.chart) {
this.chart.update();
}
};
zeppelin.Nvd3ChartVisualization.prototype.type = function() {
@ -70,3 +98,152 @@ zeppelin.Nvd3ChartVisualization.prototype.yAxisTickFormat = function(d) {
}
return this.groupedThousandsWith3DigitsFormatter(d);
};
zeppelin.Nvd3ChartVisualization.prototype.d3DataFromPivot = function(
schema, rows, keys, groups, values, allowTextXAxis, fillMissingValues, multiBarChart) {
// construct table data
var d3g = [];
var concat = function(o, n) {
if (!o) {
return n;
} else {
return o + '.' + n;
}
};
var getSchemaUnderKey = function(key, s) {
for (var c in key.children) {
s[c] = {};
getSchemaUnderKey(key.children[c], s[c]);
}
};
var traverse = function(sKey, s, rKey, r, func, rowName, rowValue, colName) {
//console.log("TRAVERSE sKey=%o, s=%o, rKey=%o, r=%o, rowName=%o, rowValue=%o, colName=%o", sKey, s, rKey, r, rowName, rowValue, colName);
if (s.type === 'key') {
rowName = concat(rowName, sKey);
rowValue = concat(rowValue, rKey);
} else if (s.type === 'group') {
colName = concat(colName, rKey);
} else if (s.type === 'value' && sKey === rKey || valueOnly) {
colName = concat(colName, rKey);
func(rowName, rowValue, colName, r);
}
for (var c in s.children) {
if (fillMissingValues && s.children[c].type === 'group' && r[c] === undefined) {
var cs = {};
getSchemaUnderKey(s.children[c], cs);
traverse(c, s.children[c], c, cs, func, rowName, rowValue, colName);
continue;
}
for (var j in r) {
if (s.children[c].type === 'key' || c === j) {
traverse(c, s.children[c], j, r[j], func, rowName, rowValue, colName);
}
}
}
};
var valueOnly = (keys.length === 0 && groups.length === 0 && values.length > 0);
var noKey = (keys.length === 0);
var isMultiBarChart = multiBarChart;
var sKey = Object.keys(schema)[0];
var rowNameIndex = {};
var rowIdx = 0;
var colNameIndex = {};
var colIdx = 0;
var rowIndexValue = {};
for (var k in rows) {
traverse(sKey, schema[sKey], k, rows[k], function(rowName, rowValue, colName, value) {
//console.log("RowName=%o, row=%o, col=%o, value=%o", rowName, rowValue, colName, value);
if (rowNameIndex[rowValue] === undefined) {
rowIndexValue[rowIdx] = rowValue;
rowNameIndex[rowValue] = rowIdx++;
}
if (colNameIndex[colName] === undefined) {
colNameIndex[colName] = colIdx++;
}
var i = colNameIndex[colName];
if (noKey && isMultiBarChart) {
i = 0;
}
if (!d3g[i]) {
d3g[i] = {
values: [],
key: (noKey && isMultiBarChart) ? 'values' : colName
};
}
var xVar = isNaN(rowValue) ? ((allowTextXAxis) ? rowValue : rowNameIndex[rowValue]) : parseFloat(rowValue);
var yVar = 0;
if (xVar === undefined) { xVar = colName; }
if (value !== undefined) {
yVar = isNaN(value.value) ? 0 : parseFloat(value.value) / parseFloat(value.count);
}
d3g[i].values.push({
x: xVar,
y: yVar
});
});
}
// clear aggregation name, if possible
var namesWithoutAggr = {};
var colName;
var withoutAggr;
// TODO - This part could use som refactoring - Weird if/else with similar actions and variable names
for (colName in colNameIndex) {
withoutAggr = colName.substring(0, colName.lastIndexOf('('));
if (!namesWithoutAggr[withoutAggr]) {
namesWithoutAggr[withoutAggr] = 1;
} else {
namesWithoutAggr[withoutAggr]++;
}
}
if (valueOnly) {
for (var valueIndex = 0; valueIndex < d3g[0].values.length; valueIndex++) {
colName = d3g[0].values[valueIndex].x;
if (!colName) {
continue;
}
withoutAggr = colName.substring(0, colName.lastIndexOf('('));
if (namesWithoutAggr[withoutAggr] <= 1) {
d3g[0].values[valueIndex].x = withoutAggr;
}
}
} else {
for (var d3gIndex = 0; d3gIndex < d3g.length; d3gIndex++) {
colName = d3g[d3gIndex].key;
withoutAggr = colName.substring(0, colName.lastIndexOf('('));
if (namesWithoutAggr[withoutAggr] <= 1) {
d3g[d3gIndex].key = withoutAggr;
}
}
// use group name instead of group.value as a column name, if there're only one group and one value selected.
if (groups.length === 1 && values.length === 1) {
for (d3gIndex = 0; d3gIndex < d3g.length; d3gIndex++) {
colName = d3g[d3gIndex].key;
colName = colName.split('.').slice(0, -1).join('.');
d3g[d3gIndex].key = colName;
}
}
}
return {
xLabels: rowIndexValue,
d3g: d3g
};
};

View file

@ -19,12 +19,20 @@ var zeppelin = zeppelin || {};
/**
* Base class for visualization
*/
zeppelin.Visualization = function(targetEl) {
zeppelin.Visualization = function(targetEl, config) {
this.targetEl = targetEl;
this.config = config;
};
/**
* Method will be invoked
* get transformation
*/
zeppelin.Visualization.prototype.getTransformation = function() {
// override this
};
/**
* Method will be invoked when data or configuration changed
*/
zeppelin.Visualization.prototype.render = function(tableData) {
// override this

View file

@ -154,6 +154,8 @@ limitations under the License.
<script src="app/app.controller.js"></script>
<script src="app/home/home.controller.js"></script>
<script src="app/tabledata/tabledata.js"></script>
<script src="app/tabledata/transformation.js"></script>
<script src="app/tabledata/pivot.js"></script>
<script src="app/visualization/visualization.js"></script>
<script src="app/visualization/builtins/visualization-table.js"></script>
<script src="app/visualization/builtins/visualization-nvd3chart.js"></script>