Superset的二次开发_集成Echarts图表

安装 vim编辑 unzip解压 方便后续对文件的操作

apt-get update
apt-get install vim
apt-get install zip

接上一篇博客 docker安装完superset之后:

前端: 安装node.js,创建前端编译环境
① 在您的计算机配置中添加存储库:
curl -sL https://deb.nodesource.com/setup_10.x | bash -
② 安装node.js
apt-get install -y nodejs
③ 测试是否安装成功
node -v
npm -v

正式的二次开发添加echarts:
①注意先别着急,现在本地下载一份源码,由于我装的是0.28的版本,因此下载一份源码 ,下载完源码由于链接不生效,需要将incubator-superset-0.28\superset\assets 的assets文件夹整个复制一份到incubator-superset-0.28\superset\static\下,替换之前打不开的assets文件夹

https://github.com/apache/incubator-superset
Superset的二次开发_集成Echarts图表_第1张图片
② docker下载之后发现再src的包不完整,因此需要将刚本地下载的源码的src打包上传到docker中去。

rz  ./src.zip

注:当rz出现乱码时,使用rz -be (机器编码不一致造成的,windows文件默认是gbk编码 ,linux文件默认是 utf-8编码)

docker cp ./src.zip 3ebdf90132cb:/usr/local/lib/python3.6/site-packages/superset/static/assets/

③集成echarts图表需要7个地方需要修改,我是采用的再外面统一修改之后上传进去
注意:再此处建议用 root权限登录docker

docker exec -it -u root 3ebdf90132cb  bash
1.docker cp ./viz.py 3ebdf90132cb:/usr/local/lib/python3.6/site-packages/superset/
2.docker cp ./index.js 3ebdf90132cb:/usr/local/lib/python3.6/site-packages/superset/static/assets/src/visualizations/
3.docker cp ./echarts_bar_polar.js 3ebdf90132cb:/usr/local/lib/python3.6/site-packages/superset/static/assets/src/visualizations/
4.docker cp ./visTypes.jsx 3ebdf90132cb:/usr/local/lib/python3.6/site-packages/superset/static/assets/src/explore/
5.docker cp ./echarts_bar_polar.png 3ebdf90132cb:/usr/local/lib/python3.6/site-packages/superset/static/assets/images/viz_thumbnails/
6.vi  /usr/local/lib/python3.6/site-packages/superset/static/assets/src/modules/colors.js
7.superset/static/assets/package.json   新增  "echarts" : "^4.2.0-rc.2",

下面一步步展开来说:

第一步:superset/viz.py文件, 在BaseViz类的下方和TableViz的上方加入如下代码

class EchartsBarPolar(BaseViz):
    viz_type = 'echarts_bar_polar' #对应前端的名字
    is_timeseries = False
    def should_be_timeseries(self):
        fd = self.form_data
        conditions_met = (
            (fd.get('granularity') and fd.get('granularity') != 'all') or
            (fd.get('granularity_sqla') and fd.get('time_grain_sqla'))
        )
        if fd.get('include_time') and not conditions_met:
            raise Exception(_(
                'Pick a granularity in the Time section or '
                "uncheck 'Include Time'"))
        return fd.get('include_time')
    def query_obj(self):
        d = super(EchartsBarPolar, self).query_obj()
        fd = self.form_data
        if fd.get('all_columns') and (fd.get('groupby') or fd.get('metrics')):
            raise Exception(_(
                'Choose either fields to [Group By] and [Metrics] or '
                '[Columns], not both'))
        sort_by = fd.get('timeseries_limit_metric')
        if fd.get('all_columns'):
            d['columns'] = fd.get('all_columns')
            d['groupby'] = []
            order_by_cols = fd.get('order_by_cols') or []
            d['orderby'] = [json.loads(t) for t in order_by_cols]
        elif sort_by:
            if sort_by not in d['metrics']:
                d['metrics'] += [sort_by]
            d['orderby'] = [(sort_by, not fd.get('order_desc', True))]
        if 'percent_metrics' in fd:
            d['metrics'] = d['metrics'] + list(filter(
                lambda m: m not in d['metrics'],
                fd['percent_metrics'],
            ))
        d['is_timeseries'] = self.should_be_timeseries()
        return d
    def get_data(self, df):
        fd = self.form_data
        if not self.should_be_timeseries() and DTTM_ALIAS in df:
            del df[DTTM_ALIAS]
        return dict(
            records=df.to_dict(orient='records'),
            columns=list(df.columns),
        )

第二步:superset/static/assets/src/visualizations/index.js文件 ,
export const VIZ_TYPES里新增

echarts_bar_polar: 'echarts_bar_polar',

const vizMap里新增

[VIZ_TYPES.echarts_bar_polar]: () => loadVis(import(/*webpackChunkName: 'echarts_bar_polar' */ './echarts_bar_polar.js')),

第三步:superset/static/assets/src/visualizations目录下新增echarts_bar_polar.js文件

import echarts from 'echarts';
import {getColorFromScheme} from '../modules/colors';
function EchartsBarPolarVis(slice, payload) {
    var div = d3.select(slice.selector);
	const sliceId = 'e_bar_polar' + slice.formData.slice_id
    var html = '
'; div.html(html); var myChart = echarts.init(document.getElementById(sliceId)); var option = { angleAxis: { type: 'category', data: [], z: 10 }, radiusAxis: {}, polar: {}, series: [] }; myChart.setOption(option); const fd = slice.formData; const json = payload.data; const data = json; const records = data['records']; const data_column = data.columns; const metrics = fd.metrics; const group_by = fd.groupby; var legend_name = []; var axis_name = []; var series_data = []; for (var i = 0; i < records.length; i++) { axis_name.push(records[i][data_column[0]]); } for (var i = 0; i < metrics.length; i++) { legend_name.push(metrics[i]); var tmp_data = []; for (var j = 0; j < records.length; j++) { tmp_data.push(records[j][metrics[i]]); } series_data.push( { type: 'bar', data: tmp_data, coordinateSystem: 'polar', name: legend_name[i], stack: 'a' } ) } var option2 = { angleAxis: { data: axis_name }, series: series_data }; myChart.setOption(option2); } module.exports = EchartsBarPolarVis;

第四步:superset/static/assets/src/explore/visTypes.jsx文件,export const visTypes里新增

echarts_bar_polar: {
        label: t('Bar Polar'),
        showOnExplore: true,
        controlPanelSections: [
            {
                label: t('GROUP BY'),
                controlSetRows: [
                    ['groupby'],
                    ['metrics'],
                    ['percent_metrics'],
                    ['include_time'],
                    ['timeseries_limit_metric', 'order_desc'],
                ],
            },
            {
                label: t('NOT GROUPED BY'),
                description: t('Use this section if you want to query atomic rows'),
                controlSetRows: [
                    ['all_columns'],
                    ['order_by_cols'],
                ],
            },
            {
                label: t('Options'),
                controlSetRows: [
                    ['table_timestamp_format'],
                    ['row_limit', 'page_length'],
                    ['include_search', 'table_filter'],
                ],
            },
        ],
        controlOverrides: {
            metrics: {
                validators: [],
            },
            time_grain_sqla: {
                default: null,
            },
        },
    },

第五步:superset/static/assets/images/viz_thumbnails文件夹下放入缩略图,命名为echarts_bar_polar.png
Superset的二次开发_集成Echarts图表_第2张图片
第六步:superset/static/assets/src/modules/colors.js 文件进行修改,直接将js文件全部用如下代码覆盖

import d3 from 'd3';
import sequentialSchemes from './colorSchemes/sequential';

export const BRAND_COLOR = '#00A699';
export const PRIMARY_COLOR = { r: 0, g: 122, b: 135, a: 1 };

export const bnbColors = [
	  '#ff5a5f', // rausch
	  '#7b0051', // hackb
	  '#007A87', // kazan
	  '#00d1c1', // babu
	  '#8ce071', // lima
	  '#ffb400', // beach
	  '#b4a76c', // barol
	  '#ff8083',
	  '#cc0086',
	  '#00a1b3',
	  '#00ffeb',
	  '#bbedab',
	  '#ffd266',
	  '#cbc29a',
	  '#ff3339',
	  '#ff1ab1',
	  '#005c66',
	  '#00b3a5',
	  '#55d12e',
	  '#b37e00',
	  '#988b4e',
];

const d3Category10 = d3.scale.category10().range();
const d3Category20 = d3.scale.category20().range();
const d3Category20b = d3.scale.category20b().range();
const d3Category20c = d3.scale.category20c().range();
const googleCategory10c = [
	  '#3366cc',
	  '#dc3912',
	  '#ff9900',
	  '#109618',
	  '#990099',
	  '#0099c6',
	  '#dd4477',
	  '#66aa00',
	  '#b82e2e',
	  '#316395',
];
const googleCategory20c = [
	  '#3366cc',
	  '#dc3912',
	  '#ff9900',
	  '#109618',
	  '#990099',
	  '#0099c6',
	  '#dd4477',
	  '#66aa00',
	  '#b82e2e',
	  '#316395',
	  '#994499',
	  '#22aa99',
	  '#aaaa11',
	  '#6633cc',
	  '#e67300',
	  '#8b0707',
	  '#651067',
	  '#329262',
	  '#5574a6',
	  '#3b3eac',
];
export const ALL_COLOR_SCHEMES = {
	  bnbColors,
	  d3Category10,
	  d3Category20,
	  d3Category20b,
	  d3Category20c,
	  googleCategory10c,
	  googleCategory20c,
};

export function hexToRGB(hex, alpha = 255) {
  if (!hex) {
    return [0, 0, 0, alpha];
  }
  const r = parseInt(hex.slice(1, 3), 16);
  const g = parseInt(hex.slice(3, 5), 16);
  const b = parseInt(hex.slice(5, 7), 16);
  return [r, g, b, alpha];
}


export const getColorFromScheme = (function () {
	  const seen = {};
	  const forcedColors = {};
	  return function (s, scheme, forcedColor) {
		      if (!s) {
			            return;
			          }
		      const selectedScheme = scheme ? ALL_COLOR_SCHEMES[scheme] : ALL_COLOR_SCHEMES.bnbColors;
		      let stringifyS = String(s).toLowerCase();
		      /* next line is for superset series that should have the same color*/
		      stringifyS = stringifyS.replace('---', '');

		      if (forcedColor && !forcedColors[stringifyS]) {
			            forcedColors[stringifyS] = forcedColor;
			          }
		      if (forcedColors[stringifyS]) {
			            return forcedColors[stringifyS];
			          }

		      if (seen[selectedScheme] === undefined) {
			            seen[selectedScheme] = {};
			          }
		      if (seen[selectedScheme][stringifyS] === undefined) {
			            seen[selectedScheme][stringifyS] = Object.keys(seen[selectedScheme]).length;
			          }
		      /* eslint consistent-return: 0 */
		      return selectedScheme[seen[selectedScheme][stringifyS] % selectedScheme.length];
		    };
}());

export const colorScalerFactory = function (colors, data, accessor, extents, outputRGBA = false) {
  // Returns a linear scaler our of an array of color
  if (!Array.isArray(colors)) {
    /* eslint no-param-reassign: 0 */
    colors = sequentialSchemes[colors];
  }
  let ext = [0, 1];
  if (extents) {
    ext = extents;
  }
  if (data) {
    ext = d3.extent(data, accessor);
  }
  const chunkSize = (ext[1] - ext[0]) / (colors.length - 1);
  const points = colors.map((col, i) => ext[0] + (i * chunkSize));
  const scaler = d3.scale.linear().domain(points).range(colors).clamp(true);
  if (outputRGBA) {
    return v => hexToRGB(scaler(v));
  }
  return scaler;
};

第七步:superset/static/assets/package.json 文件中 新增

"echarts" : "^4.2.0-rc.2",

Superset的二次开发_集成Echarts图表_第3张图片
以上全部都齐全之后,在superset/static/assets 目录下执行:

npm install
npm run dev 

之后我习惯重启一下docker

dockers ps
docker restart 3ebdf90132cb

还有需要致谢一下两位大佬的博客,让我有许多学习地方,特别感谢~ 笔芯♥
https://blog.csdn.net/qq_33172735/article/details/87708374
https://blog.csdn.net/qq_33703137/article/details/87874277#commentsedit

你可能感兴趣的:(Superset)