mirror of
https://github.com/apache/zeppelin
synced 2026-05-24 09:38:26 +00:00
feat: Support multiple charts
This commit is contained in:
parent
97be629336
commit
e1fcc2e234
3 changed files with 289 additions and 239 deletions
|
|
@ -14,36 +14,36 @@ limitations under the License.
|
|||
|
||||
<div class="panel panel-default" style="margin-top: 10px; margin-bottom: 11px;">
|
||||
|
||||
<!-- panel: axis (configured column) information -->
|
||||
<div class="panel-heading"
|
||||
style="padding: 6px 12px 6px 12px; font-size: 13px;">
|
||||
<span style="vertical-align: middle; display: inline-block; margin-top: 3px;">Configured Columns</span>
|
||||
<span style="float: right;">
|
||||
<div class="btn-group" role="group" aria-label="...">
|
||||
<div type="button" ng-click="clearConfig()"
|
||||
class="btn btn-default" style="padding: 2px 5px 2px 5px;">
|
||||
<i class="fa fa-trash-o" aria-hidden="true"></i>
|
||||
</div>
|
||||
<div type="button" ng-if="config.panel.columnPanelOpened"
|
||||
ng-click="toggleColumnPanel()"
|
||||
class="btn btn-default" style="padding: 2px 5px 2px 5px;">
|
||||
<i class="fa fa-minus" style="font-size: 12px;" aria-hidden="true"></i>
|
||||
</div>
|
||||
<div type="button" ng-if="!config.panel.columnPanelOpened"
|
||||
ng-click="toggleColumnPanel()"
|
||||
class="btn btn-default" style="padding: 2px 5px 2px 5px;">
|
||||
<i class="fa fa-expand" style="font-size: 11px;" aria-hidden="true"></i>
|
||||
</div>
|
||||
</div>
|
||||
</span>
|
||||
<div style="clear: both;"></div> <!-- to fix previous span which has float: right -->
|
||||
</div>
|
||||
<div class="panel-body" ng-if="config.panel.columnPanelOpened"
|
||||
style="margin-top: 7px; padding-top: 9px; padding-bottom: 4px;">
|
||||
<div class="row">
|
||||
<div class="col-sm-4 col-md-3"
|
||||
ng-repeat="axisSpec in axisSpecs">
|
||||
<span class="columns lightBold">
|
||||
<!-- panel: axis (configured column) information -->
|
||||
<div class="panel-heading"
|
||||
style="padding: 6px 12px 6px 12px; font-size: 13px;">
|
||||
<span style="vertical-align: middle; display: inline-block; margin-top: 3px;">Configured Columns</span>
|
||||
<span style="float: right;">
|
||||
<div class="btn-group" role="group" aria-label="...">
|
||||
<div type="button" ng-click="clearConfig()"
|
||||
class="btn btn-default" style="padding: 2px 5px 2px 5px;">
|
||||
<i class="fa fa-trash-o" aria-hidden="true"></i>
|
||||
</div>
|
||||
<div type="button" ng-if="config.panel.columnPanelOpened"
|
||||
ng-click="toggleColumnPanel()"
|
||||
class="btn btn-default" style="padding: 2px 5px 2px 5px;">
|
||||
<i class="fa fa-minus" style="font-size: 12px;" aria-hidden="true"></i>
|
||||
</div>
|
||||
<div type="button" ng-if="!config.panel.columnPanelOpened"
|
||||
ng-click="toggleColumnPanel()"
|
||||
class="btn btn-default" style="padding: 2px 5px 2px 5px;">
|
||||
<i class="fa fa-expand" style="font-size: 11px;" aria-hidden="true"></i>
|
||||
</div>
|
||||
</div>
|
||||
</span>
|
||||
<div style="clear: both;"></div> <!-- to fix previous span which has float: right -->
|
||||
</div>
|
||||
<div class="panel-body" ng-if="config.panel.columnPanelOpened"
|
||||
style="margin-top: 7px; padding-top: 9px; padding-bottom: 4px;">
|
||||
<div class="row">
|
||||
<div class="col-sm-4 col-md-3"
|
||||
ng-repeat="axisSpec in config.axisSpecs[config.chart.current]">
|
||||
<div class="columns lightBold">
|
||||
<!-- axis name -->
|
||||
<span class="label label-default"
|
||||
style="font-weight: 300; font-size: 13px; margin-left: 1px;">
|
||||
|
|
@ -68,18 +68,18 @@ limitations under the License.
|
|||
<!-- axis box: in case of single dimension -->
|
||||
<ul data-drop="true"
|
||||
ng-if="isSingleDimensionAxis(axisSpec)"
|
||||
ng-model="config.axis[axisSpec.name]"
|
||||
ng-model="config.axis[config.chart.current][axisSpec.name]"
|
||||
jqyoui-droppable="{onDrop:'axisChanged(axisSpec)'}"
|
||||
class="list-unstyled"
|
||||
style="height:36px; border-radius: 6px; margin-top: 7px; overflow: visible !important;">
|
||||
<li ng-if="config.axis[axisSpec.name]">
|
||||
<li ng-if="config.axis[config.chart.current][axisSpec.name]">
|
||||
|
||||
<!-- in case of axis is single dimension and not aggregator -->
|
||||
<div ng-if="!isAggregatorAxis(axisSpec)"
|
||||
class="btn btn-default btn-xs"
|
||||
style="background-color: #EFEFEF;">
|
||||
{{ getAxisInSingleDimension(axisSpec).name }}
|
||||
<span class="fa fa-close" ng-click="removeFromSingleDimension(axisSpec.name)"></span>
|
||||
{{ getSingleDimensionAxis(axisSpec).name }}
|
||||
<span class="fa fa-close" ng-click="removeFromAxis(null, axisSpec)"></span>
|
||||
</div>
|
||||
|
||||
<!-- in case of axis is single dimension and aggregator -->
|
||||
|
|
@ -88,18 +88,18 @@ limitations under the License.
|
|||
class="btn btn-default btn-xs dropdown-toggle"
|
||||
style="background-color: #EFEFEF; "
|
||||
type="button" data-toggle="dropdown">
|
||||
{{getAxisInSingleDimension(axisSpec).name | limitTo: 30}}{{getAxisInSingleDimension(axisSpec).name > 30 ? '...' : ''}}
|
||||
{{getSingleDimensionAxis(axisSpec).name | limitTo: 30}}{{getSingleDimensionAxis(axisSpec).name > 30 ? '...' : ''}}
|
||||
<span style="color:#717171;">
|
||||
<span class="lightBold" style="text-transform: uppercase;">{{getAxisInSingleDimension(axisSpec).aggr}}</span>
|
||||
<span class="lightBold" style="text-transform: uppercase;">{{getSingleDimensionAxis(axisSpec).aggr}}</span>
|
||||
</span>
|
||||
<span class="fa fa-close" ng-click="removeFromSingleDimension(axisSpec.name)"></span>
|
||||
<span class="fa fa-close" ng-click="removeFromAxis(null, axisSpec)"></span>
|
||||
</div>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li ng-click="singleDimensionAggregatorChanged($index, axisSpec.name, 'sum')"><a>sum</a></li>
|
||||
<li ng-click="singleDimensionAggregatorChanged($index, axisSpec.name, 'count')"><a>count</a></li>
|
||||
<li ng-click="singleDimensionAggregatorChanged($index, axisSpec.name, 'avg')"><a>avg</a></li>
|
||||
<li ng-click="singleDimensionAggregatorChanged($index, axisSpec.name, 'min')"><a>min</a></li>
|
||||
<li ng-click="singleDimensionAggregatorChanged($index, axisSpec.name, 'max')"><a>max</a></li>
|
||||
<li ng-click="aggregatorChanged(null, axisSpec, 'sum')"><a>sum</a></li>
|
||||
<li ng-click="aggregatorChanged(null, axisSpec, 'count')"><a>count</a></li>
|
||||
<li ng-click="aggregatorChanged(null, axisSpec, 'avg')"><a>avg</a></li>
|
||||
<li ng-click="aggregatorChanged(null, axisSpec, 'min')"><a>min</a></li>
|
||||
<li ng-click="aggregatorChanged(null, axisSpec, 'max')"><a>max</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
|
|
@ -109,121 +109,126 @@ limitations under the License.
|
|||
<!-- axis box: in case of multiple dimensions -->
|
||||
<ul data-drop="true"
|
||||
ng-if="!isSingleDimensionAxis(axisSpec) "
|
||||
ng-model="config.axis[axisSpec.name]"
|
||||
ng-model="config.axis[config.chart.current][axisSpec.name]"
|
||||
jqyoui-droppable="{multiple: true, onDrop:'axisChanged(axisSpec)'}"
|
||||
class="list-unstyled"
|
||||
style="height:130px; border-radius: 6px; margin-top: 7px;">
|
||||
<li ng-repeat="col in config.axis[axisSpec.name]">
|
||||
style="height: 108px; border-radius: 6px; margin-top: 7px; overflow: auto !important;">
|
||||
|
||||
<span ng-repeat="col in config.axis[config.chart.current][axisSpec.name]">
|
||||
|
||||
<!-- in case of axis is multiple dimensions and not aggregator -->
|
||||
<div ng-if="!isAggregatorAxis(axisSpec)"
|
||||
class="btn btn-default btn-xs"
|
||||
style="background-color: #EFEFEF;">
|
||||
<span ng-if="!isAggregatorAxis(axisSpec)"
|
||||
class="btn btn-default btn-xs"
|
||||
style="background-color: #EFEFEF; margin: 2px 0px 0px 2px;">
|
||||
{{col.name}}
|
||||
<span class="fa fa-close" ng-click="removeFromMultipleDimension($index, axisSpec.name)"></span>
|
||||
</div>
|
||||
<span class="fa fa-close" ng-click="removeFromAxis($index, axisSpec)"></span>
|
||||
</span>
|
||||
|
||||
<!-- in case of axis is multiple dimension and aggregator -->
|
||||
<div class="btn-group">
|
||||
<div ng-if="isAggregatorAxis(axisSpec)"
|
||||
class="btn btn-default btn-xs dropdown-toggle"
|
||||
style="background-color: #EFEFEF;"
|
||||
type="button" data-toggle="dropdown">
|
||||
<span class="btn-group">
|
||||
<span ng-if="isAggregatorAxis(axisSpec)"
|
||||
class="btn btn-default btn-xs dropdown-toggle"
|
||||
style="background-color: #EFEFEF; margin: 2px 0px 0px 2px;"
|
||||
type="button" data-toggle="dropdown">
|
||||
{{col.name | limitTo: 30}}{{col.name.length > 30 ? '...' : ''}}
|
||||
<span style="color:#717171;">
|
||||
<span class="lightBold" style="text-transform: uppercase;">{{col.aggr}}</span>
|
||||
<span style="color:#717171; margin: 0px;">
|
||||
<span class="lightBold"
|
||||
style="text-transform: uppercase; margin: 0px;">{{col.aggr}}
|
||||
</span>
|
||||
</span>
|
||||
<span class="fa fa-close" ng-click="removeFromMultipleDimension($index, axisSpec.name)"></span>
|
||||
</div>
|
||||
<span class="fa fa-close" style="margin: 0px;" ng-click="removeFromAxis($index, axisSpec)"></span>
|
||||
</span>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li ng-click="multipleDimensionAggregatorChanged($index, axisSpec.name, 'sum')"><a>sum</a></li>
|
||||
<li ng-click="multipleDimensionAggregatorChanged($index, axisSpec.name, 'count')"><a>count</a></li>
|
||||
<li ng-click="multipleDimensionAggregatorChanged($index, axisSpec.name, 'avg')"><a>avg</a></li>
|
||||
<li ng-click="multipleDimensionAggregatorChanged($index, axisSpec.name, 'min')"><a>min</a></li>
|
||||
<li ng-click="multipleDimensionAggregatorChanged($index, axisSpec.name, 'max')"><a>max</a></li>
|
||||
<li ng-click="aggregatorChanged($index, axisSpec, 'sum')"><a>sum</a></li>
|
||||
<li ng-click="aggregatorChanged($index, axisSpec, 'count')"><a>count</a></li>
|
||||
<li ng-click="aggregatorChanged($index, axisSpec, 'avg')"><a>avg</a></li>
|
||||
<li ng-click="aggregatorChanged($index, axisSpec, 'min')"><a>min</a></li>
|
||||
<li ng-click="aggregatorChanged($index, axisSpec, 'max')"><a>max</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</span>
|
||||
|
||||
</li>
|
||||
</span>
|
||||
</ul>
|
||||
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- panel: available columns -->
|
||||
<div class="panel-heading" ng-if="config.panel.columnPanelOpened"
|
||||
style="padding: 6px 12px 6px 12px; font-size: 13px; border-top: 1px solid #ddd; border-top-left-radius: 0px; border-top-right-radius: 0px;">
|
||||
<span>Available Columns</span>
|
||||
</div>
|
||||
<div class="panel-body" ng-if="config.panel.columnPanelOpened"
|
||||
style="padding: 8px; margin-top: 3px;">
|
||||
<ul class="noDot">
|
||||
<li class="liVertical" ng-repeat="column in columns">
|
||||
<div class="btn btn-default btn-xs"
|
||||
style="background-color: #EFEFEF;"
|
||||
data-drag="true"
|
||||
data-jqyoui-options="{revert: 'invalid', helper: 'clone'}"
|
||||
ng-model="columns"
|
||||
jqyoui-draggable="{index: {{$index}}, placeholder: 'keep'}">
|
||||
{{column.name | limitTo: 30}}{{column.name.length > 30 ? '...' : ''}}
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<!-- panel: available columns -->
|
||||
<div class="panel-heading" ng-if="config.panel.columnPanelOpened"
|
||||
style="padding: 6px 12px 6px 12px; font-size: 13px; border-top: 1px solid #ddd; border-top-left-radius: 0px; border-top-right-radius: 0px;">
|
||||
<span>Available Columns</span>
|
||||
</div>
|
||||
<div class="panel-body" ng-if="config.panel.columnPanelOpened"
|
||||
style="padding: 8px; margin-top: 3px;">
|
||||
<ul class="noDot">
|
||||
<li class="liVertical" ng-repeat="column in columns">
|
||||
<div class="btn btn-default btn-xs"
|
||||
style="background-color: #EFEFEF;"
|
||||
data-drag="true"
|
||||
data-jqyoui-options="{revert: 'invalid', helper: 'clone'}"
|
||||
ng-model="columns"
|
||||
jqyoui-draggable="{index: {{$index}}, placeholder: 'keep'}">
|
||||
{{column.name | limitTo: 30}}{{column.name.length > 30 ? '...' : ''}}
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- panel: parameter information -->
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading" style="padding: 6px 12px 6px 12px; font-size: 13px;">
|
||||
<span style="vertical-align: middle; display: inline-block; margin-top: 3px;">Dynamic Parameters</span>
|
||||
<span style="float: right;">
|
||||
<div class="btn-group" role="group" aria-label="...">
|
||||
<div type="button" ng-click="parameterChanged()"
|
||||
class="btn btn-default" style="padding: 2px 5px 2px 5px;">
|
||||
<i class="fa fa-floppy-o" aria-hidden="true"></i>
|
||||
</div>
|
||||
|
||||
<div type="button" ng-if="config.panel.parameterPanelOpened"
|
||||
ng-click="toggleParameterPanel()"
|
||||
class="btn btn-default" style="padding: 2px 5px 2px 5px;">
|
||||
<i class="fa fa-minus" style="font-size: 12px;" aria-hidden="true"></i>
|
||||
</div>
|
||||
<div type="button" ng-if="!config.panel.parameterPanelOpened"
|
||||
ng-click="toggleParameterPanel()"
|
||||
class="btn btn-default" style="padding: 2px 5px 2px 5px;">
|
||||
<i class="fa fa-expand" style="font-size: 11px;" aria-hidden="true"></i>
|
||||
</div>
|
||||
<div class="panel-heading" style="padding: 6px 12px 6px 12px; font-size: 13px;">
|
||||
<span style="vertical-align: middle; display: inline-block; margin-top: 3px;">Dynamic Parameters</span>
|
||||
<span style="float: right;">
|
||||
<div class="btn-group" role="group" aria-label="...">
|
||||
<div type="button" ng-click="parameterChanged()"
|
||||
class="btn btn-default" style="padding: 2px 5px 2px 5px;">
|
||||
<i class="fa fa-floppy-o" aria-hidden="true"></i>
|
||||
</div>
|
||||
|
||||
<div type="button" ng-if="config.panel.parameterPanelOpened"
|
||||
ng-click="toggleParameterPanel()"
|
||||
class="btn btn-default" style="padding: 2px 5px 2px 5px;">
|
||||
<i class="fa fa-minus" style="font-size: 12px;" aria-hidden="true"></i>
|
||||
</div>
|
||||
<div type="button" ng-if="!config.panel.parameterPanelOpened"
|
||||
ng-click="toggleParameterPanel()"
|
||||
class="btn btn-default" style="padding: 2px 5px 2px 5px;">
|
||||
<i class="fa fa-expand" style="font-size: 11px;" aria-hidden="true"></i>
|
||||
</div>
|
||||
</div>
|
||||
</span>
|
||||
<div style="clear: both;"></div> <!-- to fix previous span which has float: right -->
|
||||
</div>
|
||||
<div class="panel-body" ng-if="config.panel.parameterPanelOpened"
|
||||
style="padding-top: 13px; padding-bottom: 13px;">
|
||||
<table class="table table-striped">
|
||||
<tr>
|
||||
<th style="font-size: 12px; font-style: italic">Name</th>
|
||||
<th style="font-size: 13px; font-style: italic">Type</th>
|
||||
<th style="font-size: 12px; font-style: italic">Description</th>
|
||||
<th style="font-size: 12px; font-style: italic">Value</th>
|
||||
</tr>
|
||||
<tr>
|
||||
</tr>
|
||||
|
||||
<tr data-ng-repeat="paramSpec in config.paramSpecs[config.chart.current]">
|
||||
<td style="font-weight: 400; vertical-align: middle;">{{paramSpec.name}}</td>
|
||||
<td style="font-weight: 400; vertical-align: middle;">{{paramSpec.type}}</td>
|
||||
<td style="font-weight: 400; vertical-align: middle;">{{paramSpec.description}}</td>
|
||||
<td>
|
||||
<div class="input-group">
|
||||
<input type="text" class="form-control"
|
||||
style="font-weight: 400; font-size: 12px; vertical-align:middle; border-radius: 5px;"
|
||||
data-ng-model="config.parameter[config.chart.current][paramSpec.name]" />
|
||||
</div>
|
||||
</span>
|
||||
<div style="clear: both;"></div> <!-- to fix previous span which has float: right -->
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="panel-body" ng-if="config.panel.parameterPanelOpened"
|
||||
style="padding-top: 13px; padding-bottom: 13px;">
|
||||
<table class="table table-striped">
|
||||
<tr>
|
||||
<th style="font-size: 12px; font-style: italic">Name</th>
|
||||
<th style="font-size: 13px; font-style: italic">Type</th>
|
||||
<th style="font-size: 12px; font-style: italic">Description</th>
|
||||
<th style="font-size: 12px; font-style: italic">Value</th>
|
||||
</tr>
|
||||
<tr>
|
||||
</tr>
|
||||
<tr data-ng-repeat="paramSpec in paramSpecs">
|
||||
<td style="font-weight: 400; vertical-align: middle;">{{paramSpec.name}}</td>
|
||||
<td style="font-weight: 400; vertical-align: middle;">{{paramSpec.type}}</td>
|
||||
<td style="font-weight: 400; vertical-align: middle;">{{paramSpec.description}}</td>
|
||||
<td>
|
||||
<div class="input-group">
|
||||
<input type="text" class="form-control"
|
||||
style="font-weight: 400; font-size: 12px; vertical-align:middle; border-radius: 5px;"
|
||||
data-ng-model="config.parameter[paramSpec.name]" />
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -27,37 +27,110 @@ export function isGroup(axisSpec) { return axisSpec.group; }
|
|||
export function isGroupBase(axisSpec) { return axisSpec.groupBase; }
|
||||
export function isSingleDimension(axisSpec) { return axisSpec.dimension === 'single'; }
|
||||
|
||||
export function clearConfig(configInstance, axisSpecs, paramSpecs) {
|
||||
delete configInstance.panel
|
||||
delete configInstance.axis
|
||||
delete configInstance.parameter
|
||||
/**
|
||||
* before: { name: { ... } }
|
||||
* after: [ { name, ... } ]
|
||||
*
|
||||
* add the `name` field while converting to array to easily manipulate
|
||||
*/
|
||||
export function getSpecs(specObject) {
|
||||
const specs = [];
|
||||
for (let name in specObject) {
|
||||
const singleSpec = specObject[name];
|
||||
singleSpec.name = name;
|
||||
specs.push(singleSpec);
|
||||
}
|
||||
|
||||
return initializeConfig(configInstance, axisSpecs, paramSpecs)
|
||||
return specs
|
||||
}
|
||||
|
||||
export function initializeConfig(config, axisSpecs, paramSpecs) {
|
||||
export function getAvailableChartNames(charts) {
|
||||
const available = []
|
||||
for (var name in charts) {
|
||||
available.push(name)
|
||||
}
|
||||
|
||||
/** initialize config.axis */
|
||||
return available
|
||||
}
|
||||
|
||||
export function removeDuplicatedColumnsInMultiDimensionAxis(config, axisSpec) {
|
||||
if (isSingleDimension(axisSpec)) { return config; }
|
||||
|
||||
const columns = config.axis[config.chart.current][axisSpec.name]
|
||||
const uniqObject = columns.reduce((acc, col) => {
|
||||
if (!acc[col.name]) { acc[col.name] = col; }
|
||||
return acc
|
||||
}, {});
|
||||
|
||||
const filtered = [] ;
|
||||
for (let name in uniqObject) {
|
||||
const col = uniqObject[name];
|
||||
filtered.push(col)
|
||||
}
|
||||
|
||||
config.axis[config.chart.current][axisSpec.name] = filtered
|
||||
return config
|
||||
}
|
||||
|
||||
export function clearConfig(config) {
|
||||
delete config.chart; /** Object: contains current, available chart */
|
||||
delete config.panel; /** Object: persisted config values for panel */
|
||||
delete config.spec; /** Object: axis, parameter spec for each chart */
|
||||
|
||||
delete config.axis; /** Object: persisted axis for each chart */
|
||||
delete config.parameter; /** Object: persisted parameter for each chart */
|
||||
delete config.axisSpecs; /** Object: persisted axisSpecs for each chart */
|
||||
delete config.paramSpecs; /** Object: persisted paramSpecs for each chart */
|
||||
}
|
||||
|
||||
export function initializeConfig(config, spec) {
|
||||
// if (!config.spec || config.spec.version !== spec.version) {
|
||||
// clearConfig(config)
|
||||
// }
|
||||
|
||||
const availableCharts = getAvailableChartNames(spec.charts);
|
||||
|
||||
if (!config.spec) { config.spec = spec; }
|
||||
|
||||
if (!config.chart) {
|
||||
config.chart = {};
|
||||
config.chart.current = availableCharts[0];
|
||||
config.chart.available = availableCharts;
|
||||
}
|
||||
|
||||
/** initialize config.axis, config.axisSpecs for each chart */
|
||||
if (!config.axis) { config.axis = {}; }
|
||||
for (let i = 0; i < axisSpecs.length; i++) {
|
||||
const axisSpec = axisSpecs[i];
|
||||
const persistedConfig = config.axis[axisSpec.name];
|
||||
if (!config.axisSpecs) { config.axisSpecs = {}; }
|
||||
for (let i = 0; i < availableCharts.length; i++) {
|
||||
const chartName = availableCharts[i];
|
||||
|
||||
// behavior of jqyoui-element depends on its model (ng-model)
|
||||
// so, we have to initialize its underlying ng-model to array if it's not array
|
||||
if (!isSingleDimension(axisSpec) && !Array.isArray(persistedConfig)) {
|
||||
config.axis[axisSpec.name] = [];
|
||||
} else if (isSingleDimension(axisSpec) && Array.isArray(persistedConfig)) {
|
||||
config.axis[axisSpec.name] = {};
|
||||
if (!config.axis[chartName]) { config.axis[chartName] = {}; }
|
||||
const axisSpecs = getSpecs(spec.charts[chartName].axis)
|
||||
if (!config.axisSpecs[chartName]) { config.axisSpecs[chartName] = axisSpecs; }
|
||||
|
||||
for (let i = 0; i < axisSpecs.length; i++) {
|
||||
const axisSpec = axisSpecs[i]
|
||||
if (!isSingleDimension(axisSpec) && !Array.isArray(config.axis[chartName][axisSpec.name])) {
|
||||
config.axis[chartName][axisSpec.name] = []
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** initialize config.parameter*/
|
||||
/** initialize config.parameter for each chart */
|
||||
if (!config.parameter) { config.parameter = {}; }
|
||||
for (let i = 0; i < paramSpecs.length; i++) {
|
||||
const paramSpec = paramSpecs[i];
|
||||
if (!config.parameter[paramSpec.name]) {
|
||||
config.parameter[paramSpec.name] = paramSpec.defaultValue;
|
||||
if (!config.paramSpecs) { config.paramSpecs = {}; }
|
||||
for (let i = 0; i < availableCharts.length; i++) {
|
||||
const chartName = availableCharts[i];
|
||||
|
||||
if (!config.parameter[chartName]) { config.parameter[chartName] = {}; }
|
||||
const paramSpecs = getSpecs(spec.charts[chartName].parameter)
|
||||
if (!config.paramSpecs[chartName]) { config.paramSpecs[chartName] = paramSpecs; }
|
||||
|
||||
for (let i = 0; i < paramSpecs.length; i++) {
|
||||
const paramSpec = paramSpecs[i];
|
||||
if (!config.parameter[chartName][paramSpec.name]) {
|
||||
config.parameter[chartName][paramSpec.name] = paramSpec.defaultValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,8 +16,8 @@ import Transformation from './transformation';
|
|||
|
||||
import {
|
||||
isAggregator, isGroup, isGroupBase, isSingleDimension,
|
||||
clearConfig, initializeConfig,
|
||||
groupAndAggregateRows, getGroupAndAggrColumns,
|
||||
clearConfig, initializeConfig, removeDuplicatedColumnsInMultiDimensionAxis,
|
||||
// groupAndAggregateRows, getGroupAndAggrColumns,
|
||||
} from './advanced-transformation-util';
|
||||
|
||||
const SETTING_TEMPLATE = 'app/tabledata/advanced-transformation-setting.html';
|
||||
|
|
@ -28,69 +28,42 @@ class AdvancedTransformation extends Transformation {
|
|||
|
||||
this.columns = []; /** [{ name, index, comment }] */
|
||||
this.props = {};
|
||||
this.spec = spec
|
||||
|
||||
/**
|
||||
* spec.axis: [{ name, dimension, type, aggregator, group }]
|
||||
* spec.parameter: [{ name, type, defaultValue, description }]
|
||||
*
|
||||
* add the `name` field while converting to array to easily manipulate
|
||||
*/
|
||||
const axisSpecs = [];
|
||||
for (let name in spec.axis) {
|
||||
const axisSpec = spec.axis[name];
|
||||
axisSpec.name = name;
|
||||
axisSpecs.push(axisSpec);
|
||||
}
|
||||
this.axisSpecs = axisSpecs;
|
||||
|
||||
const paramSpecs = [];
|
||||
for (let name in spec.parameter) {
|
||||
const parameterSpec = spec.parameter[name];
|
||||
parameterSpec.name = name;
|
||||
paramSpecs.push(parameterSpec);
|
||||
}
|
||||
this.paramSpecs = paramSpecs;
|
||||
|
||||
initializeConfig(this.config, axisSpecs, paramSpecs)
|
||||
initializeConfig(config, spec);
|
||||
}
|
||||
|
||||
getSetting() {
|
||||
const self = this; /** for closure */
|
||||
/**
|
||||
* config: { axis, parameter }
|
||||
*/
|
||||
let configInstance = self.config; /** for closure */
|
||||
const configInstance = self.config; /** for closure */
|
||||
|
||||
return {
|
||||
template: SETTING_TEMPLATE,
|
||||
scope: {
|
||||
config: configInstance,
|
||||
columns: self.columns,
|
||||
axisSpecs: self.axisSpecs,
|
||||
paramSpecs: self.paramSpecs,
|
||||
|
||||
getAxisAnnotation: (axisSpec) => {
|
||||
return `${axisSpec.name} (${axisSpec.type})`
|
||||
},
|
||||
|
||||
getAxisInSingleDimension: (axisSpec) => {
|
||||
return configInstance.axis[axisSpec.name]
|
||||
getSingleDimensionAxis: (axisSpec) => {
|
||||
return configInstance.axis[configInstance.chart.current][axisSpec.name]
|
||||
},
|
||||
|
||||
toggleColumnPanel: () => {
|
||||
configInstance.panel.columnPanelOpened =
|
||||
!configInstance.panel.columnPanelOpened
|
||||
self.emitConfig(configInstance)
|
||||
},
|
||||
|
||||
clearConfig: () => {
|
||||
clearConfig(configInstance, this.axisSpecs, this.paramSpecs)
|
||||
configInstance.panel.columnPanelOpened = !configInstance.panel.columnPanelOpened
|
||||
self.emitConfig(configInstance)
|
||||
},
|
||||
|
||||
toggleParameterPanel: () => {
|
||||
configInstance.panel.parameterPanelOpened =
|
||||
!configInstance.panel.parameterPanelOpened
|
||||
configInstance.panel.parameterPanelOpened = !configInstance.panel.parameterPanelOpened
|
||||
self.emitConfig(configInstance)
|
||||
},
|
||||
|
||||
clearConfig: () => {
|
||||
clearConfig(configInstance)
|
||||
initializeConfig(configInstance, self.spec)
|
||||
self.emitConfig(configInstance)
|
||||
},
|
||||
|
||||
|
|
@ -99,63 +72,62 @@ class AdvancedTransformation extends Transformation {
|
|||
isAggregatorAxis: (axisSpec) => { return isAggregator(axisSpec) },
|
||||
isSingleDimensionAxis: (axisSpec) => { return isSingleDimension(axisSpec) },
|
||||
|
||||
parameterChanged: (paramSpec) => {
|
||||
self.emitConfig(configInstance)
|
||||
},
|
||||
|
||||
singleDimensionAggregatorChanged: (colIndex, axisName, aggregator) => {
|
||||
configInstance.axis[axisName].aggr = aggregator
|
||||
self.emitConfig(configInstance)
|
||||
},
|
||||
|
||||
multipleDimensionAggregatorChanged: (colIndex, axisName, aggregator) => {
|
||||
configInstance.axis[axisName][colIndex].aggr = aggregator
|
||||
self.emitConfig(configInstance)
|
||||
},
|
||||
|
||||
parameterChanged: (paramSpec) => { self.emitConfig(configInstance) },
|
||||
axisChanged: function(e, ui, axisSpec) {
|
||||
removeDuplicatedColumnsInMultiDimensionAxis(configInstance, axisSpec)
|
||||
|
||||
self.emitConfig(configInstance)
|
||||
},
|
||||
|
||||
removeFromSingleDimension: function(axisName) {
|
||||
configInstance.axis[axisName] = null
|
||||
aggregatorChanged: (colIndex, axisSpec, aggregator) => {
|
||||
if (isSingleDimension(axisSpec)) {
|
||||
configInstance.axis[configInstance.chart.current][axisSpec.name].aggr = aggregator
|
||||
} else {
|
||||
configInstance.axis[configInstance.chart.current][axisSpec.name][colIndex].aggr = aggregator
|
||||
}
|
||||
self.emitConfig(configInstance)
|
||||
},
|
||||
|
||||
removeFromMultipleDimension: function(colIndex, axisName) {
|
||||
configInstance.axis[axisName].splice(colIndex, 1)
|
||||
removeFromAxis: function(colIndex, axisSpec) {
|
||||
if (isSingleDimension(axisSpec)) {
|
||||
configInstance.axis[configInstance.chart.current][axisSpec.name] = null
|
||||
} else {
|
||||
configInstance.axis[configInstance.chart.current][axisSpec.name].splice(colIndex, 1)
|
||||
}
|
||||
self.emitConfig(configInstance)
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
transform(tableData) {
|
||||
this.columns = tableData.columns; /** used in `getSetting` */
|
||||
const axisSpecs = this.axisSpecs; /** specs */
|
||||
const axisConfig = this.config.axis; /** configured columns */
|
||||
|
||||
const columns = getGroupAndAggrColumns(axisSpecs, axisConfig);
|
||||
const groupBaseColumns = columns.groupBase;
|
||||
const groupColumns = columns.group;
|
||||
const aggregatorColumns = columns.aggregator;
|
||||
const otherColumns = columns.others;
|
||||
|
||||
const grouped = groupAndAggregateRows(tableData.rows, groupBaseColumns, groupColumns, aggregatorColumns)
|
||||
|
||||
return {
|
||||
row: {
|
||||
all: tableData.rows,
|
||||
grouped: grouped, /** [ { group<String>, rows<Array>, aggregatedValues<Object> } ] */
|
||||
},
|
||||
column: {
|
||||
all: tableData.columns,
|
||||
groupBase: groupBaseColumns,
|
||||
group: groupColumns,
|
||||
aggregator: aggregatorColumns,
|
||||
others: otherColumns,
|
||||
}
|
||||
}
|
||||
return tableData
|
||||
// const axisSpecs = this.axisSpecs; /** specs */
|
||||
// const axisConfig = this.config.axis; /** configured columns */
|
||||
//
|
||||
// const columns = getGroupAndAggrColumns(axisSpecs, axisConfig);
|
||||
// const groupBaseColumns = columns.groupBase;
|
||||
// const groupColumns = columns.group;
|
||||
// const aggregatorColumns = columns.aggregator;
|
||||
// const otherColumns = columns.others;
|
||||
//
|
||||
// const grouped = groupAndAggregateRows(tableData.rows, groupBaseColumns, groupColumns, aggregatorColumns)
|
||||
//
|
||||
// return {
|
||||
// row: {
|
||||
// all: tableData.rows,
|
||||
// grouped: grouped, /** [ { group<String>, rows<Array>, aggregatedValues<Object> } ] */
|
||||
// },
|
||||
// column: {
|
||||
// all: tableData.columns,
|
||||
// groupBase: groupBaseColumns,
|
||||
// group: groupColumns,
|
||||
// aggregator: aggregatorColumns,
|
||||
// others: otherColumns,
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue