Skip to content

Commit

Permalink
feat(plugin-chart-echarts): add graph echart (#918)
Browse files Browse the repository at this point in the history
  • Loading branch information
mayurnewase authored and pull[bot] committed May 6, 2024
1 parent 47e564e commit 1d2a069
Show file tree
Hide file tree
Showing 18 changed files with 1,134 additions and 9 deletions.
Original file line number Diff line number Diff line change
@@ -1,18 +1,27 @@
import buildQueryObject from './buildQueryObject';
import DatasourceKey from './DatasourceKey';
import { QueryFormData } from './types/QueryFormData';
import { QueryFieldAliases, QueryFormData } from './types/QueryFormData';
import { QueryContext, QueryObject } from './types/Query';

const WRAP_IN_ARRAY = (baseQueryObject: QueryObject) => [baseQueryObject];

export type BuildFinalQuerieObjects = (baseQueryObject: QueryObject) => QueryObject[];

export default function buildQueryContext(
formData: QueryFormData,
buildQuery: (baseQueryObject: QueryObject) => QueryObject[] = WRAP_IN_ARRAY,
options?:
| {
buildQuery?: BuildFinalQuerieObjects;
queryFields?: QueryFieldAliases;
}
| BuildFinalQuerieObjects,
): QueryContext {
const { queryFields, buildQuery = WRAP_IN_ARRAY } =
typeof options === 'function' ? { buildQuery: options, queryFields: {} } : options || {};
return {
datasource: new DatasourceKey(formData.datasource).toObject(),
force: formData.force || false,
queries: buildQuery(buildQueryObject(formData)),
queries: buildQuery(buildQueryObject(formData, queryFields)),
result_format: formData.result_format || 'json',
result_type: formData.result_type || 'full',
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@
* under the License.
*/
import { t } from '../translation';
import { removeDuplicates } from '../utils';
import { DTTM_ALIAS } from './buildQueryObject';
import getMetricLabel from './getMetricLabel';
import { QueryFields, QueryFieldAliases, FormDataResidual, QueryMode } from './types/QueryFormData';

/**
Expand Down Expand Up @@ -109,5 +111,9 @@ export default function extractQueryFields(
finalQueryFields.columns.unshift(DTTM_ALIAS);
}

// remove duplicate columns and metrics
finalQueryFields.columns = removeDuplicates(finalQueryFields.columns);
finalQueryFields.metrics = removeDuplicates(finalQueryFields.metrics, getMetricLabel);

return finalQueryFields;
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@ export default function processFilters(formData: QueryFormData): Partial<QueryFo
// (2) expressionType
// 2.1 SIMPLE (subject + operator + comparator)
// 2.2 SQL (freeform SQL expression))
const { adhoc_filters = [], extras = {}, filters = [], where } = formData;
const { adhoc_filters, extras = {}, filters = [], where } = formData;
const simpleWhere: QueryObjectFilterClause[] = filters;

const simpleHaving: QueryObjectFilterClause[] = [];
const freeformWhere: string[] = [];
if (where) freeformWhere.push(where);
const freeformHaving: string[] = [];

adhoc_filters.forEach(filter => {
(adhoc_filters || []).forEach(filter => {
const { clause } = filter;
if (isSimpleAdhocFilter(filter)) {
const filterClause = convertFilter(filter);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,8 @@ export interface BaseFormData extends TimeRange, FormDataResidual {
groupby?: QueryFormColumn[];
all_columns?: QueryFormColumn[];
/** list of filters */
adhoc_filters?: AdhocFilter[];
extra_filters?: QueryFormExtraFilter[];
adhoc_filters?: AdhocFilter[] | null;
extra_filters?: QueryFormExtraFilter[] | null;
/** order descending */
order_desc?: boolean;
/** limit number of time series */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ describe('buildQueryContext', () => {
expect(queryContext.datasource.id).toBe(5);
expect(queryContext.datasource.type).toBe('table');
expect(queryContext.force).toBe(false);
expect(queryContext.force).toBe(false);
expect(queryContext.result_format).toBe('json');
expect(queryContext.result_type).toBe('full');
});
Expand All @@ -44,4 +43,70 @@ describe('buildQueryContext', () => {
expect(queryContext.datasource.type).toBe('druid');
expect(queryContext.force).toBe(true);
});
it('should build datasource for table sources with columns', () => {
const queryContext = buildQueryContext(
{
datasource: '5__table',
granularity_sqla: 'ds',
viz_type: 'table',
source: 'source_column',
source_category: 'source_category_column',
target: 'target_column',
target_category: 'target_category_column',
},
{
queryFields: {
source: 'columns',
source_category: 'columns',
target: 'columns',
target_category: 'columns',
},
},
);
expect(queryContext.datasource.id).toBe(5);
expect(queryContext.datasource.type).toBe('table');
expect(queryContext.force).toBe(false);
expect(queryContext.result_format).toBe('json');
expect(queryContext.result_type).toBe('full');
expect(queryContext.queries).toEqual(
expect.arrayContaining([
expect.objectContaining({
columns: [
'source_column',
'source_category_column',
'target_column',
'target_category_column',
],
}),
]),
);
});
it('should build datasource for table sources and process with custom function', () => {
const queryContext = buildQueryContext(
{
datasource: '5__table',
granularity_sqla: 'ds',
viz_type: 'table',
source: 'source_column',
source_category: 'source_category_column',
target: 'target_column',
target_category: 'target_category_column',
},
function addExtraColumn(queryObject) {
return [{ ...queryObject, columns: ['dummy_column'] }];
},
);
expect(queryContext.datasource.id).toBe(5);
expect(queryContext.datasource.type).toBe('table');
expect(queryContext.force).toBe(false);
expect(queryContext.result_format).toBe('json');
expect(queryContext.result_type).toBe('full');
expect(queryContext.queries).toEqual(
expect.arrayContaining([
expect.objectContaining({
columns: ['dummy_column'],
}),
]),
);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
"@superset-ui/chart-controls": "0.17.9",
"@superset-ui/core": "0.17.9",
"@types/mathjs": "^6.0.7",
"d3-array": "^1.2.0",
"echarts": "^5.0.2",
"mathjs": "^8.0.1"
},
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
import React from 'react';
import { EchartsProps } from '../types';
import Echart from '../components/Echart';

export default function EchartsGraph({ height, width, echartOptions }: EchartsProps) {
return <Echart height={height} width={width} echartOptions={echartOptions} />;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
import { buildQueryContext, QueryFormData } from '@superset-ui/core';

export default function buildQuery(formData: QueryFormData) {
return buildQueryContext(formData, {
queryFields: {
source: 'columns',
target: 'columns',
source_category: 'columns',
target_category: 'columns',
},
});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
import { GraphSeriesOption } from 'echarts';

export const DEFAULT_GRAPH_SERIES_OPTION: GraphSeriesOption = {
zoom: 0.7,
circular: { rotateLabel: true },
force: {
initLayout: 'circular',
layoutAnimation: true,
},
edgeSymbol: ['circle', 'arrow'],
edgeSymbolSize: [10, 10],
label: {
show: true,
position: 'right',
distance: 5,
rotate: 0,
offset: [0, 0],
fontStyle: 'normal',
fontWeight: 'normal',
fontFamily: 'sans-serif',
fontSize: 12,
padding: [0, 0, 0, 0],
overflow: 'truncate',
formatter: '{b}',
},
emphasis: {
focus: 'adjacency',
lineStyle: {
width: 10,
},
},
animation: true,
animationDuration: 500,
animationEasing: 'cubicOut',
lineStyle: { color: 'source', curveness: 0.1 },
select: {
itemStyle: { borderWidth: 3 },
label: { fontWeight: 'bolder' },
},
// Ref: https://echarts.apache.org/en/option.html#series-graph.data.tooltip.formatter
// - b: data name
// - c: data value
tooltip: { formatter: '{b}: {c}' },
};

export const NORMALIZATION_LIMITS = {
minNodeSize: 10,
maxNodeSize: 60,
minEdgeWidth: 0.5,
maxEdgeWidth: 8,
};
Loading

0 comments on commit 1d2a069

Please sign in to comment.