feat(generator-superset): add scaffolder for chart plugin (#456)

* feat: add plugin generator

* feat: add templates

* feat: add templates

* fix: wrong path

* fix: unit test

* fix: coverage

* fix: simplify template
This commit is contained in:
Krist Wongsuphasawat 2020-05-13 13:51:43 -07:00 committed by Yongjie Zhao
parent 3364f0f6da
commit dfa166ca81
13 changed files with 292 additions and 14 deletions

View File

@ -18,11 +18,15 @@ module.exports = class extends Generator {
message: 'What do you want to do?',
choices: [
{
name: 'Create superset-ui package in the monorepo',
name: 'Create superset-ui core package',
value: 'package',
},
{
name: 'Create superset-ui-legacy package in the monorepo',
name: 'Create superset-ui chart plugin package',
value: 'plugin-chart',
},
{
name: 'Create superset-ui-legacy package',
value: 'legacy-plugin-chart',
},
{

View File

@ -0,0 +1,52 @@
/* eslint-disable sort-keys */
const Generator = require('yeoman-generator');
const _ = require('lodash');
module.exports = class extends Generator {
async prompting() {
this.option('skipInstall');
this.answers = await this.prompt([
{
type: 'input',
name: 'packageName',
message: 'Package name:',
// Default to current folder name
default: _.kebabCase(this.appname.replace('plugin chart', '').trim()),
},
{
type: 'input',
name: 'description',
message: 'Description:',
// Default to current folder name
default: _.upperFirst(_.startCase(this.appname.replace('plugin chart', '').trim())),
},
]);
}
writing() {
const packageLabel = _.upperFirst(_.camelCase(this.answers.packageName));
const params = {
...this.answers,
packageLabel,
};
[
['package.erb', 'package.json'],
['README.erb', 'README.md'],
['src/index.erb', 'src/index.ts'],
['src/plugin/index.erb', 'src/plugin/index.ts'],
['src/plugin/transformProps.txt', 'src/plugin/transformProps.ts'],
['src/MyChart.erb', `src/${packageLabel}.tsx`],
['test/index.erb', 'test/index.test.ts'],
].forEach(([src, dest]) => {
this.fs.copyTpl(this.templatePath(src), this.destinationPath(dest), params);
});
['types/external.d.ts', 'src/images/thumbnail.png'].forEach(file => {
this.fs.copy(this.templatePath(file), this.destinationPath(file));
});
}
};

View File

@ -0,0 +1,32 @@
## @superset-ui/plugin-chart-<%= packageName %>
[![Version](https://img.shields.io/npm/v/@superset-ui/plugin-chart-<%= packageName %>.svg?style=flat-square)](https://img.shields.io/npm/v/@superset-ui/plugin-chart-<%= packageName %>.svg?style=flat-square)
[![David (path)](https://img.shields.io/david/apache-superset/superset-ui.svg?path=packages%2Fsuperset-ui-plugin-chart-<%= packageName %>&style=flat-square)](https://david-dm.org/apache-superset/superset-ui?path=packages/superset-ui-plugin-chart-<%= packageName %>)
This plugin provides <%= description %> 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 <%= packageLabel %>ChartPlugin from '@superset-ui/plugin-chart-<%= packageName %>';
new <%= packageLabel %>ChartPlugin()
.configure({ key: '<%= packageName %>' })
.register();
```
Then use it via `SuperChart`. See [storybook](https://apache-superset.github.io/superset-ui/?selectedKind=plugin-chart-<%= packageName %>) for more details.
```js
<SuperChart
chartType="<%= packageName %>"
width={600}
height={600}
formData={...}
queryData={{
data: {...},
}}
/>
```

View File

@ -0,0 +1,32 @@
{
"name": "@superset-ui/plugin-chart-<%= packageName %>",
"version": "0.0.0",
"description": "Superset Chart - <%= description %>",
"sideEffects": false,
"main": "lib/index.js",
"module": "esm/index.js",
"files": [
"esm",
"lib"
],
"repository": {
"type": "git",
"url": "git+https://github.com/apache-superset/superset-ui.git"
},
"keywords": [
"superset"
],
"author": "Superset",
"license": "Apache-2.0",
"bugs": {
"url": "https://github.com/apache-superset/superset-ui/issues"
},
"homepage": "https://github.com/apache-superset/superset-ui#readme",
"publishConfig": {
"access": "public"
},
"peerDependencies": {
"@superset-ui/chart": "latest",
"@superset-ui/translation": "latest"
}
}

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 React from 'react';
export type <%= packageLabel %>Props = {
height: number;
width: number;
data: { x: number; y: number }[];
};
export default class <%= packageLabel %> extends React.PureComponent<<%= packageLabel %>Props> {
render() {
const { data, height, width } = this.props;
return (
<div style={{ backgroundColor: '#ffe459', padding: 16, borderRadius: 8, height, width }}>
<h3>Hello!</h3>
<pre>
{JSON.stringify(this.props, null, 2)}
</pre>
</div>
);
}
}

View File

@ -0,0 +1 @@
export { default as <%= packageLabel %>ChartPlugin } from './plugin';

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.
*/
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({
description: '<%= description %>',
name: t('<%= packageLabel %>'),
thumbnail,
});
export default class <%= packageLabel %>ChartPlugin extends ChartPlugin {
constructor() {
super({
loadChart: () => import('../<%= packageLabel %>'),
metadata,
transformProps,
});
}
}

View File

@ -0,0 +1,32 @@
import { ChartProps } from '@superset-ui/chart';
/**
* 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: ChartProps) {
const { width, height, formData, queryData } = chartProps;
const { color } = formData;
const { data } = queryData;
return {
width,
height,
color,
data,
};
}

View File

@ -0,0 +1,7 @@
import { <%= packageLabel %>ChartPlugin } from '../src';
describe('@superset-ui/plugin-chart-<%= packageName %>', () => {
it('exists', () => {
expect(<%= packageLabel %>ChartPlugin).toBeDefined();
});
});

View File

@ -0,0 +1,4 @@
declare module '*.png' {
const value: any;
export default value;
}

View File

@ -0,0 +1,45 @@
const path = require('path');
const assert = require('yeoman-assert');
const helpers = require('yeoman-test');
describe('generator-superset:plugin-chart', () => {
let dir;
beforeAll(() => {
dir = process.cwd();
return helpers
.run(path.join(__dirname, '../generators/plugin-chart'))
.withPrompts({ packageName: 'cold-map', description: 'Cold Map' })
.withOptions({ skipInstall: true });
});
/*
* Change working directory back to original working directory
* after the test has completed.
* yeoman tests switch to tmp directory and write files there.
* Usually this is fine for solo package.
* However, for a monorepo like this one,
* it made jest confuses with current directory
* (being in tmp directory instead of superset-ui root)
* and interferes with other tests in sibling packages
* that are run after the yeoman tests.
*/
afterAll(() => {
process.chdir(dir);
});
it('creates files', () => {
assert.file([
'package.json',
'README.md',
'src/plugin/index.ts',
'src/plugin/transformProps.ts',
'src/index.ts',
'src/ColdMap.tsx',
'test/index.test.ts',
'types/external.d.ts',
'src/images/thumbnail.png',
]);
});
});

View File

@ -3251,15 +3251,6 @@
conventional-changelog-cli "^2.0.12"
cz-conventional-changelog "^2.1.0"
"@superset-ui/legacy-plugin-chart-partition@0.13.5":
version "0.13.5"
resolved "https://registry.yarnpkg.com/@superset-ui/legacy-plugin-chart-partition/-/legacy-plugin-chart-partition-0.13.5.tgz#f34d14bc204ef2ad7acb7dee32ee09c46726535b"
integrity sha512-YsgbAqj/sQKEWUmI0XXy6rJvGsWSPwfekmtWpa55CF19A+TJEuCCHmIGDPupgZsIqgJBZArwYT3HNnn7a8TfxA==
dependencies:
d3 "^3.5.17"
d3-hierarchy "^1.1.8"
prop-types "^15.6.2"
"@superset-ui/legacy-plugin-chart-word-cloud@^0.11.15":
version "0.11.15"
resolved "https://registry.yarnpkg.com/@superset-ui/legacy-plugin-chart-word-cloud/-/legacy-plugin-chart-word-cloud-0.11.15.tgz#70a146aaf3cf1977c29086c069f0216325f092b2"
@ -3729,9 +3720,9 @@
"@types/react" "*"
"@types/react@*", "@types/react@^16.3.0", "@types/react@^16.9.11", "@types/react@^16.9.34":
version "16.9.35"
resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.35.tgz#a0830d172e8aadd9bd41709ba2281a3124bbd368"
integrity sha512-q0n0SsWcGc8nDqH2GJfWQWUOmZSJhXV64CjVN5SvcNti3TdEaA3AH0D8DwNmMdzjMAC/78tB8nAZIlV8yTz+zQ==
version "16.9.34"
resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.34.tgz#f7d5e331c468f53affed17a8a4d488cd44ea9349"
integrity sha512-8AJlYMOfPe1KGLKyHpflCg5z46n0b5DbRfqDksxBLBTUpB75ypDBAO9eCUcjNwE6LCUslwTz00yyG/X9gaVtow==
dependencies:
"@types/prop-types" "*"
csstype "^2.2.0"