Skip to content
This repository has been archived by the owner on Jun 25, 2020. It is now read-only.

Commit

Permalink
feat(plugin-chart-word-cloud): convert word cloud to use encodable (#258
Browse files Browse the repository at this point in the history
)

* feat: convert word cloud to use encodable

* fix: minor bugs

* feat: bump dependencies

* feat: use field

* fix: defaultProps

* fix: unit test

* docs: update storybook

* refactor: move files

* docs: update storybook

* fix: unit test

* fix: address comments
  • Loading branch information
kristw authored Nov 20, 2019
1 parent 8a5e84a commit 9b14285
Show file tree
Hide file tree
Showing 16 changed files with 409 additions and 159 deletions.
3 changes: 2 additions & 1 deletion packages/superset-ui-plugin-chart-word-cloud/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@
"@types/d3-scale": "^2.0.2",
"@types/react": "^16.3.0",
"d3-cloud": "^1.2.5",
"d3-scale": "^3.0.1"
"d3-scale": "^3.0.1",
"encodable": "^0.0.7"
},
"peerDependencies": {
"@superset-ui/chart": "^0.12.0",
Expand Down
116 changes: 0 additions & 116 deletions packages/superset-ui-plugin-chart-word-cloud/src/WordCloud.tsx

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { buildQueryContext } from '@superset-ui/query';
import WordCloudFormData from './WordCloudFormData';
import { WordCloudFormData } from './types';

export default function buildQuery(formData: WordCloudFormData) {
// Set the single QueryObject's groupby field with series in formData
Expand Down
30 changes: 30 additions & 0 deletions packages/superset-ui-plugin-chart-word-cloud/src/chart/Encoder.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { createEncoderFactory } from 'encodable';
import { DeriveEncoding } from 'encodable/lib/types/Encoding';

type WordCloudEncodingConfig = {
color: ['Color', string];
fontFamily: ['Category', string];
fontSize: ['Numeric', number];
fontWeight: ['Category', string | number];
text: ['Text', string];
};

// eslint-disable-next-line import/prefer-default-export
export const wordCloudEncoderFactory = createEncoderFactory<WordCloudEncodingConfig>({
channelTypes: {
color: 'Color',
fontFamily: 'Category',
fontSize: 'Numeric',
fontWeight: 'Category',
text: 'Text',
},
defaultEncoding: {
color: { value: 'black' },
fontFamily: { value: 'Helvetica' },
fontSize: { value: 20 },
fontWeight: { value: 'bold' },
text: { value: '' },
},
});

export type WordCloudEncoding = DeriveEncoding<WordCloudEncodingConfig>;
129 changes: 129 additions & 0 deletions packages/superset-ui-plugin-chart-word-cloud/src/chart/WordCloud.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
import React from 'react';
import cloudLayout, { Word } from 'd3-cloud';
import { PlainObject } from 'encodable/lib/types/Data';
import { WordCloudEncoding, wordCloudEncoderFactory } from './Encoder';

export const ROTATION = {
flat: () => 0,
// this calculates a random rotation between -90 and 90 degrees.
/* eslint-disable-next-line no-magic-numbers */
random: () => Math.floor(Math.random() * 6 - 3) * 30,
/* eslint-disable-next-line no-magic-numbers */
square: () => Math.floor(Math.random() * 2) * 90,
};

export type RotationType = keyof typeof ROTATION;

/**
* These props should be stored when saving the chart.
*/
export interface WordCloudVisualProps {
encoding?: Partial<WordCloudEncoding>;
rotation?: RotationType;
}

export interface WordCloudProps extends WordCloudVisualProps {
data: PlainObject[];
height: number;
width: number;
}

interface State {
words: Word[];
}

const defaultProps = {
encoding: {},
rotation: 'flat',
};

export default class WordCloud extends React.PureComponent<
WordCloudProps & typeof defaultProps,
State
> {
isMounted: boolean = false;
state: State = {
words: [],
};

createEncoder = wordCloudEncoderFactory.createSelector();

static defaultProps = defaultProps;

componentDidMount() {
this.isMounted = true;
this.update();
}

componentDidUpdate(prevProps: WordCloudProps) {
const { data, encoding, width, height, rotation } = this.props;

if (
prevProps.data !== data ||
prevProps.encoding !== encoding ||
prevProps.width !== width ||
prevProps.height !== height ||
prevProps.rotation !== rotation
) {
this.update();
}
}

componentWillUnmount() {
this.isMounted = false;
}

setWords = (words: Word[]) => {
if (this.isMounted) {
this.setState({ words });
}
};

update() {
const { data, width, height, rotation, encoding } = this.props;

const encoder = this.createEncoder(encoding);
encoder.channels.fontSize.setDomainFromDataset(data);

cloudLayout()
.size([width, height])
.words(data)
/* eslint-disable-next-line no-magic-numbers */
.padding(5)
.rotate(ROTATION[rotation] || ROTATION.flat)
.text(d => encoder.channels.text.getValueFromDatum(d))
.font(d => encoder.channels.fontFamily.encodeDatum(d, 'Helvetica'))
.fontWeight(d => encoder.channels.fontWeight.encodeDatum(d, 'normal'))
.fontSize(d => encoder.channels.fontSize.encodeDatum(d, 0))
.on('end', this.setWords)
.start();
}

render() {
const { width, height, encoding } = this.props;
const { words } = this.state;

const encoder = this.createEncoder(encoding);
encoder.channels.color.setDomainFromDataset(words);

return (
<svg width={width} height={height}>
<g transform={`translate(${width / 2},${height / 2})`}>
{words.map(w => (
<text
key={w.text}
fontSize={`${w.size}px`}
fontWeight={w.weight}
fontFamily={w.font}
fill={encoder.channels.color.encodeDatum(w, '')}
textAnchor="middle"
transform={`translate(${w.x}, ${w.y}) rotate(${w.rotate})`}
>
{w.text}
</text>
))}
</g>
</svg>
);
}
}
4 changes: 2 additions & 2 deletions packages/superset-ui-plugin-chart-word-cloud/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { t } from '@superset-ui/translation';
import { ChartMetadata, ChartPlugin } from '@superset-ui/chart';
import buildQuery from './buildQuery';
import WordCloudFormData from './WordCloudFormData';
import { WordCloudFormData } from './types';
import transformProps from './transformProps';
import thumbnail from './images/thumbnail.png';

Expand All @@ -16,7 +16,7 @@ export default class WordCloudChartPlugin extends ChartPlugin<WordCloudFormData>
constructor() {
super({
buildQuery,
loadChart: () => import('./WordCloud'),
loadChart: () => import('./chart/WordCloud'),
metadata,
transformProps,
});
Expand Down
25 changes: 25 additions & 0 deletions packages/superset-ui-plugin-chart-word-cloud/src/legacy/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { t } from '@superset-ui/translation';
import { ChartMetadata, ChartPlugin } from '@superset-ui/chart';
import buildQuery from '../buildQuery';
import transformProps from './transformProps';
import thumbnail from '../images/thumbnail.png';
import { LegacyWordCloudFormData } from './types';

const metadata = new ChartMetadata({
credits: ['https://github.com/jasondavies/d3-cloud'],
description: '',
name: t('Word Cloud'),
thumbnail,
useLegacyApi: true,
});

export default class WordCloudChartPlugin extends ChartPlugin<LegacyWordCloudFormData> {
constructor() {
super({
buildQuery,
loadChart: () => import('../chart/WordCloud'),
metadata,
transformProps,
});
}
}
Loading

0 comments on commit 9b14285

Please sign in to comment.