From 5e9ed79704d0f29be8af9474e270b2108d31ebd0 Mon Sep 17 00:00:00 2001 From: Christopher Guan <51972312+cguan7@users.noreply.github.com> Date: Thu, 1 Aug 2019 13:12:44 -0700 Subject: [PATCH] feat: file skeleton necessary for icicle chart visualization (#162) * feat: file skeleton necessary for icicle chart visualization * feat: name changes and restructure components update package to account for clearer name and reorganized implementation for planned features * feat: fix lint errors * docs: add license file headers, adjust naming and links Add Apache license file headers to all files, adjust naming of the viz in the package.json and update the README to inform that Storybook link is unavailable but will be in the near future --- .../README.md | 39 +++++++++++ .../package.json | 47 +++++++++++++ .../src/IcicleEventChart.tsx | 65 ++++++++++++++++++ .../src/IcicleEventViz.tsx | 39 +++++++++++ .../src/createMetadata.ts | 30 ++++++++ .../src/images/thumbnail.png | Bin 0 -> 52968 bytes .../src/index.ts | 31 +++++++++ .../src/transformProps.ts | 23 +++++++ .../src/utils/IcicleEventTreeHelpers.ts | 42 +++++++++++ .../src/utils/RenderedIcicleAccessors.ts | 57 +++++++++++++++ .../types/IcicleEventNode.ts | 25 +++++++ .../types/external.d.ts | 22 ++++++ 12 files changed, 420 insertions(+) create mode 100644 superset-frontend/temporary_superset_ui/superset-ui/plugins/superset-ui-plugins/packages/superset-ui-plugin-chart-icicle-event/README.md create mode 100644 superset-frontend/temporary_superset_ui/superset-ui/plugins/superset-ui-plugins/packages/superset-ui-plugin-chart-icicle-event/package.json create mode 100644 superset-frontend/temporary_superset_ui/superset-ui/plugins/superset-ui-plugins/packages/superset-ui-plugin-chart-icicle-event/src/IcicleEventChart.tsx create mode 100644 superset-frontend/temporary_superset_ui/superset-ui/plugins/superset-ui-plugins/packages/superset-ui-plugin-chart-icicle-event/src/IcicleEventViz.tsx create mode 100644 superset-frontend/temporary_superset_ui/superset-ui/plugins/superset-ui-plugins/packages/superset-ui-plugin-chart-icicle-event/src/createMetadata.ts create mode 100644 superset-frontend/temporary_superset_ui/superset-ui/plugins/superset-ui-plugins/packages/superset-ui-plugin-chart-icicle-event/src/images/thumbnail.png create mode 100644 superset-frontend/temporary_superset_ui/superset-ui/plugins/superset-ui-plugins/packages/superset-ui-plugin-chart-icicle-event/src/index.ts create mode 100644 superset-frontend/temporary_superset_ui/superset-ui/plugins/superset-ui-plugins/packages/superset-ui-plugin-chart-icicle-event/src/transformProps.ts create mode 100644 superset-frontend/temporary_superset_ui/superset-ui/plugins/superset-ui-plugins/packages/superset-ui-plugin-chart-icicle-event/src/utils/IcicleEventTreeHelpers.ts create mode 100644 superset-frontend/temporary_superset_ui/superset-ui/plugins/superset-ui-plugins/packages/superset-ui-plugin-chart-icicle-event/src/utils/RenderedIcicleAccessors.ts create mode 100644 superset-frontend/temporary_superset_ui/superset-ui/plugins/superset-ui-plugins/packages/superset-ui-plugin-chart-icicle-event/types/IcicleEventNode.ts create mode 100644 superset-frontend/temporary_superset_ui/superset-ui/plugins/superset-ui-plugins/packages/superset-ui-plugin-chart-icicle-event/types/external.d.ts diff --git a/superset-frontend/temporary_superset_ui/superset-ui/plugins/superset-ui-plugins/packages/superset-ui-plugin-chart-icicle-event/README.md b/superset-frontend/temporary_superset_ui/superset-ui/plugins/superset-ui-plugins/packages/superset-ui-plugin-chart-icicle-event/README.md new file mode 100644 index 000000000000..fcddb4f3aa65 --- /dev/null +++ b/superset-frontend/temporary_superset_ui/superset-ui/plugins/superset-ui-plugins/packages/superset-ui-plugin-chart-icicle-event/README.md @@ -0,0 +1,39 @@ +## @superset-ui/plugin-chart-icicle + +## WIP + +This is a work in progress with the design being finalized. + +This plugin provides Icicle Event Chart 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 IcicleEventVizPlugin from '@superset-ui/plugin-chart-icicle-event'; + +new IcicleEventVizPlugin() + .configure({ key: 'icicle' }) + .register(); +``` + +Then use it via `SuperChart`. A link to Storybook for the Icicle Event Chart will be available here in the future for more details. + +```js + +``` + +### Current Prototype (Subject to Change) + +![Current Prototype](./src/images/thumbnail.png) diff --git a/superset-frontend/temporary_superset_ui/superset-ui/plugins/superset-ui-plugins/packages/superset-ui-plugin-chart-icicle-event/package.json b/superset-frontend/temporary_superset_ui/superset-ui/plugins/superset-ui-plugins/packages/superset-ui-plugin-chart-icicle-event/package.json new file mode 100644 index 000000000000..101933e42a50 --- /dev/null +++ b/superset-frontend/temporary_superset_ui/superset-ui/plugins/superset-ui-plugins/packages/superset-ui-plugin-chart-icicle-event/package.json @@ -0,0 +1,47 @@ +{ + "name": "@superset-ui/plugin-chart-icicle-event", + "version": "0.10.32", + "description": "Superset Chart Plugin - Icicle Event", + "sideEffects": [ + "*.css" + ], + "main": "lib/index.js", + "module": "esm/index.js", + "files": [ + "esm", + "lib", + "types" + ], + "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": { + "@types/d3": "^5.7.2", + "@types/d3-hierarchy": "^1.1.6", + "d3": "^5.9.7", + "d3-array": "^2.2.0", + "d3-hierarchy": "^1.1.8", + "lodash": "^4.17.11", + "prop-types": "^15.6.2" + }, + "peerDependencies": { + "@superset-ui/chart": "^0.11.6", + "@superset-ui/color": "^0.11.0", + "@superset-ui/core": "^0.11.0", + "@superset-ui/translation": "^0.11.0", + "react": "^16.2" + } +} diff --git a/superset-frontend/temporary_superset_ui/superset-ui/plugins/superset-ui-plugins/packages/superset-ui-plugin-chart-icicle-event/src/IcicleEventChart.tsx b/superset-frontend/temporary_superset_ui/superset-ui/plugins/superset-ui-plugins/packages/superset-ui-plugin-chart-icicle-event/src/IcicleEventChart.tsx new file mode 100644 index 000000000000..84bfd880fe71 --- /dev/null +++ b/superset-frontend/temporary_superset_ui/superset-ui/plugins/superset-ui-plugins/packages/superset-ui-plugin-chart-icicle-event/src/IcicleEventChart.tsx @@ -0,0 +1,65 @@ +/** + * 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, { Component, createRef } from 'react'; +import { HierarchyRectangularNode } from 'd3-hierarchy'; +import { IcicleEventNode } from '../types/IcicleEventNode'; + +interface Props { + className?: string; + width: number; + height: number; + boxMargin: { + x: number; + y: number; + }; + color: (name: string) => string; + contentRenderer: () => void; + d3TreeRoot: HierarchyRectangularNode; + isVertical: boolean; + rounding: number; + transitionDuration: number; +} + +export default class IcicleEventChart extends Component { + private chartRef = createRef(); + + constructor(props: Props) { + super(props); + + this.renderIcicleChart = this.renderIcicleChart.bind(this); + } + + componentDidMount() { + this.renderIcicleChart(); + } + + // Check for changed data to rerender the icicle chart + componentDidUpdate(prevProps: Props) {} + + // Creates chart using svg & chartRef to the div element + renderIcicleChart() {} + + render() { + return ( +
+
+
+ ); + } +} diff --git a/superset-frontend/temporary_superset_ui/superset-ui/plugins/superset-ui-plugins/packages/superset-ui-plugin-chart-icicle-event/src/IcicleEventViz.tsx b/superset-frontend/temporary_superset_ui/superset-ui/plugins/superset-ui-plugins/packages/superset-ui-plugin-chart-icicle-event/src/IcicleEventViz.tsx new file mode 100644 index 000000000000..f46199eb803d --- /dev/null +++ b/superset-frontend/temporary_superset_ui/superset-ui/plugins/superset-ui-plugins/packages/superset-ui-plugin-chart-icicle-event/src/IcicleEventViz.tsx @@ -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 React, { PureComponent } from 'react'; +import { IcicleEventNode } from '../types/IcicleEventNode'; + +interface Props { + className?: string; + width: number; + height: number; + data: IcicleEventNode; + color: (name: string) => string; + isVertical: boolean; + rounding: number; + transitionDuration: number; +} + +export default class IcicleEventViz extends PureComponent { + render() { + // TODO: create d3 partition & layout w/ memoization & pass into chart here + + return
Icicle Event Chart Component
; + } +} diff --git a/superset-frontend/temporary_superset_ui/superset-ui/plugins/superset-ui-plugins/packages/superset-ui-plugin-chart-icicle-event/src/createMetadata.ts b/superset-frontend/temporary_superset_ui/superset-ui/plugins/superset-ui-plugins/packages/superset-ui-plugin-chart-icicle-event/src/createMetadata.ts new file mode 100644 index 000000000000..f44f113a3bfa --- /dev/null +++ b/superset-frontend/temporary_superset_ui/superset-ui/plugins/superset-ui-plugins/packages/superset-ui-plugin-chart-icicle-event/src/createMetadata.ts @@ -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 { t } from '@superset-ui/translation'; +import { ChartMetadata } from '@superset-ui/chart'; +import thumbnail from './images/thumbnail.png'; + +export default function createMetadata(useLegacyApi = false) { + return new ChartMetadata({ + description: '', + name: t('Icicle Event Chart'), + thumbnail, + useLegacyApi, + }); +} diff --git a/superset-frontend/temporary_superset_ui/superset-ui/plugins/superset-ui-plugins/packages/superset-ui-plugin-chart-icicle-event/src/images/thumbnail.png b/superset-frontend/temporary_superset_ui/superset-ui/plugins/superset-ui-plugins/packages/superset-ui-plugin-chart-icicle-event/src/images/thumbnail.png new file mode 100644 index 0000000000000000000000000000000000000000..568c889ef1a32b1e2f9b112f720ee997521f1965 GIT binary patch literal 52968 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 MjsMrhUJ)t(2NUSg4FCWD literal 0 HcmV?d00001 diff --git a/superset-frontend/temporary_superset_ui/superset-ui/plugins/superset-ui-plugins/packages/superset-ui-plugin-chart-icicle-event/src/index.ts b/superset-frontend/temporary_superset_ui/superset-ui/plugins/superset-ui-plugins/packages/superset-ui-plugin-chart-icicle-event/src/index.ts new file mode 100644 index 000000000000..6427b7699083 --- /dev/null +++ b/superset-frontend/temporary_superset_ui/superset-ui/plugins/superset-ui-plugins/packages/superset-ui-plugin-chart-icicle-event/src/index.ts @@ -0,0 +1,31 @@ +/** + * 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 { ChartPlugin } from '@superset-ui/chart'; +import createMetadata from './createMetadata'; +import transformProps from './transformProps'; + +export default class IcicleEventVizPlugin extends ChartPlugin { + constructor() { + super({ + loadChart: () => import('./IcicleEventViz'), + metadata: createMetadata(), + transformProps, + }); + } +} diff --git a/superset-frontend/temporary_superset_ui/superset-ui/plugins/superset-ui-plugins/packages/superset-ui-plugin-chart-icicle-event/src/transformProps.ts b/superset-frontend/temporary_superset_ui/superset-ui/plugins/superset-ui-plugins/packages/superset-ui-plugin-chart-icicle-event/src/transformProps.ts new file mode 100644 index 000000000000..fd0598767950 --- /dev/null +++ b/superset-frontend/temporary_superset_ui/superset-ui/plugins/superset-ui-plugins/packages/superset-ui-plugin-chart-icicle-event/src/transformProps.ts @@ -0,0 +1,23 @@ +/** + * 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 { ChartProps } from '@superset-ui/chart'; + +export default function transformProps(chartProps: ChartProps) { + return {}; +} diff --git a/superset-frontend/temporary_superset_ui/superset-ui/plugins/superset-ui-plugins/packages/superset-ui-plugin-chart-icicle-event/src/utils/IcicleEventTreeHelpers.ts b/superset-frontend/temporary_superset_ui/superset-ui/plugins/superset-ui-plugins/packages/superset-ui-plugin-chart-icicle-event/src/utils/IcicleEventTreeHelpers.ts new file mode 100644 index 000000000000..bd92b5913d03 --- /dev/null +++ b/superset-frontend/temporary_superset_ui/superset-ui/plugins/superset-ui-plugins/packages/superset-ui-plugin-chart-icicle-event/src/utils/IcicleEventTreeHelpers.ts @@ -0,0 +1,42 @@ +/** + * 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 { max as d3Max } from 'd3-array'; +import { HierarchyRectangularNode } from 'd3-hierarchy'; +import { IcicleEventNode } from '../../types/IcicleEventNode'; + +export function findDepth(node: IcicleEventNode, depth: number = 0): number { + if (!node.children) { + return depth; + } + + const maxDepth = d3Max(node.children.map(child => findDepth(child, depth + 1))); + + return maxDepth || depth; +} + +export function hierarchySort( + a: HierarchyRectangularNode, + b: HierarchyRectangularNode, +): number { + if (a && a.value && b && b.value) { + return b.value - a.value || b.height - a.height; + } + + return 0; +} diff --git a/superset-frontend/temporary_superset_ui/superset-ui/plugins/superset-ui-plugins/packages/superset-ui-plugin-chart-icicle-event/src/utils/RenderedIcicleAccessors.ts b/superset-frontend/temporary_superset_ui/superset-ui/plugins/superset-ui-plugins/packages/superset-ui-plugin-chart-icicle-event/src/utils/RenderedIcicleAccessors.ts new file mode 100644 index 000000000000..60ff1b65ab67 --- /dev/null +++ b/superset-frontend/temporary_superset_ui/superset-ui/plugins/superset-ui-plugins/packages/superset-ui-plugin-chart-icicle-event/src/utils/RenderedIcicleAccessors.ts @@ -0,0 +1,57 @@ +/** + * 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 { HierarchyRectangularNode } from 'd3-hierarchy'; +import { IcicleEventNode } from '../../types/IcicleEventNode'; + +export function x0(isVertical: boolean, d: HierarchyRectangularNode) { + return isVertical ? d.y0 : d.x0; +} + +export function x1(isVertical: boolean, d: HierarchyRectangularNode) { + return isVertical ? d.y1 : d.x1; +} + +export function y0(isVertical: boolean, d: HierarchyRectangularNode) { + return isVertical ? d.x0 : d.y0; +} + +export function y1(isVertical: boolean, d: HierarchyRectangularNode) { + return isVertical ? d.x1 : d.y1; +} + +export function rectWidth( + isVertical: boolean, + boxMargin: { x: number; y: number }, + d: HierarchyRectangularNode, +) { + return Math.max(0, y1(isVertical, d) - y0(isVertical, d) - boxMargin.y * 2); +} + +export function rectHeight( + isVertical: boolean, + boxMargin: { x: number; y: number }, + d: HierarchyRectangularNode, +) { + return Math.max( + 0, + x1(isVertical, d) - + x0(isVertical, d) - + (Math.min(1, (x1(isVertical, d) - x0(isVertical, d)) / 2) + boxMargin.x * 2), + ); +} diff --git a/superset-frontend/temporary_superset_ui/superset-ui/plugins/superset-ui-plugins/packages/superset-ui-plugin-chart-icicle-event/types/IcicleEventNode.ts b/superset-frontend/temporary_superset_ui/superset-ui/plugins/superset-ui-plugins/packages/superset-ui-plugin-chart-icicle-event/types/IcicleEventNode.ts new file mode 100644 index 000000000000..e7c8c88cd89c --- /dev/null +++ b/superset-frontend/temporary_superset_ui/superset-ui/plugins/superset-ui-plugins/packages/superset-ui-plugin-chart-icicle-event/types/IcicleEventNode.ts @@ -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. + */ +export type IcicleEventNode = { + id: string; + event: string; + name?: string; + value: number; + children?: [IcicleEventNode] +} diff --git a/superset-frontend/temporary_superset_ui/superset-ui/plugins/superset-ui-plugins/packages/superset-ui-plugin-chart-icicle-event/types/external.d.ts b/superset-frontend/temporary_superset_ui/superset-ui/plugins/superset-ui-plugins/packages/superset-ui-plugin-chart-icicle-event/types/external.d.ts new file mode 100644 index 000000000000..8f7985ceaf13 --- /dev/null +++ b/superset-frontend/temporary_superset_ui/superset-ui/plugins/superset-ui-plugins/packages/superset-ui-plugin-chart-icicle-event/types/external.d.ts @@ -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. + */ +declare module '*.png' { + const value: any; + export default value; +}