feat: migrate heatmap, horizon, iframe and markup (#367)

* feat: migrate heatmap

* feat: add horizon, iframe and markup
This commit is contained in:
Krist Wongsuphasawat 2020-04-15 15:44:48 -07:00 committed by Yongjie Zhao
parent d5b51202f7
commit 12bf14b7cd
41 changed files with 2896 additions and 1 deletions

View File

@ -8,6 +8,10 @@ const packages = readdirSync(basePath).filter(name => {
return stat.isSymbolicLink();
});
const PLUGIN_PACKAGES_PATH_REGEXP = new RegExp(
`${path.resolve(__dirname, '../../../plugins/(legacy-)*(plugin|preset)-')}.+/src`,
);
module.exports = {
addons: [
'@storybook/preset-typescript',
@ -20,6 +24,17 @@ module.exports = {
'../storybook/stories/**/*Stories.[tj]sx',
],
webpackFinal: config => {
// Make sure babel is applied to the package src
// These are excluded by the default rule
// because they reside in node_modules
config.module.rules.push({
include: PLUGIN_PACKAGES_PATH_REGEXP,
exclude: /node_modules/,
test: /\.jsx?$/,
use: config.module.rules[0].use,
});
config.module.rules.push({
test: /\.tsx?$/,
use: [
@ -30,7 +45,8 @@ module.exports = {
});
config.resolve.extensions.push('.ts', '.tsx');
// let webpack know where to find the source code
// Let webpack know where to find the source code
Object.assign(config.resolve.alias, {
...packages.reduce(
(acc, name) => ({

View File

@ -41,6 +41,10 @@
"@superset-ui/connection": "0.12.18",
"@superset-ui/legacy-plugin-chart-calendar": "0.12.18",
"@superset-ui/legacy-plugin-chart-chord": "0.12.18",
"@superset-ui/legacy-plugin-chart-heatmap": "^0.11.15",
"@superset-ui/legacy-plugin-chart-horizon": "^0.11.15",
"@superset-ui/legacy-plugin-chart-iframe": "^0.11.15",
"@superset-ui/legacy-plugin-chart-markup": "^0.11.15",
"@superset-ui/legacy-plugin-chart-sankey": "^0.11.15",
"@superset-ui/legacy-plugin-chart-sunburst": "^0.11.15",
"@superset-ui/legacy-plugin-chart-table": "0.12.18",

View File

@ -0,0 +1,85 @@
import React from 'react';
import { SuperChart } from '@superset-ui/chart';
import HeatmapChartPlugin from '@superset-ui/legacy-plugin-chart-heatmap';
import data from './data';
new HeatmapChartPlugin().configure({ key: 'heatmap' }).register();
export default {
title: 'Legacy Chart Plugins|legacy-plugin-chart-heatmap',
};
export const basic = () => (
<SuperChart
chartType="heatmap"
width={400}
height={400}
formData={{
allColumnsX: 'source',
allColumnsY: 'target',
bottomMargin: 'auto',
canvasImageRendering: 'pixelated',
leftMargin: 'auto',
linearColorScheme: 'blue_white_yellow',
metric: 'sum__value',
normalized: false,
showLegend: true,
showPerc: true,
showValues: false,
sortXAxis: 'alpha_asc',
sortYAxis: 'alpha_asc',
xscaleInterval: '1',
yAxisBounds: [null, null],
yAxisFormat: '.3s',
yscaleInterval: '1',
}}
queryData={{
data: {
records: data,
extents: [0.1, 24.9],
},
}}
/>
);
export const withNullData = () => (
<SuperChart
chartType="heatmap"
width={400}
height={400}
formData={{
allColumnsX: 'source',
allColumnsY: 'target',
bottomMargin: 'auto',
canvasImageRendering: 'pixelated',
leftMargin: 'auto',
linearColorScheme: 'blue_white_yellow',
metric: 'sum__value',
normalized: false,
showLegend: true,
showPerc: true,
showValues: false,
sortXAxis: 'alpha_asc',
sortYAxis: 'alpha_asc',
xscaleInterval: '1',
yAxisBounds: [null, null],
yAxisFormat: '.3s',
yscaleInterval: '1',
}}
queryData={{
data: {
records: [
...data,
{
x: null,
y: 'Electricity and heat',
v: 25.9,
perc: 0.43,
rank: 1.0,
},
],
extents: [0.1, 24.9],
},
}}
/>
);

View File

@ -0,0 +1,163 @@
export default [
{
x: 'Energy',
y: 'Electricity and heat',
v: 24.9,
perc: 1.0,
rank: 1.0,
},
{
x: 'Energy',
y: 'Industry',
v: 14.7,
perc: 0.5887096774193549,
rank: 0.9882352941176471,
},
{
x: 'Energy',
y: 'Transportation',
v: 14.3,
perc: 0.5725806451612905,
rank: 0.9764705882352941,
},
{
x: 'Deforestation',
y: 'Carbon Dioxide',
v: 10.9,
perc: 0.435483870967742,
rank: 0.9588235294117647,
},
{
x: 'Land Use Change',
y: 'Deforestation',
v: 10.9,
perc: 0.435483870967742,
rank: 0.9588235294117647,
},
{
x: 'Road',
y: 'Carbon Dioxide',
v: 10.5,
perc: 0.4193548387096775,
rank: 0.9352941176470588,
},
{
x: 'Transportation',
y: 'Road',
v: 10.5,
perc: 0.4193548387096775,
rank: 0.9352941176470588,
},
{
x: 'Residential Buildings',
y: 'Carbon Dioxide',
v: 10.2,
perc: 0.40725806451612906,
rank: 0.9176470588235294,
},
{
x: 'Energy',
y: 'Other Fuel Combustion',
v: 8.6,
perc: 0.342741935483871,
rank: 0.9058823529411765,
},
{
x: 'Other Industry',
y: 'Carbon Dioxide',
v: 6.6,
perc: 0.26209677419354843,
rank: 0.8941176470588236,
},
{
x: 'Commercial Buildings',
y: 'Carbon Dioxide',
v: 6.3,
perc: 0.25000000000000006,
rank: 0.8823529411764706,
},
{
x: 'Agriculture',
y: 'Livestock and Manure',
v: 5.4,
perc: 0.2137096774193549,
rank: 0.8705882352941177,
},
{
x: 'Agriculture',
y: 'Agriculture Soils',
v: 5.2,
perc: 0.20564516129032262,
rank: 0.8470588235294118,
},
{
x: 'Agriculture Soils',
y: 'Nitrous Oxide',
v: 5.2,
perc: 0.20564516129032262,
rank: 0.8470588235294118,
},
{
x: 'Oil and Gas Processing',
y: 'Methane',
v: 2.8,
perc: 0.10887096774193548,
rank: 0.6705882352941176,
},
{
x: 'Electricity and heat',
y: 'Other Industry',
v: 2.7,
perc: 0.10483870967741937,
rank: 0.6470588235294118,
},
{
x: 'Rail - Ship and Other Transport',
y: 'Carbon Dioxide',
v: 2.5,
perc: 0.09677419354838711,
rank: 0.6294117647058823,
},
{
x: 'Transportation',
y: 'Rail - Ship and Other Transport',
v: 2.5,
perc: 0.09677419354838711,
rank: 0.6294117647058823,
},
{
x: 'Electricity and heat',
y: 'T and D Losses',
v: 2.2,
perc: 0.08467741935483872,
rank: 0.6058823529411764,
},
{
x: 'T and D Losses',
y: 'Carbon Dioxide',
v: 2.2,
perc: 0.08467741935483872,
rank: 0.6058823529411764,
},
{
x: 'Electricity and heat',
y: 'Unallocated Fuel Combustion',
v: 2.0,
perc: 0.07661290322580645,
rank: 0.5882352941176471,
},
{
x: 'Industry',
y: 'Cement',
v: 1.9,
perc: 0.07258064516129033,
rank: 0.5764705882352941,
},
{
x: 'Other Fuel Combustion',
y: 'Unallocated Fuel Combustion',
v: 1.8,
perc: 0.0685483870967742,
rank: 0.5647058823529412,
},
];

View File

@ -0,0 +1,23 @@
import React from 'react';
import { SuperChart } from '@superset-ui/chart';
import HorizonChartPlugin from '@superset-ui/legacy-plugin-chart-horizon';
import data from './data';
new HorizonChartPlugin().configure({ key: 'horizon' }).register();
export default {
title: 'Legacy Chart Plugins|legacy-plugin-chart-horizon',
};
export const basic = () => (
<SuperChart
chartType="horizon"
width={400}
height={400}
queryData={{ data }}
formData={{
horizonColorScale: 'series',
seriesHeight: '25',
}}
/>
);

View File

@ -0,0 +1,908 @@
/* eslint-disable sort-keys */
export default [
{
key: ['Christopher'],
values: [
{
x: -157766400000.0,
y: 24703,
},
{
x: -126230400000.0,
y: 27861,
},
{
x: -94694400000.0,
y: 29436,
},
{
x: -63158400000.0,
y: 31463,
},
{
x: -31536000000.0,
y: 35718,
},
{
x: 0.0,
y: 41758,
},
{
x: 31536000000.0,
y: 48172,
},
{
x: 63072000000.0,
y: 52092,
},
{
x: 94694400000.0,
y: 48217,
},
{
x: 126230400000.0,
y: 48476,
},
{
x: 157766400000.0,
y: 46438,
},
{
x: 189302400000.0,
y: 45086,
},
{
x: 220924800000.0,
y: 46610,
},
{
x: 252460800000.0,
y: 47107,
},
{
x: 283996800000.0,
y: 50514,
},
{
x: 315532800000.0,
y: 48969,
},
{
x: 347155200000.0,
y: 50108,
},
{
x: 378691200000.0,
y: 59055,
},
{
x: 410227200000.0,
y: 59188,
},
{
x: 441763200000.0,
y: 59859,
},
{
x: 473385600000.0,
y: 59516,
},
{
x: 504921600000.0,
y: 56633,
},
{
x: 536457600000.0,
y: 54466,
},
{
x: 567993600000.0,
y: 52996,
},
{
x: 599616000000.0,
y: 53205,
},
{
x: 631152000000.0,
y: 52322,
},
{
x: 662688000000.0,
y: 47109,
},
{
x: 694224000000.0,
y: 42470,
},
{
x: 725846400000.0,
y: 38257,
},
{
x: 757382400000.0,
y: 34823,
},
{
x: 788918400000.0,
y: 32728,
},
{
x: 820454400000.0,
y: 30988,
},
{
x: 852076800000.0,
y: 29179,
},
{
x: 883612800000.0,
y: 27083,
},
{
x: 915148800000.0,
y: 25700,
},
{
x: 946684800000.0,
y: 24959,
},
{
x: 978307200000.0,
y: 23180,
},
{
x: 1009843200000.0,
y: 21731,
},
{
x: 1041379200000.0,
y: 20793,
},
{
x: 1072915200000.0,
y: 19739,
},
{
x: 1104537600000.0,
y: 19190,
},
{
x: 1136073600000.0,
y: 19674,
},
{
x: 1167609600000.0,
y: 19986,
},
{
x: 1199145600000.0,
y: 17771,
},
],
},
{
key: ['Daniel'],
values: [
{
x: -157766400000.0,
y: 24717,
},
{
x: -126230400000.0,
y: 23168,
},
{
x: -94694400000.0,
y: 22128,
},
{
x: -63158400000.0,
y: 21940,
},
{
x: -31536000000.0,
y: 23103,
},
{
x: 0.0,
y: 23427,
},
{
x: 31536000000.0,
y: 21704,
},
{
x: 63072000000.0,
y: 22022,
},
{
x: 94694400000.0,
y: 23579,
},
{
x: 126230400000.0,
y: 23759,
},
{
x: 157766400000.0,
y: 23720,
},
{
x: 189302400000.0,
y: 24621,
},
{
x: 220924800000.0,
y: 25971,
},
{
x: 252460800000.0,
y: 26324,
},
{
x: 283996800000.0,
y: 28403,
},
{
x: 315532800000.0,
y: 29759,
},
{
x: 347155200000.0,
y: 30868,
},
{
x: 378691200000.0,
y: 32480,
},
{
x: 410227200000.0,
y: 34580,
},
{
x: 441763200000.0,
y: 36370,
},
{
x: 473385600000.0,
y: 38409,
},
{
x: 504921600000.0,
y: 36440,
},
{
x: 536457600000.0,
y: 35746,
},
{
x: 567993600000.0,
y: 34589,
},
{
x: 599616000000.0,
y: 34909,
},
{
x: 631152000000.0,
y: 33740,
},
{
x: 662688000000.0,
y: 30826,
},
{
x: 694224000000.0,
y: 29047,
},
{
x: 725846400000.0,
y: 28587,
},
{
x: 757382400000.0,
y: 27978,
},
{
x: 788918400000.0,
y: 26631,
},
{
x: 820454400000.0,
y: 25029,
},
{
x: 852076800000.0,
y: 23873,
},
{
x: 883612800000.0,
y: 23089,
},
{
x: 915148800000.0,
y: 22623,
},
{
x: 946684800000.0,
y: 22250,
},
{
x: 978307200000.0,
y: 20925,
},
{
x: 1009843200000.0,
y: 21247,
},
{
x: 1041379200000.0,
y: 20980,
},
{
x: 1072915200000.0,
y: 20914,
},
{
x: 1104537600000.0,
y: 20130,
},
{
x: 1136073600000.0,
y: 19946,
},
{
x: 1167609600000.0,
y: 20108,
},
{
x: 1199145600000.0,
y: 18695,
},
],
},
{
key: ['David'],
values: [
{
x: -157766400000.0,
y: 67646,
},
{
x: -126230400000.0,
y: 66207,
},
{
x: -94694400000.0,
y: 66581,
},
{
x: -63158400000.0,
y: 63531,
},
{
x: -31536000000.0,
y: 63502,
},
{
x: 0.0,
y: 61570,
},
{
x: 31536000000.0,
y: 52948,
},
{
x: 63072000000.0,
y: 46218,
},
{
x: 94694400000.0,
y: 40968,
},
{
x: 126230400000.0,
y: 41654,
},
{
x: 157766400000.0,
y: 39019,
},
{
x: 189302400000.0,
y: 39165,
},
{
x: 220924800000.0,
y: 40407,
},
{
x: 252460800000.0,
y: 40533,
},
{
x: 283996800000.0,
y: 41898,
},
{
x: 315532800000.0,
y: 41743,
},
{
x: 347155200000.0,
y: 40486,
},
{
x: 378691200000.0,
y: 40283,
},
{
x: 410227200000.0,
y: 39048,
},
{
x: 441763200000.0,
y: 38346,
},
{
x: 473385600000.0,
y: 38395,
},
{
x: 504921600000.0,
y: 37021,
},
{
x: 536457600000.0,
y: 36672,
},
{
x: 567993600000.0,
y: 35214,
},
{
x: 599616000000.0,
y: 35139,
},
{
x: 631152000000.0,
y: 33661,
},
{
x: 662688000000.0,
y: 30347,
},
{
x: 694224000000.0,
y: 28344,
},
{
x: 725846400000.0,
y: 26947,
},
{
x: 757382400000.0,
y: 24784,
},
{
x: 788918400000.0,
y: 22967,
},
{
x: 820454400000.0,
y: 22941,
},
{
x: 852076800000.0,
y: 21824,
},
{
x: 883612800000.0,
y: 20816,
},
{
x: 915148800000.0,
y: 20267,
},
{
x: 946684800000.0,
y: 19695,
},
{
x: 978307200000.0,
y: 19281,
},
{
x: 1009843200000.0,
y: 18600,
},
{
x: 1041379200000.0,
y: 18557,
},
{
x: 1072915200000.0,
y: 18315,
},
{
x: 1104537600000.0,
y: 18017,
},
{
x: 1136073600000.0,
y: 17510,
},
{
x: 1167609600000.0,
y: 17400,
},
{
x: 1199145600000.0,
y: 16049,
},
],
},
{
key: ['James'],
values: [
{
x: -157766400000.0,
y: 67506,
},
{
x: -126230400000.0,
y: 65036,
},
{
x: -94694400000.0,
y: 61554,
},
{
x: -63158400000.0,
y: 60584,
},
{
x: -31536000000.0,
y: 59824,
},
{
x: 0.0,
y: 61597,
},
{
x: 31536000000.0,
y: 54463,
},
{
x: 63072000000.0,
y: 46960,
},
{
x: 94694400000.0,
y: 42782,
},
{
x: 126230400000.0,
y: 41258,
},
{
x: 157766400000.0,
y: 39471,
},
{
x: 189302400000.0,
y: 38203,
},
{
x: 220924800000.0,
y: 39916,
},
{
x: 252460800000.0,
y: 39783,
},
{
x: 283996800000.0,
y: 39237,
},
{
x: 315532800000.0,
y: 39185,
},
{
x: 347155200000.0,
y: 38176,
},
{
x: 378691200000.0,
y: 38750,
},
{
x: 410227200000.0,
y: 36228,
},
{
x: 441763200000.0,
y: 35728,
},
{
x: 473385600000.0,
y: 35750,
},
{
x: 504921600000.0,
y: 33955,
},
{
x: 536457600000.0,
y: 32552,
},
{
x: 567993600000.0,
y: 32418,
},
{
x: 599616000000.0,
y: 32658,
},
{
x: 631152000000.0,
y: 32288,
},
{
x: 662688000000.0,
y: 30460,
},
{
x: 694224000000.0,
y: 28450,
},
{
x: 725846400000.0,
y: 26193,
},
{
x: 757382400000.0,
y: 24706,
},
{
x: 788918400000.0,
y: 22691,
},
{
x: 820454400000.0,
y: 21122,
},
{
x: 852076800000.0,
y: 20368,
},
{
x: 883612800000.0,
y: 19651,
},
{
x: 915148800000.0,
y: 18508,
},
{
x: 946684800000.0,
y: 17939,
},
{
x: 978307200000.0,
y: 17023,
},
{
x: 1009843200000.0,
y: 16905,
},
{
x: 1041379200000.0,
y: 16832,
},
{
x: 1072915200000.0,
y: 16459,
},
{
x: 1104537600000.0,
y: 16046,
},
{
x: 1136073600000.0,
y: 16139,
},
{
x: 1167609600000.0,
y: 15821,
},
{
x: 1199145600000.0,
y: 14920,
},
],
},
{
key: ['Jennifer'],
values: [
{
x: -157766400000.0,
y: 15174,
},
{
x: -126230400000.0,
y: 18166,
},
{
x: -94694400000.0,
y: 18193,
},
{
x: -63158400000.0,
y: 26778,
},
{
x: -31536000000.0,
y: 33618,
},
{
x: 0.0,
y: 46022,
},
{
x: 31536000000.0,
y: 56607,
},
{
x: 63072000000.0,
y: 63400,
},
{
x: 94694400000.0,
y: 62229,
},
{
x: 126230400000.0,
y: 62854,
},
{
x: 157766400000.0,
y: 57960,
},
{
x: 189302400000.0,
y: 59255,
},
{
x: 220924800000.0,
y: 58682,
},
{
x: 252460800000.0,
y: 56064,
},
{
x: 283996800000.0,
y: 56472,
},
{
x: 315532800000.0,
y: 58130,
},
{
x: 347155200000.0,
y: 56779,
},
{
x: 378691200000.0,
y: 56867,
},
{
x: 410227200000.0,
y: 54136,
},
{
x: 441763200000.0,
y: 50375,
},
{
x: 473385600000.0,
y: 42500,
},
{
x: 504921600000.0,
y: 36063,
},
{
x: 536457600000.0,
y: 32613,
},
{
x: 567993600000.0,
y: 27798,
},
{
x: 599616000000.0,
y: 24006,
},
{
x: 631152000000.0,
y: 22160,
},
{
x: 662688000000.0,
y: 20616,
},
{
x: 694224000000.0,
y: 17783,
},
{
x: 725846400000.0,
y: 15704,
},
{
x: 757382400000.0,
y: 13976,
},
{
x: 788918400000.0,
y: 12655,
},
{
x: 820454400000.0,
y: 11703,
},
{
x: 852076800000.0,
y: 11803,
},
{
x: 883612800000.0,
y: 10671,
},
{
x: 915148800000.0,
y: 10593,
},
{
x: 946684800000.0,
y: 9308,
},
{
x: 978307200000.0,
y: 8843,
},
{
x: 1009843200000.0,
y: 8317,
},
{
x: 1041379200000.0,
y: 7475,
},
{
x: 1072915200000.0,
y: 6079,
},
{
x: 1104537600000.0,
y: 5413,
},
{
x: 1136073600000.0,
y: 4736,
},
{
x: 1167609600000.0,
y: 4001,
},
{
x: 1199145600000.0,
y: 3010,
},
],
},
];

View File

@ -0,0 +1,21 @@
import React from 'react';
import { SuperChart } from '@superset-ui/chart';
import IframeChartPlugin from '@superset-ui/legacy-plugin-chart-iframe';
new IframeChartPlugin().configure({ key: 'iframe' }).register();
export default {
title: 'Legacy Chart Plugins|legacy-plugin-chart-iframe',
};
export const basic = () => (
<SuperChart
chartType="iframe"
width={400}
height={400}
queryData={{}}
formData={{
url: 'https://www.youtube.com/embed/jbkSRLYSojo',
}}
/>
);

View File

@ -0,0 +1,24 @@
import React from 'react';
import { SuperChart } from '@superset-ui/chart';
import MarkupChartPlugin from '@superset-ui/legacy-plugin-chart-markup';
new MarkupChartPlugin().configure({ key: 'markup' }).register();
export default {
title: 'Legacy Chart Plugins|legacy-plugin-chart-markup',
};
export const basic = () => (
<SuperChart
chartType="markup"
width={400}
height={400}
queryData={{
data: {
html:
'<div><b>hello</b> <i>world</i><div><img src="https://avatars3.githubusercontent.com/u/42724554?s=200&v=4" style="width: 80px" />',
},
}}
formData={{ vizType: 'markup' }}
/>
);

View File

@ -0,0 +1,32 @@
## @superset-ui/legacy-plugin-chart-heatmap
[![Version](https://img.shields.io/npm/v/@superset-ui/legacy-plugin-chart-heatmap.svg?style=flat-square)](https://img.shields.io/npm/v/@superset-ui/legacy-plugin-chart-heatmap.svg?style=flat-square)
[![David (path)](https://img.shields.io/david/apache-superset/superset-ui-plugins.svg?path=packages%2Fsuperset-ui-legacy-plugin-chart-heatmap&style=flat-square)](https://david-dm.org/apache-superset/superset-ui-plugins?path=packages/superset-ui-legacy-plugin-chart-heatmap)
This plugin provides Heatmap for Superset.
### Usage
Configure `key`, which can be any `string`, and register the plugin. This `key` will be used to lookup this chart throughout the app.
```js
import HeatmapChartPlugin from '@superset-ui/legacy-plugin-chart-heatmap';
new HeatmapChartPlugin()
.configure({ key: 'heatmap' })
.register();
```
Then use it via `SuperChart`. See [storybook](https://apache-superset.github.io/superset-ui-plugins/?selectedKind=plugin-chart-heatmap) for more details.
```js
<SuperChart
chartType="heatmap"
width={600}
height={600}
formData={...}
queryData={{
data: {...},
}}
/>
```

View File

@ -0,0 +1,42 @@
{
"name": "@superset-ui/legacy-plugin-chart-heatmap",
"version": "0.11.15",
"description": "Superset Legacy Chart - Heatmap",
"sideEffects": [
"*.css"
],
"main": "lib/index.js",
"module": "esm/index.js",
"files": [
"esm",
"lib"
],
"repository": {
"type": "git",
"url": "git+https://github.com/apache-superset/superset-ui-plugins.git"
},
"keywords": [
"superset"
],
"author": "Superset",
"license": "Apache-2.0",
"bugs": {
"url": "https://github.com/apache-superset/superset-ui-plugins/issues"
},
"homepage": "https://github.com/apache-superset/superset-ui-plugins#readme",
"publishConfig": {
"access": "public"
},
"dependencies": {
"d3": "^3.5.17",
"d3-svg-legend": "^1.x",
"d3-tip": "^0.9.1",
"prop-types": "^15.6.2"
},
"peerDependencies": {
"@superset-ui/chart": "^0.12.0",
"@superset-ui/color": "^0.12.0",
"@superset-ui/number-format": "^0.12.0",
"@superset-ui/translation": "^0.12.0"
}
}

View File

@ -0,0 +1,72 @@
/**
* 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.
*/
.superset-legacy-chart-heatmap {
position: relative;
top: 0;
left: 0;
height: 100%;
}
.superset-legacy-chart-heatmap .axis text {
font: 12px sans-serif;
text-rendering: optimizeLegibility;
fill: #555;
}
.superset-legacy-chart-heatmap .background-rect {
stroke: #ddd;
fill-opacity: 0;
pointer-events: all;
}
.superset-legacy-chart-heatmap .axis path,
.superset-legacy-chart-heatmap .axis line {
fill: none;
stroke: #ddd;
shape-rendering: crispEdges;
}
.superset-legacy-chart-heatmap canvas,
.superset-legacy-chart-heatmap img {
image-rendering: optimizeSpeed; /* Older versions of FF */
image-rendering: -moz-crisp-edges; /* FF 6.0+ */
image-rendering: -webkit-optimize-contrast; /* Safari */
image-rendering: -o-crisp-edges; /* OS X & Windows Opera (12.02+) */
image-rendering: pixelated; /* Awesome future-browsers */
-ms-interpolation-mode: nearest-neighbor; /* IE */
}
.superset-legacy-chart-heatmap .legendCells text {
font-size: 10px;
font-weight: normal;
opacity: 0;
}
.superset-legacy-chart-heatmap .legendCells .cell:first-child text {
opacity: 1;
}
.superset-legacy-chart-heatmap .legendCells .cell:last-child text {
opacity: 1;
}
.dashboard .superset-legacy-chart-heatmap .axis text {
font-size: 10px;
opacity: 0.75;
}

View File

@ -0,0 +1,366 @@
/**
* 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.
*/
/* eslint-disable func-names, no-plusplus, react/sort-prop-types */
import d3 from 'd3';
import PropTypes from 'prop-types';
import 'd3-svg-legend';
import d3tip from 'd3-tip';
import { getSequentialSchemeRegistry } from '@superset-ui/color';
import { getNumberFormatter, NumberFormats } from '@superset-ui/number-format';
import './vendor/d3tip.css';
import './Heatmap.css';
const propTypes = {
data: PropTypes.shape({
records: PropTypes.arrayOf(
PropTypes.shape({
x: PropTypes.string,
y: PropTypes.string,
v: PropTypes.number,
perc: PropTypes.number,
rank: PropTypes.number,
}),
),
extents: PropTypes.arrayOf(PropTypes.number),
}),
width: PropTypes.number,
height: PropTypes.number,
bottomMargin: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
colorScheme: PropTypes.string,
columnX: PropTypes.string,
columnY: PropTypes.string,
leftMargin: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
metric: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
normalized: PropTypes.bool,
numberFormat: PropTypes.string,
showLegend: PropTypes.bool,
showPercentage: PropTypes.bool,
showValues: PropTypes.bool,
sortXAxis: PropTypes.string,
sortYAxis: PropTypes.string,
xScaleInterval: PropTypes.number,
yScaleInterval: PropTypes.number,
yAxisBounds: PropTypes.arrayOf(PropTypes.number),
};
function cmp(a, b) {
return a > b ? 1 : -1;
}
// Inspired from http://bl.ocks.org/mbostock/3074470
// https://jsfiddle.net/cyril123/h0reyumq/
function Heatmap(element, props) {
const {
data,
width,
height,
bottomMargin,
canvasImageRendering,
colorScheme,
columnX,
columnY,
leftMargin,
metric,
normalized,
numberFormat,
showLegend,
showPercentage,
showValues,
sortXAxis,
sortYAxis,
xScaleInterval,
yScaleInterval,
yAxisBounds,
} = props;
const { records, extents } = data;
const margin = {
top: 10,
right: 10,
bottom: 35,
left: 35,
};
const valueFormatter = getNumberFormatter(numberFormat);
// Dynamically adjusts based on max x / y category lengths
function adjustMargins() {
const pixelsPerCharX = 4.5; // approx, depends on font size
const pixelsPerCharY = 6; // approx, depends on font size
let longestX = 1;
let longestY = 1;
records.forEach(datum => {
longestX = Math.max(longestX, (datum.x && datum.x.toString().length) || 1);
longestY = Math.max(longestY, (datum.y && datum.y.toString().length) || 1);
});
if (leftMargin === 'auto') {
margin.left = Math.ceil(Math.max(margin.left, pixelsPerCharY * longestY));
} else {
margin.left = leftMargin;
}
if (showLegend) {
margin.right += 40;
}
margin.bottom =
bottomMargin === 'auto'
? Math.ceil(Math.max(margin.bottom, pixelsPerCharX * longestX))
: bottomMargin;
}
function ordScale(k, rangeBands, sortMethod) {
let domain = {};
const actualKeys = {}; // hack to preserve type of keys when number
records.forEach(d => {
domain[d[k]] = (domain[d[k]] || 0) + d.v;
actualKeys[d[k]] = d[k];
});
// Not usgin object.keys() as it converts to strings
const keys = Object.keys(actualKeys).map(s => actualKeys[s]);
if (sortMethod === 'alpha_asc') {
domain = keys.sort(cmp);
} else if (sortMethod === 'alpha_desc') {
domain = keys.sort(cmp).reverse();
} else if (sortMethod === 'value_desc') {
domain = Object.keys(domain).sort((a, b) => (domain[a] > domain[b] ? -1 : 1));
} else if (sortMethod === 'value_asc') {
domain = Object.keys(domain).sort((a, b) => (domain[b] > domain[a] ? -1 : 1));
}
if (k === 'y' && rangeBands) {
domain.reverse();
}
if (rangeBands) {
return d3.scale.ordinal().domain(domain).rangeBands(rangeBands);
}
return d3.scale.ordinal().domain(domain).range(d3.range(domain.length));
}
// eslint-disable-next-line no-param-reassign
element.innerHTML = '';
const matrix = {};
adjustMargins();
const hmWidth = width - (margin.left + margin.right);
const hmHeight = height - (margin.bottom + margin.top);
const fp = getNumberFormatter(NumberFormats.PERCENT);
const xScale = ordScale('x', null, sortXAxis);
const yScale = ordScale('y', null, sortYAxis);
const xRbScale = ordScale('x', [0, hmWidth], sortXAxis);
const yRbScale = ordScale('y', [hmHeight, 0], sortYAxis);
const X = 0;
const Y = 1;
const heatmapDim = [xRbScale.domain().length, yRbScale.domain().length];
const minBound = yAxisBounds[0] || 0;
const maxBound = yAxisBounds[1] || 1;
const colorScale = getSequentialSchemeRegistry()
.get(colorScheme)
.createLinearScale([minBound, maxBound]);
const scale = [
d3.scale.linear().domain([0, heatmapDim[X]]).range([0, hmWidth]),
d3.scale.linear().domain([0, heatmapDim[Y]]).range([0, hmHeight]),
];
const container = d3.select(element);
container.classed('superset-legacy-chart-heatmap', true);
const canvas = container
.append('canvas')
.attr('width', heatmapDim[X])
.attr('height', heatmapDim[Y])
.style('width', `${hmWidth}px`)
.style('height', `${hmHeight}px`)
.style('image-rendering', canvasImageRendering)
.style('left', `${margin.left}px`)
.style('top', `${margin.top}px`)
.style('position', 'absolute');
const svg = container
.append('svg')
.attr('width', width)
.attr('height', height)
.style('position', 'relative');
if (showValues) {
const cells = svg
.selectAll('rect')
.data(records)
.enter()
.append('g')
.attr('transform', `translate(${margin.left}, ${margin.top})`);
cells
.append('text')
.attr('transform', d => `translate(${xRbScale(d.x)}, ${yRbScale(d.y)})`)
.attr('y', yRbScale.rangeBand() / 2)
.attr('x', xRbScale.rangeBand() / 2)
.attr('text-anchor', 'middle')
.attr('dy', '.35em')
.text(d => valueFormatter(d.v))
.attr('font-size', `${Math.min(yRbScale.rangeBand(), xRbScale.rangeBand()) / 3}px`)
.attr('fill', d => (d.v >= extents[1] / 2 ? 'white' : 'black'));
}
if (showLegend) {
const colorLegend = d3.legend
.color()
.labelFormat(valueFormatter)
.scale(colorScale)
.shapePadding(0)
.cells(10)
.shapeWidth(10)
.shapeHeight(10)
.labelOffset(3);
svg
.append('g')
.attr('transform', `translate(${width - 40}, ${margin.top})`)
.call(colorLegend);
}
const tip = d3tip()
.attr('class', 'd3-tip')
.offset(function () {
const k = d3.mouse(this);
const x = k[0] - hmWidth / 2;
return [k[1] - 20, x];
})
.html(function () {
let s = '';
const k = d3.mouse(this);
const m = Math.floor(scale[0].invert(k[0]));
const n = Math.floor(scale[1].invert(k[1]));
const metricLabel = typeof metric === 'object' ? metric.label : metric;
if (m in matrix && n in matrix[m]) {
const obj = matrix[m][n];
s += `<div><b>${columnX}: </b>${obj.x}<div>`;
s += `<div><b>${columnY}: </b>${obj.y}<div>`;
s += `<div><b>${metricLabel}: </b>${valueFormatter(obj.v)}<div>`;
if (showPercentage) {
s += `<div><b>%: </b>${fp(normalized ? obj.rank : obj.perc)}<div>`;
}
tip.style('display', null);
} else {
// this is a hack to hide the tooltip because we have map it to a single <rect>
// d3-tip toggles opacity and calling hide here is undone by the lib after this call
tip.style('display', 'none');
}
return s;
});
const rect = svg
.append('g')
.attr('transform', `translate(${margin.left}, ${margin.top})`)
.append('rect')
.classed('background-rect', true)
.on('mousemove', tip.show)
.on('mouseout', tip.hide)
.attr('width', hmWidth)
.attr('height', hmHeight);
rect.call(tip);
const xAxis = d3.svg
.axis()
.scale(xRbScale)
.outerTickSize(0)
.tickValues(xRbScale.domain().filter((d, i) => !(i % xScaleInterval)))
.orient('bottom');
const yAxis = d3.svg
.axis()
.scale(yRbScale)
.outerTickSize(0)
.tickValues(yRbScale.domain().filter((d, i) => !(i % yScaleInterval)))
.orient('left');
svg
.append('g')
.attr('class', 'x axis')
.attr('transform', `translate(${margin.left},${margin.top + hmHeight})`)
.call(xAxis)
.selectAll('text')
.attr('x', -4)
.attr('y', 10)
.attr('dy', '0.3em')
.style('text-anchor', 'end')
.attr('transform', 'rotate(-45)');
svg
.append('g')
.attr('class', 'y axis')
.attr('transform', `translate(${margin.left},${margin.top})`)
.call(yAxis);
const context = canvas.node().getContext('2d');
context.imageSmoothingEnabled = false;
// Compute the pixel colors; scaled by CSS.
function createImageObj() {
const imageObj = new Image();
const image = context.createImageData(heatmapDim[0], heatmapDim[1]);
const pixs = {};
records.forEach(d => {
const c = d3.rgb(colorScale(normalized ? d.rank : d.perc));
const x = xScale(d.x);
const y = yScale(d.y);
pixs[x + y * xScale.domain().length] = c;
if (matrix[x] === undefined) {
matrix[x] = {};
}
if (matrix[x][y] === undefined) {
matrix[x][y] = d;
}
});
let p = -1;
for (let i = 0; i < heatmapDim[0] * heatmapDim[1]; i++) {
let c = pixs[i];
let alpha = 255;
if (c === undefined) {
c = d3.rgb('#F00');
alpha = 0;
}
image.data[++p] = c.r;
image.data[++p] = c.g;
image.data[++p] = c.b;
image.data[++p] = alpha;
}
context.putImageData(image, 0, 0);
imageObj.src = canvas.node().toDataURL();
}
createImageObj();
}
Heatmap.displayName = 'Heatmap';
Heatmap.propTypes = propTypes;
export default Heatmap;

View File

@ -0,0 +1,22 @@
/**
* 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 { reactify } from '@superset-ui/chart';
import Component from './Heatmap';
export default reactify(Component);

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

View File

@ -0,0 +1,40 @@
/**
* 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 { t } from '@superset-ui/translation';
import { ChartMetadata, ChartPlugin } from '@superset-ui/chart';
import transformProps from './transformProps';
import thumbnail from './images/thumbnail.png';
const metadata = new ChartMetadata({
credits: ['http://bl.ocks.org/mbostock/3074470'],
description: '',
name: t('Heatmap'),
thumbnail,
useLegacyApi: true,
});
export default class HeatmapChartPlugin extends ChartPlugin {
constructor() {
super({
loadChart: () => import('./ReactHeatmap.js'),
metadata,
transformProps,
});
}
}

View File

@ -0,0 +1,63 @@
/**
* 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.
*/
export default function transformProps(chartProps) {
const { width, height, formData, queryData } = chartProps;
const {
bottomMargin,
canvasImageRendering,
allColumnsX,
allColumnsY,
linearColorScheme,
leftMargin,
metric,
normalized,
showLegend,
showPerc,
showValues,
sortXAxis,
sortYAxis,
xscaleInterval,
yscaleInterval,
yAxisBounds,
yAxisFormat,
} = formData;
return {
width,
height,
data: queryData.data,
bottomMargin,
canvasImageRendering,
colorScheme: linearColorScheme,
columnX: allColumnsX,
columnY: allColumnsY,
leftMargin,
metric,
normalized,
numberFormat: yAxisFormat,
showLegend,
showPercentage: showPerc,
showValues,
sortXAxis,
sortYAxis,
xScaleInterval: parseInt(xscaleInterval, 10),
yScaleInterval: parseInt(yscaleInterval, 10),
yAxisBounds,
};
}

View File

@ -0,0 +1,74 @@
/**
* 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.
*/
/* from d3-tip */
.d3-tip {
line-height: 1;
padding: 12px;
background: rgba(0, 0, 0, 0.8);
color: #fff;
border-radius: 2px;
pointer-events: none;
z-index: 1000;
}
/* Creates a small triangle extender for the tooltip */
.d3-tip:after {
box-sizing: border-box;
display: inline;
font-size: 10px;
width: 100%;
line-height: 1;
color: rgba(0, 0, 0, 0.8);
position: absolute;
pointer-events: none;
}
/* Northward tooltips */
.d3-tip.n:after {
content: '\25BC';
margin: -1px 0 0 0;
top: 100%;
left: 0;
text-align: center;
}
/* Eastward tooltips */
.d3-tip.e:after {
content: '\25C0';
margin: -4px 0 0 0;
top: 50%;
left: -8px;
}
/* Southward tooltips */
.d3-tip.s:after {
content: '\25B2';
margin: 0 0 1px 0;
top: -8px;
left: 0;
text-align: center;
}
/* Westward tooltips */
.d3-tip.w:after {
content: '\25B6';
margin: -4px 0 0 -1px;
top: 50%;
left: 100%;
}

View File

@ -0,0 +1,32 @@
## @superset-ui/legacy-plugin-chart-horizon
[![Version](https://img.shields.io/npm/v/@superset-ui/legacy-plugin-chart-horizon.svg?style=flat-square)](https://img.shields.io/npm/v/@superset-ui/legacy-plugin-chart-horizon.svg?style=flat-square)
[![David (path)](https://img.shields.io/david/apache-superset/superset-ui-plugins.svg?path=packages%2Fsuperset-ui-legacy-plugin-chart-horizon&style=flat-square)](https://david-dm.org/apache-superset/superset-ui-plugins?path=packages/superset-ui-legacy-plugin-chart-horizon)
This plugin provides Horizon for Superset.
### Usage
Configure `key`, which can be any `string`, and register the plugin. This `key` will be used to lookup this chart throughout the app.
```js
import HorizonChartPlugin from '@superset-ui/legacy-plugin-chart-horizon';
new HorizonChartPlugin()
.configure({ key: 'horizon' })
.register();
```
Then use it via `SuperChart`. See [storybook](https://apache-superset.github.io/superset-ui-plugins/?selectedKind=plugin-chart-horizon) for more details.
```js
<SuperChart
chartType="horizon"
width={600}
height={600}
formData={...}
queryData={{
data: {...},
}}
/>
```

View File

@ -0,0 +1,40 @@
{
"name": "@superset-ui/legacy-plugin-chart-horizon",
"version": "0.11.15",
"description": "Superset Legacy Chart - Horizon",
"sideEffects": [
"*.css"
],
"main": "lib/index.js",
"module": "esm/index.js",
"files": [
"esm",
"lib"
],
"repository": {
"type": "git",
"url": "git+https://github.com/apache-superset/superset-ui-plugins.git"
},
"keywords": [
"superset"
],
"author": "Superset",
"license": "Apache-2.0",
"bugs": {
"url": "https://github.com/apache-superset/superset-ui-plugins/issues"
},
"homepage": "https://github.com/apache-superset/superset-ui-plugins#readme",
"publishConfig": {
"access": "public"
},
"dependencies": {
"d3-array": "^2.0.3",
"d3-scale": "^3.0.1",
"prop-types": "^15.6.2"
},
"peerDependencies": {
"@superset-ui/chart": "^0.12.0",
"@superset-ui/translation": "^0.12.0",
"react": "^15 || ^16"
}
}

View File

@ -0,0 +1,38 @@
/**
* 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.
*/
.superset-legacy-chart-horizon {
overflow: auto;
position: relative;
}
.superset-legacy-chart-horizon .horizon-row {
border-bottom: solid 1px #ddd;
border-top: 0px;
padding: 0px;
margin: 0px;
}
.superset-legacy-chart-horizon .horizon-row span.title {
position: absolute;
color: #333;
font-size: 0.8em;
margin: 0;
text-shadow: 1px 1px rgba(255, 255, 255, 0.75);
}

View File

@ -0,0 +1,106 @@
/**
* 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.
*/
/* eslint-disable react/jsx-sort-default-props, react/sort-prop-types */
import React from 'react';
import PropTypes from 'prop-types';
import { extent as d3Extent } from 'd3-array';
import HorizonRow, { DEFAULT_COLORS } from './HorizonRow';
import './HorizonChart.css';
const propTypes = {
className: PropTypes.string,
width: PropTypes.number,
height: PropTypes.number,
seriesHeight: PropTypes.number,
data: PropTypes.arrayOf(
PropTypes.shape({
key: PropTypes.arrayOf(PropTypes.string),
values: PropTypes.arrayOf(
PropTypes.shape({
y: PropTypes.number,
}),
),
}),
).isRequired,
// number of bands in each direction (positive / negative)
bands: PropTypes.number,
colors: PropTypes.arrayOf(PropTypes.string),
colorScale: PropTypes.string,
mode: PropTypes.string,
offsetX: PropTypes.number,
};
const defaultProps = {
className: '',
width: 800,
height: 600,
seriesHeight: 20,
bands: Math.floor(DEFAULT_COLORS.length / 2),
colors: DEFAULT_COLORS,
colorScale: 'series',
mode: 'offset',
offsetX: 0,
};
class HorizonChart extends React.PureComponent {
render() {
const {
className,
width,
height,
data,
seriesHeight,
bands,
colors,
colorScale,
mode,
offsetX,
} = this.props;
let yDomain;
if (colorScale === 'overall') {
const allValues = data.reduce((acc, current) => acc.concat(current.values), []);
yDomain = d3Extent(allValues, d => d.y);
}
return (
<div className={`superset-legacy-chart-horizon ${className}`} style={{ height }}>
{data.map(row => (
<HorizonRow
key={row.key}
width={width}
height={seriesHeight}
title={row.key.join(', ')}
data={row.values}
bands={bands}
colors={colors}
colorScale={colorScale}
mode={mode}
offsetX={offsetX}
yDomain={yDomain}
/>
))}
</div>
);
}
}
HorizonChart.propTypes = propTypes;
HorizonChart.defaultProps = defaultProps;
export default HorizonChart;

View File

@ -0,0 +1,197 @@
/**
* 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.
*/
/* eslint-disable no-continue, no-plusplus, no-bitwise */
/* eslint-disable react/jsx-sort-default-props */
/* eslint-disable react/sort-prop-types */
import React from 'react';
import PropTypes from 'prop-types';
import { extent as d3Extent } from 'd3-array';
import { scaleLinear } from 'd3-scale';
export const DEFAULT_COLORS = [
'#313695',
'#4575b4',
'#74add1',
'#abd9e9',
'#fee090',
'#fdae61',
'#f46d43',
'#d73027',
];
const propTypes = {
className: PropTypes.string,
width: PropTypes.number,
height: PropTypes.number,
data: PropTypes.arrayOf(
PropTypes.shape({
y: PropTypes.number,
}),
).isRequired,
bands: PropTypes.number,
colors: PropTypes.arrayOf(PropTypes.string),
colorScale: PropTypes.string,
mode: PropTypes.string,
offsetX: PropTypes.number,
title: PropTypes.string,
yDomain: PropTypes.arrayOf(PropTypes.number),
};
const defaultProps = {
className: '',
width: 800,
height: 20,
bands: DEFAULT_COLORS.length >> 1,
colors: DEFAULT_COLORS,
colorScale: 'series',
mode: 'offset',
offsetX: 0,
title: '',
yDomain: undefined,
};
class HorizonRow extends React.PureComponent {
componentDidMount() {
this.drawChart();
}
componentDidUpdate() {
this.drawChart();
}
componentWillUnmount() {
this.canvas = null;
}
drawChart() {
if (this.canvas) {
const {
data: rawData,
yDomain,
width,
height,
bands,
colors,
colorScale,
offsetX,
mode,
} = this.props;
const data =
colorScale === 'change' ? rawData.map(d => ({ ...d, y: d.y - rawData[0].y })) : rawData;
const context = this.canvas.getContext('2d');
context.imageSmoothingEnabled = false;
context.clearRect(0, 0, width, height);
// Reset transform
context.setTransform(1, 0, 0, 1, 0, 0);
context.translate(0.5, 0.5);
const step = width / data.length;
// the data frame currently being shown:
const startIndex = Math.floor(Math.max(0, -(offsetX / step)));
const endIndex = Math.floor(Math.min(data.length, startIndex + width / step));
// skip drawing if there's no data to be drawn
if (startIndex > data.length) {
return;
}
// Create y-scale
const [min, max] = yDomain || d3Extent(data, d => d.y);
const y = scaleLinear()
.domain([0, Math.max(-min, max)])
.range([0, height]);
// we are drawing positive & negative bands separately to avoid mutating canvas state
// http://www.html5rocks.com/en/tutorials/canvas/performance/
let hasNegative = false;
// draw positive bands
let value;
let bExtents;
for (let b = 0; b < bands; b += 1) {
context.fillStyle = colors[bands + b];
// Adjust the range based on the current band index.
bExtents = (b + 1 - bands) * height;
y.range([bands * height + bExtents, bExtents]);
// only the current data frame is being drawn i.e. what's visible:
for (let i = startIndex; i < endIndex; i++) {
value = data[i].y;
if (value <= 0) {
hasNegative = true;
continue;
}
if (value !== undefined) {
context.fillRect(offsetX + i * step, y(value), step + 1, y(0) - y(value));
}
}
}
// draw negative bands
if (hasNegative) {
// mirror the negative bands, by flipping the canvas
if (mode === 'offset') {
context.translate(0, height);
context.scale(1, -1);
}
for (let b = 0; b < bands; b++) {
context.fillStyle = colors[bands - b - 1];
// Adjust the range based on the current band index.
bExtents = (b + 1 - bands) * height;
y.range([bands * height + bExtents, bExtents]);
// only the current data frame is being drawn i.e. what's visible:
for (let ii = startIndex; ii < endIndex; ii++) {
value = data[ii].y;
if (value >= 0) {
continue;
}
context.fillRect(offsetX + ii * step, y(-value), step + 1, y(0) - y(-value));
}
}
}
}
}
render() {
const { className, title, width, height } = this.props;
return (
<div className={`horizon-row ${className}`}>
<span className="title">{title}</span>
<canvas
ref={c => {
this.canvas = c;
}}
width={width}
height={height}
/>
</div>
);
}
}
HorizonRow.propTypes = propTypes;
HorizonRow.defaultProps = defaultProps;
export default HorizonRow;

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

View File

@ -0,0 +1,40 @@
/**
* 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 { t } from '@superset-ui/translation';
import { ChartMetadata, ChartPlugin } from '@superset-ui/chart';
import transformProps from './transformProps';
import thumbnail from './images/thumbnail.png';
const metadata = new ChartMetadata({
credits: ['http://kmandov.github.io/d3-horizon-chart/'],
description: '',
name: t('Horizon Chart'),
thumbnail,
useLegacyApi: true,
});
export default class HorizonChartPlugin extends ChartPlugin {
constructor() {
super({
loadChart: () => import('./HorizonChart'),
metadata,
transformProps,
});
}
}

View File

@ -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.
*/
export default function transformProps(chartProps) {
const { height, width, formData, queryData } = chartProps;
const { horizonColorScale, seriesHeight } = formData;
return {
colorScale: horizonColorScale,
data: queryData.data,
height,
seriesHeight: parseInt(seriesHeight, 10),
width,
};
}

View File

@ -0,0 +1,32 @@
## @superset-ui/legacy-plugin-chart-iframe
[![Version](https://img.shields.io/npm/v/@superset-ui/legacy-plugin-chart-iframe.svg?style=flat-square)](https://img.shields.io/npm/v/@superset-ui/legacy-plugin-chart-iframe.svg?style=flat-square)
[![David (path)](https://img.shields.io/david/apache-superset/superset-ui-plugins.svg?path=packages%2Fsuperset-ui-legacy-plugin-chart-iframe&style=flat-square)](https://david-dm.org/apache-superset/superset-ui-plugins?path=packages/superset-ui-legacy-plugin-chart-iframe)
This plugin provides Iframe for Superset.
### Usage
Configure `key`, which can be any `string`, and register the plugin. This `key` will be used to lookup this chart throughout the app.
```js
import IframeChartPlugin from '@superset-ui/legacy-plugin-chart-iframe';
new IframeChartPlugin()
.configure({ key: 'iframe' })
.register();
```
Then use it via `SuperChart`. See [storybook](https://apache-superset.github.io/superset-ui-plugins/?selectedKind=plugin-chart-iframe) for more details.
```js
<SuperChart
chartType="iframe"
width={600}
height={600}
formData={...}
queryData={{
data: {...},
}}
/>
```

View File

@ -0,0 +1,39 @@
{
"name": "@superset-ui/legacy-plugin-chart-iframe",
"version": "0.11.15",
"description": "Superset Legacy Chart - Iframe",
"sideEffects": [
"*.css"
],
"main": "lib/index.js",
"module": "esm/index.js",
"files": [
"esm",
"lib"
],
"repository": {
"type": "git",
"url": "git+https://github.com/apache-superset/superset-ui-plugins.git"
},
"keywords": [
"superset"
],
"author": "Superset",
"license": "Apache-2.0",
"bugs": {
"url": "https://github.com/apache-superset/superset-ui-plugins/issues"
},
"homepage": "https://github.com/apache-superset/superset-ui-plugins#readme",
"publishConfig": {
"access": "public"
},
"dependencies": {
"mustache": "^4.0.0",
"prop-types": "^15.6.2"
},
"peerDependencies": {
"@superset-ui/chart": "^0.12.0",
"@superset-ui/translation": "^0.12.0",
"react": "^15 || ^16"
}
}

View File

@ -0,0 +1,60 @@
/**
* 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 Mustache from 'mustache';
import React from 'react';
import PropTypes from 'prop-types';
const propTypes = {
className: PropTypes.string,
height: PropTypes.number.isRequired,
url: PropTypes.string,
width: PropTypes.number.isRequired,
};
const defaultProps = {
className: '',
url: '',
};
class Iframe extends React.PureComponent {
render() {
const { className, url, width, height } = this.props;
const completeUrl = Mustache.render(url, {
height,
width,
});
return (
<iframe
className={className}
title="superset-iframe"
src={completeUrl}
style={{
height,
width: '100%',
}}
/>
);
}
}
Iframe.propTypes = propTypes;
Iframe.defaultProps = defaultProps;
export default Iframe;

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

View File

@ -0,0 +1,39 @@
/**
* 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 { t } from '@superset-ui/translation';
import { ChartMetadata, ChartPlugin } from '@superset-ui/chart';
import thumbnail from './images/thumbnail.png';
import transformProps from './transformProps';
const metadata = new ChartMetadata({
description: 'HTML Inline Frame',
name: t('IFrame'),
thumbnail,
useLegacyApi: true,
});
export default class IframeChartPlugin extends ChartPlugin {
constructor() {
super({
loadChart: () => import('./Iframe'),
metadata,
transformProps,
});
}
}

View File

@ -0,0 +1,28 @@
/**
* 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.
*/
export default function transformProps(chartProps) {
const { formData, height, width } = chartProps;
const { url } = formData;
return {
height,
url,
width,
};
}

View File

@ -0,0 +1,32 @@
## @superset-ui/legacy-plugin-chart-markup
[![Version](https://img.shields.io/npm/v/@superset-ui/legacy-plugin-chart-markup.svg?style=flat-square)](https://img.shields.io/npm/v/@superset-ui/legacy-plugin-chart-markup.svg?style=flat-square)
[![David (path)](https://img.shields.io/david/apache-superset/superset-ui-plugins.svg?path=packages%2Fsuperset-ui-legacy-plugin-chart-markup&style=flat-square)](https://david-dm.org/apache-superset/superset-ui-plugins?path=packages/superset-ui-legacy-plugin-chart-markup)
This plugin provides Markup for Superset.
### Usage
Configure `key`, which can be any `string`, and register the plugin. This `key` will be used to lookup this chart throughout the app.
```js
import MarkupChartPlugin from '@superset-ui/legacy-plugin-chart-markup';
new MarkupChartPlugin()
.configure({ key: 'markup' })
.register();
```
Then use it via `SuperChart`. See [storybook](https://apache-superset.github.io/superset-ui-plugins/?selectedKind=plugin-chart-markup) for more details.
```js
<SuperChart
chartType="markup"
width={600}
height={600}
formData={...}
queryData={{
data: {...},
}}
/>
```

View File

@ -0,0 +1,38 @@
{
"name": "@superset-ui/legacy-plugin-chart-markup",
"version": "0.11.15",
"description": "Superset Legacy Chart - Markup",
"sideEffects": [
"*.css"
],
"main": "lib/index.js",
"module": "esm/index.js",
"files": [
"esm",
"lib"
],
"repository": {
"type": "git",
"url": "git+https://github.com/apache-superset/superset-ui-plugins.git"
},
"keywords": [
"superset"
],
"author": "Superset",
"license": "Apache-2.0",
"bugs": {
"url": "https://github.com/apache-superset/superset-ui-plugins/issues"
},
"homepage": "https://github.com/apache-superset/superset-ui-plugins#readme",
"publishConfig": {
"access": "public"
},
"dependencies": {
"prop-types": "^15.6.2"
},
"peerDependencies": {
"@superset-ui/chart": "^0.12.0",
"@superset-ui/translation": "^0.12.0",
"react": "^15 || ^16"
}
}

View File

@ -0,0 +1,39 @@
/**
* 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.
*/
.markup.slice_container {
margin: 10px;
}
.separator {
background-color: transparent !important;
}
.separator hr {
border: 0;
height: 1px;
background-image: linear-gradient(
to right,
rgba(0, 0, 0, 1),
rgba(0, 0, 0, 1),
rgba(0, 0, 0, 1),
rgba(0, 0, 0, 0)
);
}
.separator .chart-header {
border: none !important;
}

View File

@ -0,0 +1,71 @@
/**
* 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 PropTypes from 'prop-types';
import './Markup.css';
const propTypes = {
className: PropTypes.string,
cssFiles: PropTypes.arrayOf(PropTypes.string),
height: PropTypes.number.isRequired,
html: PropTypes.string,
isSeparator: PropTypes.bool,
};
const defaultProps = {
className: '',
cssFiles: [],
html: '',
isSeparator: false,
};
const CONTAINER_STYLE = {
overflow: 'auto',
position: 'relative',
};
class Markup extends React.PureComponent {
render() {
const { className, height, isSeparator, html, cssFiles } = this.props;
return (
<div className={className} style={CONTAINER_STYLE}>
<iframe
title="superset-markup"
frameBorder={0}
height={isSeparator ? height - 20 : height}
sandbox="allow-forms allow-popups allow-same-origin allow-scripts allow-top-navigation"
srcDoc={`
<html>
<head>
${cssFiles.map(href => `<link rel="stylesheet" type="text/css" href="${href}" />`)}
</head>
<body style="background-color: transparent;">
${html}
</body>
</html>`}
/>
</div>
);
}
}
Markup.propTypes = propTypes;
Markup.defaultProps = defaultProps;
export default Markup;

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

View File

@ -0,0 +1,39 @@
/**
* 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 { t } from '@superset-ui/translation';
import { ChartMetadata, ChartPlugin } from '@superset-ui/chart';
import thumbnail from './images/thumbnail.png';
import transformProps from './transformProps';
const metadata = new ChartMetadata({
description: 'HTML Markup',
name: t('Markup'),
thumbnail,
useLegacyApi: true,
});
export default class IframeChartPlugin extends ChartPlugin {
constructor() {
super({
loadChart: () => import('./Markup'),
metadata,
transformProps,
});
}
}

View File

@ -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.
*/
export default function transformProps(chartProps) {
const { height, queryData, formData } = chartProps;
const { vizType } = formData;
const { theme_css: cssFiles, html } = queryData.data;
return {
cssFiles,
height,
html,
isSeparator: vizType === 'separator',
};
}

View File

@ -6827,6 +6827,11 @@ d3-shape@^1.0.6, d3-shape@^1.2.0, d3-shape@^1.3.7:
dependencies:
d3-path "1"
d3-svg-legend@^1.x:
version "1.13.0"
resolved "https://registry.yarnpkg.com/d3-svg-legend/-/d3-svg-legend-1.13.0.tgz#6217478c9add9d62cb333617e1961311a41a4db3"
integrity sha1-YhdHjJrdnWLLMzYX4ZYTEaQaTbM=
d3-time-format@2, d3-time-format@^2.2.0, d3-time-format@^2.2.1, d3-time-format@^2.2.2, d3-time-format@^2.2.3:
version "2.2.3"
resolved "https://registry.yarnpkg.com/d3-time-format/-/d3-time-format-2.2.3.tgz#0c9a12ee28342b2037e5ea1cf0b9eb4dd75f29cb"
@ -12010,6 +12015,11 @@ multimatch@^4.0.0:
arrify "^2.0.1"
minimatch "^3.0.4"
mustache@^4.0.0:
version "4.0.1"
resolved "https://registry.yarnpkg.com/mustache/-/mustache-4.0.1.tgz#d99beb031701ad433338e7ea65e0489416c854a2"
integrity sha512-yL5VE97+OXn4+Er3THSmTdCFCtx5hHWzrolvH+JObZnUYwuaG7XV+Ch4fR2cIrcYI0tFHxS7iyFYl14bW8y2sA==
mute-stream@0.0.7:
version "0.0.7"
resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab"