Convert viz-lib to TypeScript (#5310)

Co-authored-by: ts-migrate <>
This commit is contained in:
Elad Ossadon
2020-12-15 18:21:37 -08:00
committed by GitHub
parent b70e95a323
commit c290864ccd
210 changed files with 5245 additions and 1998 deletions

View File

@@ -1,5 +1,4 @@
import React, { useEffect, useState } from "react";
// @ts-expect-error (Must be removed after adding @redash/viz typing)
import ErrorBoundary, { ErrorBoundaryContext } from "@redash/viz/lib/components/ErrorBoundary";
import { Auth } from "@/services/auth";
import { policy } from "@/services/policy";
@@ -62,9 +61,10 @@ export function UserSessionWrapper<P>({ bodyClass, currentRoute, render }: UserS
return (
<ApplicationLayout>
<React.Fragment key={currentRoute.key}>
{/* @ts-expect-error FIXME */}
<ErrorBoundary renderError={(error: Error) => <ErrorMessage error={error} />}>
<ErrorBoundaryContext.Consumer>
{({ handleError }: { handleError: UserSessionWrapperRenderChildrenProps<P>["onError"] }) =>
{({ handleError } /* : { handleError: UserSessionWrapperRenderChildrenProps<P>["onError"] } FIXME bring back type */) =>
render({ ...currentRoute.routeParams, pageTitle: currentRoute.title, onError: handleError })
}
</ErrorBoundaryContext.Consumer>

View File

@@ -15,21 +15,14 @@
"jsx": "react",
"allowSyntheticDefaultImports": true,
"noUnusedLocals": true,
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"lib": ["dom", "dom.iterable", "esnext"],
"forceConsistentCasingInFileNames": true,
"baseUrl": "./",
"paths": {
"@/*": ["./app/*"]
}
},
"skipLibCheck": true
},
"include": [
"app/**/*"
],
"exclude": [
"dist"
]
"include": ["app/**/*"],
"exclude": ["dist"]
}

28
package-lock.json generated
View File

@@ -5384,22 +5384,22 @@
"dev": true
},
"@types/react": {
"version": "16.9.41",
"resolved": "https://registry.npmjs.org/@types/react/-/react-16.9.41.tgz",
"integrity": "sha512-6cFei7F7L4wwuM+IND/Q2cV1koQUvJ8iSV+Gwn0c3kvABZ691g7sp3hfEQHOUBJtccl1gPi+EyNjMIl9nGA0ug==",
"version": "16.14.2",
"resolved": "https://registry.npmjs.org/@types/react/-/react-16.14.2.tgz",
"integrity": "sha512-BzzcAlyDxXl2nANlabtT4thtvbbnhee8hMmH/CcJrISDBVcJS1iOsP1f0OAgSdGE0MsY9tqcrb9YoZcOFv9dbQ==",
"dev": true,
"requires": {
"@types/prop-types": "*",
"csstype": "^2.2.0"
"csstype": "^3.0.2"
}
},
"@types/react-dom": {
"version": "16.9.8",
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-16.9.8.tgz",
"integrity": "sha512-ykkPQ+5nFknnlU6lDd947WbQ6TE3NNzbQAkInC2EKY1qeYdTKp7onFusmYZb+ityzx2YviqT6BXSu+LyWWJwcA==",
"version": "16.9.10",
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-16.9.10.tgz",
"integrity": "sha512-ItatOrnXDMAYpv6G8UCk2VhbYVTjZT9aorLtA/OzDN9XJ2GKcfam68jutoAcILdRjsRUO8qb7AmyObF77Q8QFw==",
"dev": true,
"requires": {
"@types/react": "*"
"@types/react": "^16"
}
},
"@types/sinonjs__fake-timers": {
@@ -9448,9 +9448,9 @@
}
},
"csstype": {
"version": "2.6.11",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.11.tgz",
"integrity": "sha512-l8YyEC9NBkSm783PFTvh0FmJy7s5pFKrDp49ZL7zBGX3fWkO+N4EEyan1qqp8cwPLDcD0OSdyY6hAMoxp34JFw==",
"version": "3.0.5",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.5.tgz",
"integrity": "sha512-uVDi8LpBUKQj6sdxNaTetL6FpeCqTjOvAQuQUa/qAqq8oOd4ivkbhgnqayl0dnPal8Tb/yB1tF+gOvCBiicaiQ==",
"dev": true
},
"cubic-hermite": {
@@ -25447,9 +25447,9 @@
}
},
"typescript": {
"version": "3.9.6",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.6.tgz",
"integrity": "sha512-Pspx3oKAPJtjNwE92YS05HQoY7z2SFyOpHo9MqJor3BXAGNaPUs83CuVp9VISFkSjyRfiTpmKuAYGJB7S7hOxw==",
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.1.2.tgz",
"integrity": "sha512-thGloWsGH3SOxv1SoY7QojKi0tc+8FnOmiarEGMbd/lar7QOEd3hvlx3Fp5y6FlDUGl9L+pd4n2e+oToGMmhRQ==",
"dev": true
},
"uglify-js": {

View File

@@ -95,8 +95,8 @@
"@types/hoist-non-react-statics": "^3.3.1",
"@types/lodash": "^4.14.157",
"@types/prop-types": "^15.7.3",
"@types/react": "^16.9.41",
"@types/react-dom": "^16.9.8",
"@types/react": "^16.14.2",
"@types/react-dom": "^16.9.10",
"@types/sql-formatter": "^2.3.0",
"@typescript-eslint/eslint-plugin": "^2.10.0",
"@typescript-eslint/parser": "^2.10.0",
@@ -144,7 +144,7 @@
"request": "^2.88.0",
"request-cookies": "^1.1.0",
"style-loader": "^2.0.0",
"typescript": "^3.9.6",
"typescript": "^4.1.2",
"url-loader": "^1.1.2",
"webpack": "^4.44.2",
"webpack-build-notifier": "^0.1.30",

View File

@@ -1,5 +1,5 @@
{
"presets": ["@babel/preset-env", "@babel/preset-react"],
"presets": ["@babel/preset-env", "@babel/preset-react", "@babel/preset-typescript"],
"plugins": [
"@babel/plugin-proposal-class-properties",
[

View File

@@ -1,9 +0,0 @@
{
"compilerOptions": {
"baseUrl": "./",
"paths": {
"@/*": ["./src/*"]
}
},
"exclude": ["dist", "lib"]
}

2149
viz-lib/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -5,10 +5,13 @@
"main": "dist/redash-visualizations.js",
"scripts": {
"clean": "rm -rf lib dist",
"build:babel": "babel src --out-dir lib --source-maps --ignore 'src/**/*.test.js' --copy-files --no-copy-ignored",
"type-check": "tsc --noEmit",
"type-gen": "tsc --emitDeclarationOnly",
"build:babel:base": "babel src --out-dir lib --source-maps --ignore 'src/**/*.test.js' --copy-files --no-copy-ignored --extensions .ts,.tsx,.js,.jsx",
"build:babel": "npm run type-gen && npm run build:babel:base",
"build:webpack": "webpack",
"build": " NODE_ENV=production npm-run-all clean build:babel build:webpack",
"watch:babel": "babel src --watch --out-dir lib --source-maps --ignore 'src/**/*.test.js' --copy-files --no-copy-ignored",
"watch:babel": "npm run build:babel:base -- --watch",
"watch:webpack": "webpack --watch",
"watch": "npm-run-all --parallel watch:*",
"version": "npm run build",
@@ -34,6 +37,20 @@
"@babel/plugin-proposal-class-properties": "^7.8.3",
"@babel/preset-env": "^7.9.0",
"@babel/preset-react": "^7.9.4",
"@babel/preset-typescript": "^7.12.7",
"@types/chroma-js": "^2.1.2",
"@types/d3": "^6.2.0",
"@types/d3-cloud": "^1.2.3",
"@types/debug": "^4.1.5",
"@types/dompurify": "^2.0.4",
"@types/enzyme": "^3.10.8",
"@types/jest": "^26.0.18",
"@types/leaflet": "^1.5.19",
"@types/numeral": "0.0.28",
"@types/plotly.js": "^1.54.4",
"@types/react": "^17.0.0",
"@types/react-dom": "^17.0.0",
"@types/tinycolor2": "^1.4.2",
"babel-loader": "^8.1.0",
"babel-plugin-istanbul": "^6.0.0",
"babel-plugin-module-resolver": "^4.0.0",
@@ -50,6 +67,8 @@
"prettier": "^1.19.1",
"prop-types": "^15.7.2",
"style-loader": "^1.1.4",
"ts-migrate": "^0.1.10",
"typescript": "^4.1.2",
"webpack": "^4.42.1",
"webpack-cli": "^3.3.11"
},

View File

@@ -1,6 +1,5 @@
import { isNil, isArray, chunk, map, filter, toPairs } from "lodash";
import React, { useState, useEffect } from "react";
import PropTypes from "prop-types";
import tinycolor from "tinycolor2";
import TextInput from "antd/lib/input";
import Typography from "antd/lib/typography";
@@ -8,7 +7,7 @@ import Swatch from "./Swatch";
import "./input.less";
function preparePresets(presetColors, presetColumns) {
function preparePresets(presetColors: any, presetColumns: any) {
presetColors = isArray(presetColors) ? map(presetColors, v => [null, v]) : toPairs(presetColors);
presetColors = map(presetColors, ([title, value]) => {
if (isNil(value)) {
@@ -23,7 +22,7 @@ function preparePresets(presetColors, presetColumns) {
return chunk(filter(presetColors), presetColumns);
}
function validateColor(value, callback, prefix = "#") {
function validateColor(value: any, callback: any, prefix = "#") {
if (isNil(value)) {
callback(null);
}
@@ -33,13 +32,25 @@ function validateColor(value, callback, prefix = "#") {
}
}
export default function Input({ color, presetColors, presetColumns, onChange, onPressEnter }) {
type OwnProps = {
color?: string;
presetColors?: string[] | {
[key: string]: string;
};
presetColumns?: number;
onChange?: (...args: any[]) => any;
onPressEnter?: (...args: any[]) => any;
};
type Props = OwnProps & typeof Input.defaultProps;
export default function Input({ color, presetColors, presetColumns, onChange, onPressEnter }: Props) {
const [inputValue, setInputValue] = useState("");
const [isInputFocused, setIsInputFocused] = useState(false);
const presets = preparePresets(presetColors, presetColumns);
function handleInputChange(value) {
function handleInputChange(value: any) {
setInputValue(value);
validateColor(value, onChange);
}
@@ -55,6 +66,7 @@ export default function Input({ color, presetColors, presetColumns, onChange, on
{map(presets, (group, index) => (
<div className="color-picker-input-swatches" key={`preset-row-${index}`}>
{map(group, ([title, value]) => (
// @ts-expect-error ts-migrate(2322) FIXME: Type 'any' is not assignable to type 'never'.
<Swatch key={value} color={value} title={title} size={30} onClick={() => validateColor(value, onChange)} />
))}
</div>
@@ -74,17 +86,6 @@ export default function Input({ color, presetColors, presetColumns, onChange, on
);
}
Input.propTypes = {
color: PropTypes.string,
presetColors: PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.string), // array of colors (no tooltips)
PropTypes.objectOf(PropTypes.string), // color name => color value
]),
presetColumns: PropTypes.number,
onChange: PropTypes.func,
onPressEnter: PropTypes.func,
};
Input.defaultProps = {
color: "#FFFFFF",
presetColors: null,

View File

@@ -1,11 +1,21 @@
import React, { useMemo } from "react";
import PropTypes from "prop-types";
import cx from "classnames";
import { validateColor, getColorName } from "./utils";
import "./label.less";
export default function Label({ className, color, presetColors, ...props }) {
type OwnProps = {
className?: string;
color?: string;
presetColors?: string[] | {
[key: string]: string;
};
};
type Props = OwnProps & typeof Label.defaultProps;
// @ts-expect-error ts-migrate(2700) FIXME: Rest types may only be created from object types.
export default function Label({ className, color, presetColors, ...props }: Props) {
const name = useMemo(() => getColorName(validateColor(color), presetColors), [color, presetColors]);
return (
@@ -15,15 +25,6 @@ export default function Label({ className, color, presetColors, ...props }) {
);
}
Label.propTypes = {
className: PropTypes.string,
color: PropTypes.string,
presetColors: PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.string), // array of colors (no tooltips)
PropTypes.objectOf(PropTypes.string), // color name => color value
]),
};
Label.defaultProps = {
className: null,
color: "#FFFFFF",

View File

@@ -1,15 +1,26 @@
import { isString } from "lodash";
import React from "react";
import PropTypes from "prop-types";
import cx from "classnames";
import Tooltip from "antd/lib/tooltip";
import "./swatch.less";
export default function Swatch({ className, color, title, size, style, ...props }) {
type OwnProps = {
className?: string;
style?: any;
title?: string;
color?: string;
size?: number;
};
type Props = OwnProps & typeof Swatch.defaultProps;
// @ts-expect-error ts-migrate(2700) FIXME: Rest types may only be created from object types.
export default function Swatch({ className, color, title, size, style, ...props }: Props) {
const result = (
<span
className={cx("color-swatch", className)}
// @ts-expect-error ts-migrate(2698) FIXME: Spread types may only be created from object types... Remove this comment to see the full error message
style={{ backgroundColor: color, width: size, ...style }}
{...props}
/>
@@ -25,14 +36,6 @@ export default function Swatch({ className, color, title, size, style, ...props
return result;
}
Swatch.propTypes = {
className: PropTypes.string,
style: PropTypes.object,
title: PropTypes.string,
color: PropTypes.string,
size: PropTypes.number,
};
Swatch.defaultProps = {
className: null,
style: null,

View File

@@ -1,6 +1,5 @@
import { toString } from "lodash";
import React, { useState, useEffect, useMemo } from "react";
import PropTypes from "prop-types";
import cx from "classnames";
import Popover from "antd/lib/popover";
import Card from "antd/lib/card";
@@ -17,18 +16,24 @@ import { validateColor } from "./utils";
import "./index.less";
export default function ColorPicker({
color,
placement,
presetColors,
presetColumns,
interactive,
children,
onChange,
triggerProps,
addonBefore,
addonAfter,
}) {
type OwnProps = {
color?: string;
placement?: "top" | "left" | "right" | "bottom" | "topLeft" | "topRight" | "bottomLeft" | "bottomRight" | "leftTop" | "leftBottom" | "rightTop" | "rightBottom";
presetColors?: string[] | {
[key: string]: string;
};
presetColumns?: number;
interactive?: boolean;
triggerProps?: any;
children?: React.ReactNode;
addonBefore?: React.ReactNode;
addonAfter?: React.ReactNode;
onChange?: (...args: any[]) => any;
};
type Props = OwnProps & typeof ColorPicker.defaultProps;
export default function ColorPicker({ color, placement, presetColors, presetColumns, interactive, children, onChange, triggerProps, addonBefore, addonAfter, }: Props) {
const [visible, setVisible] = useState(false);
const validatedColor = useMemo(() => validateColor(color), [color]);
const [currentColor, setCurrentColor] = useState("");
@@ -36,6 +41,7 @@ export default function ColorPicker({
function handleApply() {
setVisible(false);
if (!interactive) {
// @ts-expect-error ts-migrate(2349) FIXME: This expression is not callable.
onChange(currentColor);
}
}
@@ -58,15 +64,17 @@ export default function ColorPicker({
);
}
function handleInputChange(newColor) {
function handleInputChange(newColor: any) {
setCurrentColor(newColor);
if (interactive) {
// @ts-expect-error ts-migrate(2349) FIXME: This expression is not callable.
onChange(newColor);
}
}
useEffect(() => {
if (visible) {
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'string | null' is not assignable... Remove this comment to see the full error message
setCurrentColor(validatedColor);
}
}, [validatedColor, visible]);
@@ -77,6 +85,7 @@ export default function ColorPicker({
<Popover
arrowPointAtCenter
overlayClassName={`color-picker ${interactive ? "color-picker-interactive" : "color-picker-with-actions"}`}
// @ts-expect-error ts-migrate(2322) FIXME: Type '{ "--color-picker-selected-color": string; }... Remove this comment to see the full error message
overlayStyle={{ "--color-picker-selected-color": currentColor }}
content={
<Card
@@ -86,14 +95,18 @@ export default function ColorPicker({
title={toString(currentColor).toUpperCase()}
headStyle={{
backgroundColor: currentColor,
// @ts-expect-error ts-migrate(2322) FIXME: Type 'string | null | undefined' is not assignable... Remove this comment to see the full error message
color: chooseTextColorForBackground(currentColor),
}}
actions={actions}>
<ColorInput
// @ts-expect-error ts-migrate(2322) FIXME: Type 'string' is not assignable to type 'never'.
color={currentColor}
presetColors={presetColors}
presetColumns={presetColumns}
// @ts-expect-error ts-migrate(2322) FIXME: Type '(newColor: any) => void' is not assignable t... Remove this comment to see the full error message
onChange={handleInputChange}
// @ts-expect-error ts-migrate(2322) FIXME: Type '() => void' is not assignable to type 'never... Remove this comment to see the full error message
onPressEnter={handleApply}
/>
</Card>
@@ -107,6 +120,7 @@ export default function ColorPicker({
color={validatedColor}
size={30}
{...triggerProps}
// @ts-expect-error ts-migrate(2339) FIXME: Property 'className' does not exist on type 'never... Remove this comment to see the full error message
className={cx("color-picker-trigger", triggerProps.className)}
/>
)}
@@ -116,35 +130,6 @@ export default function ColorPicker({
);
}
ColorPicker.propTypes = {
color: PropTypes.string,
placement: PropTypes.oneOf([
"top",
"left",
"right",
"bottom",
"topLeft",
"topRight",
"bottomLeft",
"bottomRight",
"leftTop",
"leftBottom",
"rightTop",
"rightBottom",
]),
presetColors: PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.string), // array of colors (no tooltips)
PropTypes.objectOf(PropTypes.string), // color name => color value
]),
presetColumns: PropTypes.number,
interactive: PropTypes.bool,
triggerProps: PropTypes.object, // eslint-disable-line react/forbid-prop-types
children: PropTypes.node,
addonBefore: PropTypes.node,
addonAfter: PropTypes.node,
onChange: PropTypes.func,
};
ColorPicker.defaultProps = {
color: "#FFFFFF",
placement: "top",

View File

@@ -1,12 +1,12 @@
import { isArray, findKey } from "lodash";
import tinycolor from "tinycolor2";
export function validateColor(value, fallback = null) {
export function validateColor(value: any, fallback = null) {
value = tinycolor(value);
return value.isValid() ? "#" + value.toHex().toUpperCase() : fallback;
}
export function getColorName(color, presetColors) {
export function getColorName(color: any, presetColors: any) {
if (isArray(presetColors)) {
return color;
}

View File

@@ -1,13 +1,12 @@
import { isFunction } from "lodash";
import React from "react";
import PropTypes from "prop-types";
import debug from "debug";
import Alert from "antd/lib/alert";
const logger = debug("redash:errors");
export const ErrorBoundaryContext = React.createContext({
handleError: error => {
handleError: (error: any) => {
// Allow calling chain to roll up, and then throw the error in global context
setTimeout(() => {
throw error;
@@ -16,23 +15,29 @@ export const ErrorBoundaryContext = React.createContext({
reset: () => {},
});
export function ErrorMessage({ children }) {
type OwnErrorMessageProps = {
children?: React.ReactNode;
};
type ErrorMessageProps = OwnErrorMessageProps & typeof ErrorMessage.defaultProps;
export function ErrorMessage({ children }: ErrorMessageProps) {
return <Alert message={children} type="error" showIcon />;
}
ErrorMessage.propTypes = {
children: PropTypes.node,
};
ErrorMessage.defaultProps = {
children: "Something went wrong.",
};
export default class ErrorBoundary extends React.Component {
static propTypes = {
children: PropTypes.node,
renderError: PropTypes.func, // error => ReactNode
};
type OwnErrorBoundaryProps = {
renderError?: (...args: any[]) => any;
};
type ErrorBoundaryState = any;
type ErrorBoundaryProps = OwnErrorBoundaryProps & typeof ErrorBoundary.defaultProps;
export default class ErrorBoundary extends React.Component<ErrorBoundaryProps, ErrorBoundaryState> {
static defaultProps = {
children: null,
@@ -41,10 +46,13 @@ export default class ErrorBoundary extends React.Component {
state = { error: null };
handleError = error => {
handleError = (error: any) => {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'getDerivedStateFromError' does not exist... Remove this comment to see the full error message
this.setState(this.constructor.getDerivedStateFromError(error));
this.componentDidCatch(error, null);
// @ts-expect-error ts-migrate(2339) FIXME: Property 'handleException' does not exist on type ... Remove this comment to see the full error message
if (isFunction(window.handleException)) {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'handleException' does not exist on type ... Remove this comment to see the full error message
window.handleException(error);
}
};
@@ -53,11 +61,11 @@ export default class ErrorBoundary extends React.Component {
this.setState({ error: null });
};
static getDerivedStateFromError(error) {
static getDerivedStateFromError(error: any) {
return { error };
}
componentDidCatch(error, errorInfo) {
componentDidCatch(error: any, errorInfo: any) {
logger(error, errorInfo);
}
@@ -67,6 +75,7 @@ export default class ErrorBoundary extends React.Component {
if (error) {
if (isFunction(renderError)) {
// @ts-expect-error ts-migrate(2349) FIXME: This expression is not callable.
return renderError(error);
}
return <ErrorMessage />;

View File

@@ -6,15 +6,18 @@ const HtmlContent = React.memo(function HtmlContent({ children, ...props }) {
return (
<div
{...props}
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'ReactNode' is not assignable to ... Remove this comment to see the full error message
dangerouslySetInnerHTML={{ __html: sanitize(children) }} // eslint-disable-line react/no-danger
/>
);
});
// @ts-expect-error ts-migrate(2339) FIXME: Property 'propTypes' does not exist on type 'Named... Remove this comment to see the full error message
HtmlContent.propTypes = {
children: PropTypes.string,
};
// @ts-expect-error ts-migrate(2339) FIXME: Property 'defaultProps' does not exist on type 'Na... Remove this comment to see the full error message
HtmlContent.defaultProps = {
children: "",
};

View File

@@ -1,6 +1,5 @@
import { pickBy, startsWith } from "lodash";
import React from "react";
import PropTypes from "prop-types";
import cx from "classnames";
import Radio from "antd/lib/radio";
import Tooltip from "antd/lib/tooltip";
@@ -11,7 +10,14 @@ import AlignRightOutlinedIcon from "@ant-design/icons/AlignRightOutlined";
import "./index.less";
export default function TextAlignmentSelect({ className, ...props }) {
type OwnProps = {
className?: string;
};
type Props = OwnProps & typeof TextAlignmentSelect.defaultProps;
// @ts-expect-error ts-migrate(2700) FIXME: Rest types may only be created from object types.
export default function TextAlignmentSelect({ className, ...props }: Props) {
return (
// Antd RadioGroup does not use any custom attributes
<div {...pickBy(props, (v, k) => startsWith(k, "data-"))}>
@@ -36,10 +42,6 @@ export default function TextAlignmentSelect({ className, ...props }) {
);
}
TextAlignmentSelect.propTypes = {
className: PropTypes.string,
};
TextAlignmentSelect.defaultProps = {
className: null,
};

View File

@@ -3,11 +3,16 @@
import { isFinite, isString, isArray, isObject, keys, map } from "lodash";
import React, { useState } from "react";
import cx from "classnames";
import PropTypes from "prop-types";
import "./json-view-interactive.less";
function JsonBlock({ value, children, openingBrace, closingBrace, withKeys }) {
function JsonBlock({
value,
children,
openingBrace,
closingBrace,
withKeys
}: any) {
const [isExpanded, setIsExpanded] = useState(false);
const objectKeys = keys(value);
@@ -56,7 +61,10 @@ function JsonBlock({ value, children, openingBrace, closingBrace, withKeys }) {
);
}
function JsonValue({ value, children }) {
function JsonValue({
value,
children
}: any) {
if (value === null || value === false || value === true || isFinite(value)) {
return (
<span className="jvi-value jvi-primitive">
@@ -92,7 +100,13 @@ function JsonValue({ value, children }) {
return null;
}
export default function JsonViewInteractive({ value }) {
type OwnJsonViewInteractiveProps = {
value?: any;
};
type JsonViewInteractiveProps = OwnJsonViewInteractiveProps & typeof JsonViewInteractive.defaultProps;
export default function JsonViewInteractive({ value }: JsonViewInteractiveProps) {
return (
<span className="jvi-item jvi-root">
<JsonValue value={value} />
@@ -100,10 +114,6 @@ export default function JsonViewInteractive({ value }) {
);
}
JsonViewInteractive.propTypes = {
value: PropTypes.any, // eslint-disable-line react/forbid-prop-types
};
JsonViewInteractive.defaultProps = {
// `null` will be rendered as "null" because it is a valid JSON value, so use `undefined` for no value
value: undefined,

View File

@@ -1,20 +1,36 @@
import { isFunction, wrap } from "lodash";
import React, { useRef, useState } from "react";
import PropTypes from "prop-types";
import cx from "classnames";
// @ts-expect-error ts-migrate(2724) FIXME: Module '"../../../node_modules/react-sortable-hoc/... Remove this comment to see the full error message
import { sortableContainer, sortableElement, sortableHandle } from "react-sortable-hoc";
import "./style.less";
export const DragHandle = sortableHandle(({ className, ...restProps }) => (
export const DragHandle = sortableHandle(({
className,
...restProps
}: any) => (
<div className={cx("drag-handle", className)} {...restProps} />
));
export const SortableContainerWrapper = sortableContainer(({ children }) => children);
export const SortableContainerWrapper = sortableContainer(({
children
}: any) => children);
export const SortableElement = sortableElement(({ children }) => children);
export const SortableElement = sortableElement(({
children
}: any) => children);
export function SortableContainer({ disabled, containerComponent, containerProps, children, ...wrapperProps }) {
type OwnProps = {
disabled?: boolean;
containerComponent?: React.ReactElement;
containerProps?: any;
children?: React.ReactNode;
};
type Props = OwnProps & typeof SortableContainer.defaultProps;
export function SortableContainer({ disabled, containerComponent, containerProps, children, ...wrapperProps }: Props) {
const containerRef = useRef();
const [isDragging, setIsDragging] = useState(false);
@@ -25,22 +41,26 @@ export function SortableContainer({ disabled, containerComponent, containerProps
// Disabled state:
// - forbid drag'n'drop (and therefore no need to hook events
// - don't override anything on container element
// @ts-expect-error ts-migrate(2339) FIXME: Property 'shouldCancelStart' does not exist on typ... Remove this comment to see the full error message
wrapperProps.shouldCancelStart = () => true;
} else {
// Enabled state:
// - use container element as a default helper element
// @ts-expect-error ts-migrate(2339) FIXME: Property 'helperContainer' does not exist on type ... Remove this comment to see the full error message
wrapperProps.helperContainer = wrap(wrapperProps.helperContainer, helperContainer =>
isFunction(helperContainer) ? helperContainer(containerRef.current) : containerRef.current
);
// - hook drag start/end events
// @ts-expect-error ts-migrate(2339) FIXME: Property 'updateBeforeSortStart' does not exist on... Remove this comment to see the full error message
wrapperProps.updateBeforeSortStart = wrap(wrapperProps.updateBeforeSortStart, (updateBeforeSortStart, ...args) => {
setIsDragging(true);
if (isFunction(updateBeforeSortStart)) {
updateBeforeSortStart(...args);
}
});
// @ts-expect-error ts-migrate(2339) FIXME: Property 'onSortEnd' does not exist on type '{}'.
wrapperProps.onSortEnd = wrap(wrapperProps.onSortEnd, (onSortEnd, ...args) => {
setIsDragging(false);
if (isFunction(onSortEnd)) {
@@ -60,18 +80,12 @@ export function SortableContainer({ disabled, containerComponent, containerProps
const ContainerComponent = containerComponent;
return (
<SortableContainerWrapper {...wrapperProps}>
{/* @ts-expect-error ts-migrate(2604) FIXME: JSX element type 'ContainerComponent' does not hav... Remove this comment to see the full error message */}
<ContainerComponent {...containerProps}>{children}</ContainerComponent>
</SortableContainerWrapper>
);
}
SortableContainer.propTypes = {
disabled: PropTypes.bool,
containerComponent: PropTypes.elementType,
containerProps: PropTypes.object, // eslint-disable-line react/forbid-prop-types
children: PropTypes.node,
};
SortableContainer.defaultProps = {
disabled: false,
containerComponent: "div",

View File

@@ -1,12 +1,18 @@
import React from "react";
import PropTypes from "prop-types";
import Popover from "antd/lib/popover";
import QuestionCircleFilledIcon from "@ant-design/icons/QuestionCircleFilled";
import { visualizationsSettings } from "@/visualizations/visualizationsSettings";
import "./context-help.less";
export default function ContextHelp({ icon, children, ...props }) {
type OwnContextHelpProps = {
icon?: React.ReactNode;
children?: React.ReactNode;
};
type ContextHelpProps = OwnContextHelpProps & typeof ContextHelp.defaultProps;
export default function ContextHelp({ icon, children, ...props }: ContextHelpProps) {
return (
<Popover {...props} content={children}>
{icon || ContextHelp.defaultIcon}
@@ -14,11 +20,6 @@ export default function ContextHelp({ icon, children, ...props }) {
);
}
ContextHelp.propTypes = {
icon: PropTypes.node,
children: PropTypes.node,
};
ContextHelp.defaultProps = {
icon: null,
children: null,
@@ -30,6 +31,7 @@ function NumberFormatSpecs() {
const { HelpTriggerComponent } = visualizationsSettings;
return (
<HelpTriggerComponent
// @ts-expect-error ts-migrate(2322) FIXME: Type '{ children: Element; type: string; title: st... Remove this comment to see the full error message
type="NUMBER_FORMAT_SPECS"
title="Formatting Numbers"
href="https://redash.io/help/user-guide/visualizations/formatting-numbers"

View File

@@ -1,10 +1,17 @@
import React from "react";
import PropTypes from "prop-types";
import cx from "classnames";
import "./Section.less";
function SectionTitle({ className, children, ...props }) {
type OwnSectionTitleProps = {
className?: string;
children?: React.ReactNode;
};
type SectionTitleProps = OwnSectionTitleProps & typeof SectionTitle.defaultProps;
// @ts-expect-error ts-migrate(2700) FIXME: Rest types may only be created from object types.
function SectionTitle({ className, children, ...props }: SectionTitleProps) {
if (!children) {
return null;
}
@@ -16,17 +23,20 @@ function SectionTitle({ className, children, ...props }) {
);
}
SectionTitle.propTypes = {
className: PropTypes.string,
children: PropTypes.node,
};
SectionTitle.defaultProps = {
className: null,
children: null,
};
export default function Section({ className, children, ...props }) {
type OwnSectionProps = {
className?: string;
children?: React.ReactNode;
};
type SectionProps = OwnSectionProps & typeof Section.defaultProps;
// @ts-expect-error ts-migrate(2700) FIXME: Rest types may only be created from object types.
export default function Section({ className, children, ...props }: SectionProps) {
return (
<div className={cx("visualization-editor-section", className)} {...props}>
{children}
@@ -34,11 +44,6 @@ export default function Section({ className, children, ...props }) {
);
}
Section.propTypes = {
className: PropTypes.string,
children: PropTypes.node,
};
Section.defaultProps = {
className: null,
children: null,

View File

@@ -1,11 +1,19 @@
import React, { useMemo } from "react";
import PropTypes from "prop-types";
import AntSwitch from "antd/lib/switch";
import Typography from "antd/lib/typography";
import "./Switch.less";
export default function Switch({ id, children, disabled, ...props }) {
type OwnProps = {
id?: string;
disabled?: boolean;
children?: React.ReactNode;
};
type Props = OwnProps & typeof Switch.defaultProps;
// @ts-expect-error ts-migrate(2700) FIXME: Rest types may only be created from object types.
export default function Switch({ id, children, disabled, ...props }: Props) {
const fallbackId = useMemo(
() =>
`visualization-editor-control-${Math.random()
@@ -29,12 +37,6 @@ export default function Switch({ id, children, disabled, ...props }) {
return <AntSwitch {...props} />;
}
Switch.propTypes = {
id: PropTypes.string,
disabled: PropTypes.bool,
children: PropTypes.node,
};
Switch.defaultProps = {
id: null,
disabled: false,

View File

@@ -5,7 +5,10 @@ import withControlLabel from "./withControlLabel";
import "./TextArea.less";
function TextArea({ className, ...otherProps }) {
function TextArea({
className,
...otherProps
}: any) {
return <AntInput.TextArea className={cx("visualization-editor-text-area", className)} {...otherProps} />;
}

View File

@@ -1,56 +0,0 @@
import { isFunction, map, filter, extend, merge } from "lodash";
import React from "react";
import PropTypes from "prop-types";
import Tabs from "antd/lib/tabs";
import { EditorPropTypes } from "@/visualizations/prop-types";
export const UpdateOptionsStrategy = {
replace: (existingOptions, newOptions) => merge({}, newOptions),
shallowMerge: (existingOptions, newOptions) => extend({}, existingOptions, newOptions),
deepMerge: (existingOptions, newOptions) => merge({}, existingOptions, newOptions),
};
export function TabbedEditor({ tabs, options, data, onOptionsChange, ...restProps }) {
const optionsChanged = (newOptions, updateStrategy = UpdateOptionsStrategy.deepMerge) => {
onOptionsChange(updateStrategy(options, newOptions));
};
tabs = filter(tabs, tab => (isFunction(tab.isAvailable) ? tab.isAvailable(options, data) : true));
return (
<Tabs animated={false} tabBarGutter={20}>
{map(tabs, ({ key, title, component: Component }) => (
<Tabs.TabPane
key={key}
tab={<span data-test={`VisualizationEditor.Tabs.${key}`}>{isFunction(title) ? title(options) : title}</span>}>
<Component options={options} data={data} onOptionsChange={optionsChanged} {...restProps} />
</Tabs.TabPane>
))}
</Tabs>
);
}
TabbedEditor.propTypes = {
...EditorPropTypes,
tabs: PropTypes.arrayOf(
PropTypes.shape({
key: PropTypes.string.isRequired,
title: PropTypes.oneOfType([
PropTypes.string,
PropTypes.func, // (options) => string
]).isRequired,
isAvailable: PropTypes.func, // (options) => boolean
component: PropTypes.func.isRequired,
})
),
};
TabbedEditor.defaultProps = {
tabs: [],
};
export default function createTabbedEditor(tabs) {
return function TabbedEditorWrapper(props) {
return <TabbedEditor {...props} tabs={tabs} />;
};
}

View File

@@ -0,0 +1,57 @@
import { isFunction, map, filter, extend, merge } from "lodash";
import React from "react";
import Tabs from "antd/lib/tabs";
import { EditorPropTypes } from "@/visualizations/prop-types";
export const UpdateOptionsStrategy = {
replace: (existingOptions: any, newOptions: any) => merge({}, newOptions),
shallowMerge: (existingOptions: any, newOptions: any) => extend({}, existingOptions, newOptions),
deepMerge: (existingOptions: any, newOptions: any) => merge({}, existingOptions, newOptions),
};
/*
(ts-migrate) TODO: Migrate the remaining prop types
...EditorPropTypes
*/
type OwnProps = {
tabs?: {
key: string;
title: string | ((...args: any[]) => any);
isAvailable?: (...args: any[]) => any;
component: (...args: any[]) => any;
}[];
};
type Props = OwnProps & typeof TabbedEditor.defaultProps;
// @ts-expect-error ts-migrate(2339) FIXME: Property 'options' does not exist on type 'Props'.
export function TabbedEditor({ tabs, options, data, onOptionsChange, ...restProps }: Props) {
const optionsChanged = (newOptions: any, updateStrategy = UpdateOptionsStrategy.deepMerge) => {
onOptionsChange(updateStrategy(options, newOptions));
};
// @ts-expect-error ts-migrate(2322) FIXME: Type '(number | ((() => string) & (() => string)) ... Remove this comment to see the full error message
tabs = filter(tabs, tab => (isFunction(tab.isAvailable) ? tab.isAvailable(options, data) : true));
return (
<Tabs animated={false} tabBarGutter={20}>
{map(tabs, ({ key, title, component: Component }) => (
<Tabs.TabPane
key={key}
tab={<span data-test={`VisualizationEditor.Tabs.${key}`}>{isFunction(title) ? title(options) : title}</span>}>
<Component options={options} data={data} onOptionsChange={optionsChanged} {...restProps} />
</Tabs.TabPane>
))}
</Tabs>
);
}
TabbedEditor.defaultProps = {
tabs: [],
};
export default function createTabbedEditor(tabs: any) {
return function TabbedEditorWrapper(props: any) {
return <TabbedEditor {...props} tabs={tabs} />;
};
}

View File

@@ -1,13 +1,22 @@
import React, { useMemo } from "react";
import cx from "classnames";
import PropTypes from "prop-types";
import hoistNonReactStatics from "hoist-non-react-statics";
import * as Grid from "antd/lib/grid";
import Typography from "antd/lib/typography";
import "./control-label.less";
export function ControlLabel({ layout, label, labelProps, disabled, children }) {
type OwnProps = {
layout?: "vertical" | "horizontal";
label?: React.ReactNode;
labelProps?: any;
disabled?: boolean;
children?: React.ReactNode;
};
type Props = OwnProps & typeof ControlLabel.defaultProps;
export function ControlLabel({ layout, label, labelProps, disabled, children }: Props) {
if (layout === "vertical" && label) {
return (
<div className="visualization-editor-control-label visualization-editor-control-label-vertical">
@@ -23,6 +32,7 @@ export function ControlLabel({ layout, label, labelProps, disabled, children })
return (
<Grid.Row
className="visualization-editor-control-label visualization-editor-control-label-horizontal"
// @ts-expect-error ts-migrate(2322) FIXME: Type '{ children: Element[]; className: string; ty... Remove this comment to see the full error message
type="flex"
align="middle"
gutter={15}>
@@ -39,14 +49,6 @@ export function ControlLabel({ layout, label, labelProps, disabled, children })
return children;
}
ControlLabel.propTypes = {
layout: PropTypes.oneOf(["vertical", "horizontal"]),
label: PropTypes.node,
labelProps: PropTypes.object, // eslint-disable-line react/forbid-prop-types
disabled: PropTypes.bool,
children: PropTypes.node,
};
ControlLabel.defaultProps = {
layout: "vertical",
label: null,
@@ -54,9 +56,17 @@ ControlLabel.defaultProps = {
children: null,
};
export default function withControlLabel(WrappedControl) {
export default function withControlLabel(WrappedControl: any) {
// eslint-disable-next-line react/prop-types
function ControlWrapper({ className, id, layout, label, labelProps, disabled, ...props }) {
function ControlWrapper({
className,
id,
layout,
label,
labelProps,
disabled,
...props
}: any) {
const fallbackId = useMemo(
() =>
`visualization-editor-control-${Math.random()
@@ -71,6 +81,7 @@ export default function withControlLabel(WrappedControl) {
return (
<ControlLabel layout={layout} label={label} labelProps={labelProps} disabled={disabled}>
{/* @ts-expect-error ts-migrate(2322) FIXME: Type 'Element' is not assignable to type 'null | u... Remove this comment to see the full error message */}
<WrappedControl
className={cx("visualization-editor-input", className)}
id={labelProps.htmlFor}

View File

@@ -1,7 +1,7 @@
import { maxBy } from "lodash";
import chroma from "chroma-js";
export default function chooseTextColorForBackground(backgroundColor, textColors = ["#ffffff", "#333333"]) {
export default function chooseTextColorForBackground(backgroundColor: any, textColors = ["#ffffff", "#333333"]) {
try {
backgroundColor = chroma(backgroundColor);
return maxBy(textColors, color => chroma.contrast(backgroundColor, color));

View File

@@ -1,10 +1,11 @@
import { isEqual } from "lodash";
import { useMemo, useRef } from "react";
export default function useMemoWithDeepCompare(create, inputs) {
export default function useMemoWithDeepCompare(create: any, inputs: any) {
const valueRef = useRef();
const value = useMemo(create, inputs);
if (!isEqual(value, valueRef.current)) {
// @ts-expect-error ts-migrate(2322) FIXME: Type 'unknown' is not assignable to type 'undefine... Remove this comment to see the full error message
valueRef.current = value;
}
return valueRef.current;

View File

@@ -1,39 +0,0 @@
import { each, debounce } from "lodash";
export default function createReferenceCountingCache({ cleanupDelay = 2000 } = {}) {
const items = {};
const cleanup = debounce(() => {
each(items, (item, key) => {
if (item.refCount <= 0) {
delete items[key];
}
});
}, cleanupDelay);
function get(key, getter) {
if (!items[key]) {
items[key] = {
value: getter(),
refCount: 0,
};
}
const item = items[key];
item.refCount += 1;
return item.value;
}
function release(key) {
if (items[key]) {
const item = items[key];
if (item.refCount > 0) {
item.refCount -= 1;
if (item.refCount <= 0) {
cleanup();
}
}
}
}
return { get, release };
}

View File

@@ -0,0 +1,46 @@
import { each, debounce } from "lodash";
export default function createReferenceCountingCache({ cleanupDelay = 2000 } = {}) {
const items = {};
const cleanup = debounce(() => {
each(items, (item, key) => {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'refCount' does not exist on type 'never'... Remove this comment to see the full error message
if (item.refCount <= 0) {
// @ts-expect-error ts-migrate(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
delete items[key];
}
});
}, cleanupDelay);
function get(key: any, getter: any) {
// @ts-expect-error ts-migrate(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
if (!items[key]) {
// @ts-expect-error ts-migrate(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
items[key] = {
value: getter(),
refCount: 0,
};
}
// @ts-expect-error ts-migrate(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
const item = items[key];
item.refCount += 1;
return item.value;
}
function release(key: any) {
// @ts-expect-error ts-migrate(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
if (items[key]) {
// @ts-expect-error ts-migrate(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
const item = items[key];
if (item.refCount > 0) {
item.refCount -= 1;
if (item.refCount <= 0) {
cleanup();
}
}
}
}
return { get, release };
}

View File

@@ -1,7 +1,7 @@
import moment from "moment";
import { visualizationsSettings } from "@/visualizations/visualizationsSettings";
function formatDateTime(value) {
function formatDateTime(value: any) {
if (!value) {
return "";
}
@@ -14,7 +14,7 @@ function formatDateTime(value) {
return parsed.format(visualizationsSettings.dateTimeFormat);
}
function formatDate(value) {
function formatDate(value: any) {
if (!value) {
return "";
}
@@ -27,7 +27,7 @@ function formatDate(value) {
return parsed.format(visualizationsSettings.dateFormat);
}
export function formatColumnValue(value, columnType = null) {
export function formatColumnValue(value: any, columnType = null) {
if (moment.isMoment(value)) {
if (columnType === "date") {
return formatDate(value);

View File

@@ -12,9 +12,9 @@ const urlPattern = /(^|[\s\n]|<br\/?>)((?:https?|ftp):\/\/[\-A-Z0-9+\u0026\u2019
const hasOwnProperty = Object.prototype.hasOwnProperty;
export function createTextFormatter(highlightLinks) {
export function createTextFormatter(highlightLinks: any) {
if (highlightLinks) {
return value => {
return (value: any) => {
if (isString(value)) {
const Link = visualizationsSettings.LinkComponent;
value = value.replace(urlPattern, (unused, prefix, href) => {
@@ -29,10 +29,10 @@ export function createTextFormatter(highlightLinks) {
return toString(value);
};
}
return value => toString(value);
return (value: any) => toString(value);
}
function toMoment(value) {
function toMoment(value: any) {
if (moment.isMoment(value)) {
return value;
}
@@ -43,21 +43,21 @@ function toMoment(value) {
return moment(toString(value), [moment.ISO_8601, moment.RFC_2822]);
}
export function createDateTimeFormatter(format) {
export function createDateTimeFormatter(format: any) {
if (isString(format) && format !== "") {
return value => {
return (value: any) => {
const wrapped = toMoment(value);
return wrapped.isValid() ? wrapped.format(format) : toString(value);
};
}
return value => toString(value);
return (value: any) => toString(value);
}
export function createBooleanFormatter(values) {
export function createBooleanFormatter(values: any) {
if (isArray(values)) {
if (values.length >= 2) {
// Both `true` and `false` specified
return value => {
return (value: any) => {
if (isNil(value)) {
return "";
}
@@ -65,10 +65,10 @@ export function createBooleanFormatter(values) {
};
} else if (values.length === 1) {
// Only `true`
return value => (value ? values[0] : "");
return (value: any) => value ? values[0] : "";
}
}
return value => {
return (value: any) => {
if (isNil(value)) {
return "";
}
@@ -76,15 +76,15 @@ export function createBooleanFormatter(values) {
};
}
export function createNumberFormatter(format) {
export function createNumberFormatter(format: any) {
if (isString(format) && format !== "") {
const n = numeral(0); // cache `numeral` instance
return value => (value === null || value === "" ? "" : n.set(value).format(format));
return (value: any) => value === null || value === "" ? "" : n.set(value).format(format);
}
return value => toString(value);
return (value: any) => toString(value);
}
export function formatSimpleTemplate(str, data) {
export function formatSimpleTemplate(str: any, data: any) {
if (!isString(str)) {
return "";
}

View File

@@ -19,7 +19,7 @@ function checkItems() {
}
}
export default function observe(node, callback) {
export default function observe(node: any, callback: any) {
if (node && !items.has(node)) {
const shouldTrigger = items.size === 0;
items.set(node, { callback });

View File

@@ -1,16 +1,19 @@
import React, { useMemo } from "react";
import PropTypes from "prop-types";
import { EditorPropTypes } from "@/visualizations/prop-types";
import registeredVisualizations from "@/visualizations/registeredVisualizations";
export default function Editor({ type, options: optionsProp, data, ...otherProps }) {
/*
(ts-migrate) TODO: Migrate the remaining prop types
...EditorPropTypes
*/
type Props = {
type: string;
} & typeof EditorPropTypes;
export default function Editor({ type, options: optionsProp, data, ...otherProps }: Props) {
// @ts-expect-error ts-migrate(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
const { Editor, getOptions } = registeredVisualizations[type];
const options = useMemo(() => getOptions(optionsProp, data), [optionsProp, data]);
return <Editor options={options} data={data} {...otherProps} />;
}
Editor.propTypes = {
type: PropTypes.string.isRequired,
...EditorPropTypes,
};

View File

@@ -1,22 +1,24 @@
import { isEqual } from "lodash";
import React, { useEffect, useRef } from "react";
import PropTypes from "prop-types";
import ErrorBoundary, { ErrorMessage } from "@/components/ErrorBoundary";
import { RendererPropTypes } from "@/visualizations/prop-types";
import registeredVisualizations from "@/visualizations/registeredVisualizations";
export default function Renderer({
type,
data,
options: optionsProp,
visualizationName,
addonBefore,
addonAfter,
...otherProps
}) {
/*
(ts-migrate) TODO: Migrate the remaining prop types
...RendererPropTypes
*/
type Props = {
type: string;
addonBefore?: React.ReactNode;
addonAfter?: React.ReactNode;
} & typeof RendererPropTypes;
export default function Renderer({ type, data, options: optionsProp, visualizationName, addonBefore, addonAfter, ...otherProps }: Props) {
const lastOptions = useRef();
const errorHandlerRef = useRef();
// @ts-expect-error ts-migrate(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
const { Renderer, getOptions } = registeredVisualizations[type];
// Avoid unnecessary updates (which may be expensive or cause issues with
@@ -31,6 +33,7 @@ export default function Renderer({
useEffect(() => {
if (errorHandlerRef.current) {
// @ts-expect-error ts-migrate(2532) FIXME: Object is possibly 'undefined'.
errorHandlerRef.current.reset();
}
}, [optionsProp, data]);
@@ -38,6 +41,7 @@ export default function Renderer({
return (
<div className="visualization-renderer">
{addonBefore}
{/* @ts-expect-error ts-migrate(2769) FIXME: No overload matches this call. */}
<ErrorBoundary
ref={errorHandlerRef}
renderError={() => <ErrorMessage>Error while rendering visualization.</ErrorMessage>}>
@@ -49,10 +53,3 @@ export default function Renderer({
</div>
);
}
Renderer.propTypes = {
type: PropTypes.string.isRequired,
addonBefore: PropTypes.node,
addonAfter: PropTypes.node,
...RendererPropTypes,
};

View File

@@ -2,34 +2,39 @@ import React from "react";
import { Section, Input } from "@/components/visualizations/editor";
import { EditorPropTypes } from "@/visualizations/prop-types";
export default function Editor({ options, onOptionsChange }) {
const onXAxisLabelChanged = xAxisLabel => {
export default function Editor({
options,
onOptionsChange
}: any) {
const onXAxisLabelChanged = (xAxisLabel: any) => {
const newOptions = { ...options, xAxisLabel };
onOptionsChange(newOptions);
};
const onYAxisLabelChanged = yAxisLabel => {
const onYAxisLabelChanged = (yAxisLabel: any) => {
const newOptions = { ...options, yAxisLabel };
onOptionsChange(newOptions);
};
return (
<React.Fragment>
{/* @ts-expect-error ts-migrate(2745) FIXME: This JSX tag's 'children' prop expects type 'never... Remove this comment to see the full error message */}
<Section>
<Input
label="X Axis Label"
data-test="BoxPlot.XAxisLabel"
value={options.xAxisLabel}
onChange={event => onXAxisLabelChanged(event.target.value)}
onChange={(event: any) => onXAxisLabelChanged(event.target.value)}
/>
</Section>
{/* @ts-expect-error ts-migrate(2745) FIXME: This JSX tag's 'children' prop expects type 'never... Remove this comment to see the full error message */}
<Section>
<Input
label="Y Axis Label"
data-test="BoxPlot.YAxisLabel"
value={options.yAxisLabel}
onChange={event => onYAxisLabelChanged(event.target.value)}
onChange={(event: any) => onYAxisLabelChanged(event.target.value)}
/>
</Section>
</React.Fragment>

View File

@@ -6,8 +6,8 @@ import { RendererPropTypes } from "@/visualizations/prop-types";
import box from "./d3box";
import "./renderer.less";
function calcIqr(k) {
return d => {
function calcIqr(k: any) {
return (d: any) => {
const q1 = d.quartiles[0];
const q3 = d.quartiles[2];
const iqr = (q3 - q1) * k;
@@ -29,7 +29,10 @@ function calcIqr(k) {
};
}
function render(container, data, { xAxisLabel, yAxisLabel }) {
function render(container: any, data: any, {
xAxisLabel,
yAxisLabel
}: any) {
container = d3.select(container);
const containerBounds = container.node().getBoundingClientRect();
@@ -48,11 +51,12 @@ function render(container, data, { xAxisLabel, yAxisLabel }) {
let min = Infinity;
let max = -Infinity;
const mydata = [];
const mydata: any = [];
let value = 0;
let d = [];
const columns = map(data.columns, col => col.name);
// @ts-expect-error ts-migrate(2339) FIXME: Property 'scale' does not exist on type 'typeof im... Remove this comment to see the full error message
const xscale = d3.scale
.ordinal()
.domain(columns)
@@ -76,6 +80,7 @@ function render(container, data, { xAxisLabel, yAxisLabel }) {
});
});
// @ts-expect-error ts-migrate(2339) FIXME: Property 'scale' does not exist on type 'typeof im... Remove this comment to see the full error message
const yscale = d3.scale
.linear()
.domain([min * 0.99, max * 1.01])
@@ -83,32 +88,37 @@ function render(container, data, { xAxisLabel, yAxisLabel }) {
const chart = box()
.whiskers(calcIqr(1.5))
// @ts-expect-error ts-migrate(2339) FIXME: Property 'width' does not exist on type '{ (g: any... Remove this comment to see the full error message
.width(boxWidth - 2 * margin.inner)
.height(height)
.domain([min * 0.99, max * 1.01]);
const xAxis = d3.svg
// @ts-expect-error ts-migrate(2339) FIXME: Property 'axis' does not exist on type '(url: stri... Remove this comment to see the full error message
.axis()
.scale(xscale)
.orient("bottom");
const yAxis = d3.svg
// @ts-expect-error ts-migrate(2339) FIXME: Property 'axis' does not exist on type '(url: stri... Remove this comment to see the full error message
.axis()
.scale(yscale)
.orient("left");
const xLines = d3.svg
// @ts-expect-error ts-migrate(2339) FIXME: Property 'axis' does not exist on type '(url: stri... Remove this comment to see the full error message
.axis()
.scale(xscale)
.tickSize(height)
.orient("bottom");
const yLines = d3.svg
// @ts-expect-error ts-migrate(2339) FIXME: Property 'axis' does not exist on type '(url: stri... Remove this comment to see the full error message
.axis()
.scale(yscale)
.tickSize(width)
.orient("right");
function barOffset(i) {
function barOffset(i: any) {
return xscale(columns[i]) + (xscale(columns[1]) - margin.inner) / 2.0;
}
@@ -174,11 +184,14 @@ function render(container, data, { xAxisLabel, yAxisLabel }) {
.attr("class", "box")
.attr("width", boxWidth)
.attr("height", height)
.attr("transform", (_, i) => `translate(${barOffset(i)},${0})`)
.attr("transform", (_: any, i: any) => `translate(${barOffset(i)},${0})`)
.call(chart);
}
export default function Renderer({ data, options }) {
export default function Renderer({
data,
options
}: any) {
const [container, setContainer] = useState(null);
useEffect(() => {
@@ -191,6 +204,7 @@ export default function Renderer({ data, options }) {
}
}, [container, data, options]);
// @ts-expect-error ts-migrate(2322) FIXME: Type 'Dispatch<SetStateAction<null>>' is not assig... Remove this comment to see the full error message
return <div className="box-plot-deprecated-visualization-container" ref={setContainer} />;
}

View File

@@ -4,16 +4,17 @@ function box() {
let width = 1,
height = 1,
duration = 0,
domain = null,
domain: any = null,
value = Number,
whiskers = boxWhiskers,
quartiles = boxQuartiles,
tickFormat = null;
tickFormat: any = null;
// For each small multiple…
function box(g) {
g.each(function(d, i) {
function box(g: any) {
g.each(function(d: any, i: any) {
d = d.map(value).sort(d3.ascending);
// @ts-expect-error ts-migrate(2683) FIXME: 'this' implicitly has type 'any' because it does n... Remove this comment to see the full error message
let g = d3.select(this),
n = d.length,
min = d[0],
@@ -23,6 +24,7 @@ function box() {
const quartileData = (d.quartiles = quartiles(d));
// Compute whiskers. Must return exactly 2 elements, or null.
// @ts-expect-error ts-migrate(2683) FIXME: 'this' implicitly has type 'any' because it does n... Remove this comment to see the full error message
let whiskerIndices = whiskers && whiskers.call(this, d, i),
whiskerData = whiskerIndices && whiskerIndices.map(i => d[i]);
@@ -33,20 +35,25 @@ function box() {
: d3.range(n);
// Compute the new x-scale.
// @ts-expect-error ts-migrate(2339) FIXME: Property 'scale' does not exist on type 'typeof im... Remove this comment to see the full error message
const x1 = d3.scale
.linear()
// @ts-expect-error ts-migrate(2683) FIXME: 'this' implicitly has type 'any' because it does n... Remove this comment to see the full error message
.domain((domain && domain.call(this, d, i)) || [min, max])
.range([height, 0]);
// Retrieve the old x-scale, if this is an update.
const x0 =
// @ts-expect-error ts-migrate(2683) FIXME: 'this' implicitly has type 'any' because it does n... Remove this comment to see the full error message
this.__chart__ ||
// @ts-expect-error ts-migrate(2339) FIXME: Property 'scale' does not exist on type 'typeof im... Remove this comment to see the full error message
d3.scale
.linear()
.domain([0, Infinity])
.range(x1.range());
// Stash the new scale.
// @ts-expect-error ts-migrate(2683) FIXME: 'this' implicitly has type 'any' because it does n... Remove this comment to see the full error message
this.__chart__ = x1;
// Note: the box, median, and box tick elements are fixed in number,
@@ -84,7 +91,9 @@ function box() {
.transition()
.duration(duration)
.style("opacity", 1e-6)
// @ts-expect-error ts-migrate(2571) FIXME: Object is of type 'unknown'.
.attr("y1", d => x1(d[0]))
// @ts-expect-error ts-migrate(2571) FIXME: Object is of type 'unknown'.
.attr("y2", d => x1(d[1]))
.remove();
@@ -196,6 +205,7 @@ function box() {
.exit()
.transition()
.duration(duration)
// @ts-expect-error ts-migrate(2538) FIXME: Type 'unknown' cannot be used as an index type.
.attr("cy", i => x1(d[i]))
.style("opacity", 1e-6)
.remove();
@@ -263,52 +273,54 @@ function box() {
.style("opacity", 1e-6)
.remove();
});
// @ts-expect-error ts-migrate(2339) FIXME: Property 'flush' does not exist on type '(callback... Remove this comment to see the full error message
d3.timer.flush();
}
box.width = function(x) {
box.width = function(x: any) {
if (!arguments.length) return width;
width = x;
return box;
};
box.height = function(x) {
box.height = function(x: any) {
if (!arguments.length) return height;
height = x;
return box;
};
box.tickFormat = function(x) {
box.tickFormat = function(x: any) {
if (!arguments.length) return tickFormat;
tickFormat = x;
return box;
};
box.duration = function(x) {
box.duration = function(x: any) {
if (!arguments.length) return duration;
duration = x;
return box;
};
box.domain = function(x) {
box.domain = function(x: any) {
if (!arguments.length) return domain;
// @ts-expect-error ts-migrate(2339) FIXME: Property 'functor' does not exist on type 'typeof ... Remove this comment to see the full error message
domain = x == null ? x : d3.functor(x);
return box;
};
box.value = function(x) {
box.value = function(x: any) {
if (!arguments.length) return value;
value = x;
return box;
};
box.whiskers = function(x) {
box.whiskers = function(x: any) {
if (!arguments.length) return whiskers;
whiskers = x;
return box;
};
box.quartiles = function(x) {
box.quartiles = function(x: any) {
if (!arguments.length) return quartiles;
quartiles = x;
return box;
@@ -317,11 +329,11 @@ function box() {
return box;
}
function boxWhiskers(d) {
function boxWhiskers(d: any) {
return [0, d.length - 1];
}
function boxQuartiles(d) {
function boxQuartiles(d: any) {
return [d3.quantile(d, 0.25), d3.quantile(d, 0.5), d3.quantile(d, 0.75)];
}

View File

@@ -5,7 +5,9 @@ export default {
type: "BOXPLOT",
name: "Boxplot (Deprecated)",
isDeprecated: true,
getOptions: options => ({ ...options }),
getOptions: (options: any) => ({
...options
}),
Renderer,
Editor,

View File

@@ -1,110 +0,0 @@
import { isString, isObject, isFinite, isNumber, merge } from "lodash";
import React from "react";
import PropTypes from "prop-types";
import { useDebouncedCallback } from "use-debounce";
import * as Grid from "antd/lib/grid";
import { Section, Select, Input, InputNumber } from "@/components/visualizations/editor";
function toNumber(value) {
value = isNumber(value) ? value : parseFloat(value);
return isFinite(value) ? value : null;
}
export default function AxisSettings({ id, options, features, onChange }) {
function optionsChanged(newOptions) {
onChange(merge({}, options, newOptions));
}
const [handleNameChange] = useDebouncedCallback(text => {
const title = isString(text) && text !== "" ? { text } : null;
optionsChanged({ title });
}, 200);
const [handleMinMaxChange] = useDebouncedCallback(opts => optionsChanged(opts), 200);
return (
<React.Fragment>
<Section>
<Select
label="Scale"
data-test={`Chart.${id}.Type`}
defaultValue={options.type}
onChange={type => optionsChanged({ type })}>
{features.autoDetectType && (
<Select.Option value="-" data-test={`Chart.${id}.Type.Auto`}>
Auto Detect
</Select.Option>
)}
<Select.Option value="datetime" data-test={`Chart.${id}.Type.DateTime`}>
Datetime
</Select.Option>
<Select.Option value="linear" data-test={`Chart.${id}.Type.Linear`}>
Linear
</Select.Option>
<Select.Option value="logarithmic" data-test={`Chart.${id}.Type.Logarithmic`}>
Logarithmic
</Select.Option>
<Select.Option value="category" data-test={`Chart.${id}.Type.Category`}>
Category
</Select.Option>
</Select>
</Section>
<Section>
<Input
label="Name"
data-test={`Chart.${id}.Name`}
defaultValue={isObject(options.title) ? options.title.text : null}
onChange={event => handleNameChange(event.target.value)}
/>
</Section>
{features.range && (
<Section>
<Grid.Row gutter={15} type="flex" align="middle">
<Grid.Col span={12}>
<InputNumber
label="Min Value"
placeholder="Auto"
data-test={`Chart.${id}.RangeMin`}
defaultValue={toNumber(options.rangeMin)}
onChange={value => handleMinMaxChange({ rangeMin: toNumber(value) })}
/>
</Grid.Col>
<Grid.Col span={12}>
<InputNumber
label="Max Value"
placeholder="Auto"
data-test={`Chart.${id}.RangeMax`}
defaultValue={toNumber(options.rangeMax)}
onChange={value => handleMinMaxChange({ rangeMax: toNumber(value) })}
/>
</Grid.Col>
</Grid.Row>
</Section>
)}
</React.Fragment>
);
}
AxisSettings.propTypes = {
id: PropTypes.string.isRequired,
options: PropTypes.shape({
type: PropTypes.string.isRequired,
title: PropTypes.shape({
text: PropTypes.string,
}),
rangeMin: PropTypes.number,
rangeMax: PropTypes.number,
}).isRequired,
features: PropTypes.shape({
autoDetectType: PropTypes.bool,
range: PropTypes.bool,
}),
onChange: PropTypes.func,
};
AxisSettings.defaultProps = {
features: {},
onChange: () => {},
};

View File

@@ -0,0 +1,125 @@
import { isString, isObject, isFinite, isNumber, merge } from "lodash";
import React from "react";
import { useDebouncedCallback } from "use-debounce";
import * as Grid from "antd/lib/grid";
import { Section, Select, Input, InputNumber } from "@/components/visualizations/editor";
function toNumber(value: any) {
value = isNumber(value) ? value : parseFloat(value);
return isFinite(value) ? value : null;
}
type OwnProps = {
id: string;
options: {
type: string;
title?: {
text?: string;
};
rangeMin?: number;
rangeMax?: number;
};
features?: {
autoDetectType?: boolean;
range?: boolean;
};
onChange?: (...args: any[]) => any;
};
type Props = OwnProps & typeof AxisSettings.defaultProps;
export default function AxisSettings({ id, options, features, onChange }: Props) {
function optionsChanged(newOptions: any) {
onChange(merge({}, options, newOptions));
}
const [handleNameChange] = useDebouncedCallback(text => {
const title = isString(text) && text !== "" ? { text } : null;
optionsChanged({ title });
}, 200);
const [handleMinMaxChange] = useDebouncedCallback(opts => optionsChanged(opts), 200);
return (
<React.Fragment>
{/* @ts-expect-error ts-migrate(2745) FIXME: This JSX tag's 'children' prop expects type 'never... Remove this comment to see the full error message */}
<Section>
<Select
label="Scale"
data-test={`Chart.${id}.Type`}
defaultValue={options.type}
onChange={(type: any) => optionsChanged({ type })}>
{features.autoDetectType && (
// @ts-expect-error ts-migrate(2339) FIXME: Property 'Option' does not exist on type '({ class... Remove this comment to see the full error message
<Select.Option value="-" data-test={`Chart.${id}.Type.Auto`}>
Auto Detect
{/* @ts-expect-error ts-migrate(2339) FIXME: Property 'Option' does not exist on type '({ class... Remove this comment to see the full error message */}
</Select.Option>
)}
{/* @ts-expect-error ts-migrate(2339) FIXME: Property 'Option' does not exist on type '({ class... Remove this comment to see the full error message */}
<Select.Option value="datetime" data-test={`Chart.${id}.Type.DateTime`}>
Datetime
{/* @ts-expect-error ts-migrate(2339) FIXME: Property 'Option' does not exist on type '({ class... Remove this comment to see the full error message */}
</Select.Option>
{/* @ts-expect-error ts-migrate(2339) FIXME: Property 'Option' does not exist on type '({ class... Remove this comment to see the full error message */}
<Select.Option value="linear" data-test={`Chart.${id}.Type.Linear`}>
Linear
{/* @ts-expect-error ts-migrate(2339) FIXME: Property 'Option' does not exist on type '({ class... Remove this comment to see the full error message */}
</Select.Option>
{/* @ts-expect-error ts-migrate(2339) FIXME: Property 'Option' does not exist on type '({ class... Remove this comment to see the full error message */}
<Select.Option value="logarithmic" data-test={`Chart.${id}.Type.Logarithmic`}>
Logarithmic
{/* @ts-expect-error ts-migrate(2339) FIXME: Property 'Option' does not exist on type '({ class... Remove this comment to see the full error message */}
</Select.Option>
{/* @ts-expect-error ts-migrate(2339) FIXME: Property 'Option' does not exist on type '({ class... Remove this comment to see the full error message */}
<Select.Option value="category" data-test={`Chart.${id}.Type.Category`}>
Category
{/* @ts-expect-error ts-migrate(2339) FIXME: Property 'Option' does not exist on type '({ class... Remove this comment to see the full error message */}
</Select.Option>
</Select>
</Section>
{/* @ts-expect-error ts-migrate(2745) FIXME: This JSX tag's 'children' prop expects type 'never... Remove this comment to see the full error message */}
<Section>
<Input
label="Name"
data-test={`Chart.${id}.Name`}
defaultValue={isObject(options.title) ? options.title.text : null}
onChange={(event: any) => handleNameChange(event.target.value)}
/>
</Section>
{features.range && (
// @ts-expect-error ts-migrate(2745) FIXME: This JSX tag's 'children' prop expects type 'never... Remove this comment to see the full error message
<Section>
{/* @ts-expect-error ts-migrate(2322) FIXME: Type '{ children: Element[]; gutter: number; type:... Remove this comment to see the full error message */}
<Grid.Row gutter={15} type="flex" align="middle">
<Grid.Col span={12}>
<InputNumber
label="Min Value"
placeholder="Auto"
data-test={`Chart.${id}.RangeMin`}
defaultValue={toNumber(options.rangeMin)}
onChange={(value: any) => handleMinMaxChange({ rangeMin: toNumber(value) })}
/>
</Grid.Col>
<Grid.Col span={12}>
<InputNumber
label="Max Value"
placeholder="Auto"
data-test={`Chart.${id}.RangeMax`}
defaultValue={toNumber(options.rangeMax)}
onChange={(value: any) => handleMinMaxChange({ rangeMax: toNumber(value) })}
/>
</Grid.Col>
</Grid.Row>
</Section>
)}
</React.Fragment>
);
}
AxisSettings.defaultProps = {
features: {},
onChange: () => {},
};

View File

@@ -1,6 +1,5 @@
import { filter, includes, map } from "lodash";
import React, { useMemo } from "react";
import PropTypes from "prop-types";
import { Select } from "@/components/visualizations/editor";
import { visualizationsSettings } from "@/visualizations/visualizationsSettings";
@@ -15,7 +14,13 @@ const allChartTypes = [
{ type: "box", name: "Box", icon: "square-o" },
];
export default function ChartTypeSelect({ hiddenChartTypes, ...props }) {
type OwnProps = {
hiddenChartTypes?: any[]; // TODO: PropTypes.oneOf(map(allChartTypes, "type"))
};
type Props = OwnProps & typeof ChartTypeSelect.defaultProps;
export default function ChartTypeSelect({ hiddenChartTypes, ...props }: Props) {
const chartTypes = useMemo(() => {
const result = [...allChartTypes];
@@ -33,19 +38,17 @@ export default function ChartTypeSelect({ hiddenChartTypes, ...props }) {
return (
<Select {...props}>
{map(chartTypes, ({ type, name, icon }) => (
// @ts-expect-error ts-migrate(2339) FIXME: Property 'Option' does not exist on type '({ class... Remove this comment to see the full error message
<Select.Option key={type} value={type} data-test={`Chart.ChartType.${type}`}>
<i className={`fa fa-${icon}`} style={{ marginRight: 5 }} />
{name}
{/* @ts-expect-error ts-migrate(2339) FIXME: Property 'Option' does not exist on type '({ class... Remove this comment to see the full error message */}
</Select.Option>
))}
</Select>
);
}
ChartTypeSelect.propTypes = {
hiddenChartTypes: PropTypes.arrayOf(PropTypes.oneOf(map(allChartTypes, "type"))),
};
ChartTypeSelect.defaultProps = {
hiddenChartTypes: [],
};

View File

@@ -5,11 +5,11 @@ import enzyme from "enzyme";
import getOptions from "../getOptions";
import ColorsSettings from "./ColorsSettings";
function findByTestID(wrapper, testId) {
function findByTestID(wrapper: any, testId: any) {
return wrapper.find(`[data-test="${testId}"]`);
}
function mount(options, done) {
function mount(options: any, done: any) {
options = getOptions(options);
return enzyme.mount(
<ColorsSettings
@@ -22,7 +22,7 @@ function mount(options, done) {
rows: [{ a: "v", b: 3.14 }],
}}
options={options}
onOptionsChange={changedOptions => {
onOptionsChange={(changedOptions: any) => {
expect(changedOptions).toMatchSnapshot();
done();
}}

View File

@@ -10,7 +10,11 @@ const components = {
heatmap: HeatmapColorsSettings,
};
export default function ColorsSettings({ options, ...props }) {
export default function ColorsSettings({
options,
...props
}: any) {
// @ts-expect-error ts-migrate(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
const Component = components[options.globalSeriesType] || DefaultColorsSettings;
return <Component options={options} {...props} />;
}

View File

@@ -1,6 +1,5 @@
import { isString, map, uniq, flatten, filter, sortBy, keys } from "lodash";
import React from "react";
import PropTypes from "prop-types";
import { Section, Select } from "@/components/visualizations/editor";
const MappingTypes = {
@@ -18,13 +17,23 @@ const SwappedMappingTypes = {
y: { label: "X Columns", multiple: true },
};
export default function ColumnMappingSelect({ value, availableColumns, type, onChange, areAxesSwapped }) {
type OwnProps = {
value?: string | string[];
availableColumns?: string[];
type?: any; // TODO: PropTypes.oneOf(keys(MappingTypes))
onChange?: (...args: any[]) => any;
};
type Props = OwnProps & typeof ColumnMappingSelect.defaultProps;
export default function ColumnMappingSelect({ value, availableColumns, type, onChange, areAxesSwapped }: Props) {
const options = sortBy(filter(uniq(flatten([availableColumns, value])), v => isString(v) && v !== ""));
// this swaps the ui, as the data will be swapped on render
const { label, multiple } = !areAxesSwapped ? MappingTypes[type] : SwappedMappingTypes[type];
return (
// @ts-expect-error ts-migrate(2745) FIXME: This JSX tag's 'children' prop expects type 'never... Remove this comment to see the full error message
<Section>
<Select
label={label}
@@ -34,10 +43,13 @@ export default function ColumnMappingSelect({ value, availableColumns, type, onC
showSearch
placeholder={multiple ? "Choose columns..." : "Choose column..."}
value={value || undefined}
onChange={column => onChange(column || null, type)}>
// @ts-expect-error ts-migrate(2349) FIXME: This expression is not callable.
onChange={(column: any) => onChange(column || null, type)}>
{map(options, c => (
// @ts-expect-error ts-migrate(2339) FIXME: Property 'Option' does not exist on type '({ class... Remove this comment to see the full error message
<Select.Option key={c} value={c} data-test={`Chart.ColumnMapping.${type}.${c}`}>
{c}
{/* @ts-expect-error ts-migrate(2339) FIXME: Property 'Option' does not exist on type '({ class... Remove this comment to see the full error message */}
</Select.Option>
))}
</Select>
@@ -45,13 +57,6 @@ export default function ColumnMappingSelect({ value, availableColumns, type, onC
);
}
ColumnMappingSelect.propTypes = {
value: PropTypes.oneOfType([PropTypes.string, PropTypes.arrayOf(PropTypes.string)]),
availableColumns: PropTypes.arrayOf(PropTypes.string),
type: PropTypes.oneOf(keys(MappingTypes)),
onChange: PropTypes.func,
};
ColumnMappingSelect.defaultProps = {
value: null,
availableColumns: [],

View File

@@ -1,48 +0,0 @@
import { isNil, trimStart } from "lodash";
import React from "react";
import { Section, Switch, TextArea } from "@/components/visualizations/editor";
import { EditorPropTypes } from "@/visualizations/prop-types";
const defaultCustomCode = trimStart(`
// Available variables are x, ys, element, and Plotly
// Type console.log(x, ys); for more info about x and ys
// To plot your graph call Plotly.plot(element, ...)
// Plotly examples and docs: https://plot.ly/javascript/
`);
export default function CustomChartSettings({ options, onOptionsChange }) {
return (
<React.Fragment>
<Section>
<TextArea
label="Custom code"
data-test="Chart.Custom.Code"
rows="10"
defaultValue={isNil(options.customCode) ? defaultCustomCode : options.customCode}
onChange={event => onOptionsChange({ customCode: event.target.value })}
/>
</Section>
<Section>
<Switch
data-test="Chart.Custom.EnableConsoleLogs"
defaultChecked={options.enableConsoleLogs}
onChange={enableConsoleLogs => onOptionsChange({ enableConsoleLogs })}>
Show errors in the console
</Switch>
</Section>
<Section>
<Switch
id="chart-editor-auto-update-custom-chart"
data-test="Chart.Custom.AutoUpdate"
defaultChecked={options.autoRedraw}
onChange={autoRedraw => onOptionsChange({ autoRedraw })}>
Auto update graph
</Switch>
</Section>
</React.Fragment>
);
}
CustomChartSettings.propTypes = EditorPropTypes;

View File

@@ -0,0 +1,63 @@
import { isNil, trimStart } from "lodash";
import React from "react";
import { Section, Switch, TextArea } from "@/components/visualizations/editor";
import { EditorPropTypes } from "@/visualizations/prop-types";
const defaultCustomCode = trimStart(`
// Available variables are x, ys, element, and Plotly
// Type console.log(x, ys); for more info about x and ys
// To plot your graph call Plotly.plot(element, ...)
// Plotly examples and docs: https://plot.ly/javascript/
`);
export default function CustomChartSettings({
options,
onOptionsChange
}: any) {
return (
<React.Fragment>
{/* @ts-expect-error ts-migrate(2745) FIXME: This JSX tag's 'children' prop expects type 'never... Remove this comment to see the full error message */}
<Section>
<TextArea
label="Custom code"
data-test="Chart.Custom.Code"
rows="10"
defaultValue={isNil(options.customCode) ? defaultCustomCode : options.customCode}
onChange={(event: any) => onOptionsChange({ customCode: event.target.value })}
/>
</Section>
{/* @ts-expect-error ts-migrate(2745) FIXME: This JSX tag's 'children' prop expects type 'never... Remove this comment to see the full error message */}
<Section>
{/* @ts-expect-error ts-migrate(2745) FIXME: This JSX tag's 'children' prop expects type 'never... Remove this comment to see the full error message */}
<Switch
// @ts-expect-error ts-migrate(2322) FIXME: Type 'string' is not assignable to type 'never'.
data-test="Chart.Custom.EnableConsoleLogs"
// @ts-expect-error ts-migrate(2322) FIXME: Type 'any' is not assignable to type 'never'.
defaultChecked={options.enableConsoleLogs}
// @ts-expect-error ts-migrate(2322) FIXME: Type '(enableConsoleLogs: any) => any' is not assi... Remove this comment to see the full error message
onChange={(enableConsoleLogs: any) => onOptionsChange({ enableConsoleLogs })}>
Show errors in the console
</Switch>
</Section>
{/* @ts-expect-error ts-migrate(2745) FIXME: This JSX tag's 'children' prop expects type 'never... Remove this comment to see the full error message */}
<Section>
{/* @ts-expect-error ts-migrate(2745) FIXME: This JSX tag's 'children' prop expects type 'never... Remove this comment to see the full error message */}
<Switch
// @ts-expect-error ts-migrate(2322) FIXME: Type 'string' is not assignable to type 'never'.
id="chart-editor-auto-update-custom-chart"
// @ts-expect-error ts-migrate(2322) FIXME: Type 'string' is not assignable to type 'never'.
data-test="Chart.Custom.AutoUpdate"
// @ts-expect-error ts-migrate(2322) FIXME: Type 'any' is not assignable to type 'never'.
defaultChecked={options.autoRedraw}
// @ts-expect-error ts-migrate(2322) FIXME: Type '(autoRedraw: any) => any' is not assignable ... Remove this comment to see the full error message
onChange={(autoRedraw: any) => onOptionsChange({ autoRedraw })}>
Auto update graph
</Switch>
</Section>
</React.Fragment>
);
}
CustomChartSettings.propTypes = EditorPropTypes;

View File

@@ -4,11 +4,11 @@ import enzyme from "enzyme";
import getOptions from "../getOptions";
import DataLabelsSettings from "./DataLabelsSettings";
function findByTestID(wrapper, testId) {
function findByTestID(wrapper: any, testId: any) {
return wrapper.find(`[data-test="${testId}"]`);
}
function mount(options, done) {
function mount(options: any, done: any) {
options = getOptions(options);
return enzyme.mount(
<DataLabelsSettings

View File

@@ -4,7 +4,10 @@ import { useDebouncedCallback } from "use-debounce";
import { Section, Input, Checkbox, ContextHelp } from "@/components/visualizations/editor";
import { EditorPropTypes } from "@/visualizations/prop-types";
export default function DataLabelsSettings({ options, onOptionsChange }) {
export default function DataLabelsSettings({
options,
onOptionsChange
}: any) {
const isShowDataLabelsAvailable = includes(
["line", "area", "column", "scatter", "pie", "heatmap"],
options.globalSeriesType
@@ -15,6 +18,7 @@ export default function DataLabelsSettings({ options, onOptionsChange }) {
return (
<React.Fragment>
{isShowDataLabelsAvailable && (
// @ts-expect-error ts-migrate(2745) FIXME: This JSX tag's 'children' prop expects type 'never... Remove this comment to see the full error message
<Section>
<Checkbox
data-test="Chart.DataLabels.ShowDataLabels"
@@ -25,6 +29,7 @@ export default function DataLabelsSettings({ options, onOptionsChange }) {
</Section>
)}
{/* @ts-expect-error ts-migrate(2745) FIXME: This JSX tag's 'children' prop expects type 'never... Remove this comment to see the full error message */}
<Section>
<Input
label={
@@ -35,10 +40,11 @@ export default function DataLabelsSettings({ options, onOptionsChange }) {
}
data-test="Chart.DataLabels.NumberFormat"
defaultValue={options.numberFormat}
onChange={e => debouncedOnOptionsChange({ numberFormat: e.target.value })}
onChange={(e: any) => debouncedOnOptionsChange({ numberFormat: e.target.value })}
/>
</Section>
{/* @ts-expect-error ts-migrate(2745) FIXME: This JSX tag's 'children' prop expects type 'never... Remove this comment to see the full error message */}
<Section>
<Input
label={
@@ -49,10 +55,11 @@ export default function DataLabelsSettings({ options, onOptionsChange }) {
}
data-test="Chart.DataLabels.PercentFormat"
defaultValue={options.percentFormat}
onChange={e => debouncedOnOptionsChange({ percentFormat: e.target.value })}
onChange={(e: any) => debouncedOnOptionsChange({ percentFormat: e.target.value })}
/>
</Section>
{/* @ts-expect-error ts-migrate(2745) FIXME: This JSX tag's 'children' prop expects type 'never... Remove this comment to see the full error message */}
<Section>
<Input
label={
@@ -63,15 +70,17 @@ export default function DataLabelsSettings({ options, onOptionsChange }) {
}
data-test="Chart.DataLabels.DateTimeFormat"
defaultValue={options.dateTimeFormat}
onChange={e => debouncedOnOptionsChange({ dateTimeFormat: e.target.value })}
onChange={(e: any) => debouncedOnOptionsChange({ dateTimeFormat: e.target.value })}
/>
</Section>
{/* @ts-expect-error ts-migrate(2745) FIXME: This JSX tag's 'children' prop expects type 'never... Remove this comment to see the full error message */}
<Section>
<Input
label={
<React.Fragment>
Data Labels
{/* @ts-expect-error ts-migrate(2746) FIXME: This JSX tag's 'children' prop expects a single ch... Remove this comment to see the full error message */}
<ContextHelp placement="topRight" arrowPointAtCenter>
<div style={{ paddingBottom: 5 }}>Use special names to access additional properties:</div>
<div>
@@ -104,7 +113,7 @@ export default function DataLabelsSettings({ options, onOptionsChange }) {
data-test="Chart.DataLabels.TextFormat"
placeholder="(auto)"
defaultValue={options.textFormat}
onChange={e => debouncedOnOptionsChange({ textFormat: e.target.value })}
onChange={(e: any) => debouncedOnOptionsChange({ textFormat: e.target.value })}
/>
</Section>
</React.Fragment>

View File

@@ -6,7 +6,11 @@ import { EditorPropTypes } from "@/visualizations/prop-types";
import ColorPalette from "@/visualizations/ColorPalette";
import getChartData from "../getChartData";
export default function DefaultColorsSettings({ options, data, onOptionsChange }) {
export default function DefaultColorsSettings({
options,
data,
onOptionsChange
}: any) {
const colors = useMemo(
() => ({
Automatic: null,
@@ -46,20 +50,28 @@ export default function DefaultColorsSettings({ options, data, onOptionsChange }
title: "Color",
dataIndex: "color",
width: "1%",
render: (unused, item) => (
render: (unused: any, item: any) => (
<ColorPicker
// @ts-expect-error ts-migrate(2322) FIXME: Type 'string' is not assignable to type 'never'.
data-test={`Chart.Series.${item.key}.Color`}
// @ts-expect-error ts-migrate(2322) FIXME: Type 'boolean' is not assignable to type 'never'.
interactive
// @ts-expect-error ts-migrate(2322) FIXME: Type '{ "Indian Red": string; "Green 2": string; "... Remove this comment to see the full error message
presetColors={colors}
// @ts-expect-error ts-migrate(2322) FIXME: Type 'string' is not assignable to type 'never'.
placement="topRight"
// @ts-expect-error ts-migrate(2322) FIXME: Type 'any' is not assignable to type 'never'.
color={item.color}
onChange={value => updateSeriesOption(item.key, "color", value)}
// @ts-expect-error ts-migrate(2322) FIXME: Type '(value: any) => void' is not assignable to t... Remove this comment to see the full error message
onChange={(value: any) => updateSeriesOption(item.key, "color", value)}
// @ts-expect-error ts-migrate(2322) FIXME: Type 'Element' is not assignable to type 'never'.
addonAfter={<ColorPicker.Label color={item.color} presetColors={colors} />}
/>
),
},
];
// @ts-expect-error ts-migrate(2322) FIXME: Type 'boolean[]' is not assignable to type 'object... Remove this comment to see the full error message
return <Table showHeader={false} dataSource={series} columns={columns} pagination={false} />;
}

View File

@@ -4,15 +4,15 @@ import enzyme from "enzyme";
import getOptions from "../getOptions";
import GeneralSettings from "./GeneralSettings";
function findByTestID(wrapper, testId) {
function findByTestID(wrapper: any, testId: any) {
return wrapper.find(`[data-test="${testId}"]`);
}
function elementExists(wrapper, testId) {
function elementExists(wrapper: any, testId: any) {
return findByTestID(wrapper, testId).length > 0;
}
function mount(options, done) {
function mount(options: any, done: any) {
options = getOptions(options);
return enzyme.mount(
<GeneralSettings
@@ -149,6 +149,7 @@ describe("Visualizations -> Chart -> Editor -> General Settings", () => {
describe("Column mappings should be available", () => {
test("for bubble", () => {
// @ts-expect-error ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
const el = mount({
globalSeriesType: "column",
seriesOptions: {
@@ -164,6 +165,7 @@ describe("Visualizations -> Chart -> Editor -> General Settings", () => {
});
test("for heatmap", () => {
// @ts-expect-error ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
const el = mount({
globalSeriesType: "heatmap",
seriesOptions: {
@@ -179,6 +181,7 @@ describe("Visualizations -> Chart -> Editor -> General Settings", () => {
});
test("for all types except of bubble, heatmap and custom", () => {
// @ts-expect-error ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
const el = mount({
globalSeriesType: "column",
seriesOptions: {

View File

@@ -7,7 +7,7 @@ import { EditorPropTypes } from "@/visualizations/prop-types";
import ChartTypeSelect from "./ChartTypeSelect";
import ColumnMappingSelect from "./ColumnMappingSelect";
function getAvailableColumnMappingTypes(options) {
function getAvailableColumnMappingTypes(options: any) {
const result = ["x", "y"];
if (!includes(["custom", "heatmap"], options.globalSeriesType)) {
@@ -29,22 +29,26 @@ function getAvailableColumnMappingTypes(options) {
return result;
}
function getMappedColumns(options, availableColumns) {
function getMappedColumns(options: any, availableColumns: any) {
const mappedColumns = {};
const availableTypes = getAvailableColumnMappingTypes(options);
each(availableTypes, type => {
// @ts-expect-error ts-migrate(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
mappedColumns[type] = ColumnMappingSelect.MappingTypes[type].multiple ? [] : null;
});
availableColumns = map(availableColumns, c => c.name);
const usedColumns = [];
const usedColumns: any = [];
each(options.columnMapping, (type, column) => {
if (includes(availableColumns, column) && includes(availableTypes, type)) {
// @ts-expect-error ts-migrate(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
const { multiple } = ColumnMappingSelect.MappingTypes[type];
if (multiple) {
// @ts-expect-error ts-migrate(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
mappedColumns[type].push(column);
} else {
// @ts-expect-error ts-migrate(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
mappedColumns[type] = column;
}
usedColumns.push(column);
@@ -57,15 +61,17 @@ function getMappedColumns(options, availableColumns) {
};
}
function mappedColumnsToColumnMappings(mappedColumns) {
function mappedColumnsToColumnMappings(mappedColumns: any) {
const result = {};
each(mappedColumns, (value, type) => {
if (isArray(value)) {
each(value, v => {
// @ts-expect-error ts-migrate(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
result[v] = type;
});
} else {
if (value) {
// @ts-expect-error ts-migrate(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
result[value] = type;
}
}
@@ -73,13 +79,17 @@ function mappedColumnsToColumnMappings(mappedColumns) {
return result;
}
export default function GeneralSettings({ options, data, onOptionsChange }) {
export default function GeneralSettings({
options,
data,
onOptionsChange
}: any) {
const { mappedColumns, unusedColumns } = useMemo(() => getMappedColumns(options, data.columns), [
options,
data.columns,
]);
function handleGlobalSeriesTypeChange(globalSeriesType) {
function handleGlobalSeriesTypeChange(globalSeriesType: any) {
onOptionsChange({
globalSeriesType,
showDataLabels: globalSeriesType === "pie",
@@ -91,7 +101,7 @@ export default function GeneralSettings({ options, data, onOptionsChange }) {
});
}
function handleColumnMappingChange(column, type) {
function handleColumnMappingChange(column: any, type: any) {
const columnMapping = mappedColumnsToColumnMappings({
...mappedColumns,
[type]: column,
@@ -99,7 +109,7 @@ export default function GeneralSettings({ options, data, onOptionsChange }) {
onOptionsChange({ columnMapping }, UpdateOptionsStrategy.shallowMerge);
}
function handleLegendPlacementChange(value) {
function handleLegendPlacementChange(value: any) {
if (value === "hidden") {
onOptionsChange({ legend: { enabled: false } });
} else {
@@ -118,8 +128,10 @@ export default function GeneralSettings({ options, data, onOptionsChange }) {
return (
<React.Fragment>
{/* @ts-expect-error ts-migrate(2745) FIXME: This JSX tag's 'children' prop expects type 'never... Remove this comment to see the full error message */}
<Section>
<ChartTypeSelect
// @ts-expect-error ts-migrate(2322) FIXME: Type '{ label: string; "data-test": string; defaul... Remove this comment to see the full error message
label="Chart Type"
data-test="Chart.GlobalSeriesType"
defaultValue={options.globalSeriesType}
@@ -128,6 +140,7 @@ export default function GeneralSettings({ options, data, onOptionsChange }) {
</Section>
{includes(["column", "line", "box"], options.globalSeriesType) && (
// @ts-expect-error ts-migrate(2745) FIXME: This JSX tag's 'children' prop expects type 'never... Remove this comment to see the full error message
<Section>
<Checkbox
data-test="Chart.SwappedAxes"
@@ -141,37 +154,48 @@ export default function GeneralSettings({ options, data, onOptionsChange }) {
{map(mappedColumns, (value, type) => (
<ColumnMappingSelect
// @ts-expect-error ts-migrate(2322) FIXME: Type 'string' is not assignable to type 'never'.
key={type}
// @ts-expect-error ts-migrate(2322) FIXME: Type 'string' is not assignable to type 'never'.
type={type}
value={value}
// @ts-expect-error ts-migrate(2322) FIXME: Type 'any' is not assignable to type 'never'.
areAxesSwapped={options.swappedAxes}
// @ts-expect-error ts-migrate(2322) FIXME: Type 'unknown[]' is not assignable to type 'never'... Remove this comment to see the full error message
availableColumns={unusedColumns}
// @ts-expect-error ts-migrate(2322) FIXME: Type '(column: any, type: any) => void' is not ass... Remove this comment to see the full error message
onChange={handleColumnMappingChange}
/>
))}
{includes(["bubble"], options.globalSeriesType) && (
<React.Fragment>
{/* @ts-expect-error ts-migrate(2745) FIXME: This JSX tag's 'children' prop expects type 'never... Remove this comment to see the full error message */}
<Section>
<InputNumber
label="Bubble Size Coefficient"
data-test="Chart.BubbleCoefficient"
defaultValue={options.coefficient}
onChange={value => onOptionsChange({ coefficient: toNumber(value) })}
onChange={(value: any) => onOptionsChange({ coefficient: toNumber(value) })}
/>
</Section>
{/* @ts-expect-error ts-migrate(2745) FIXME: This JSX tag's 'children' prop expects type 'never... Remove this comment to see the full error message */}
<Section>
<Select
label="Bubble Size Proportional To"
data-test="Chart.SizeMode"
defaultValue={options.sizemode}
onChange={mode => onOptionsChange({ sizemode: mode })}>
onChange={(mode: any) => onOptionsChange({ sizemode: mode })}>
{/* @ts-expect-error ts-migrate(2339) FIXME: Property 'Option' does not exist on type '({ class... Remove this comment to see the full error message */}
<Select.Option value="area" data-test="Chart.SizeMode.Area">
Area
{/* @ts-expect-error ts-migrate(2339) FIXME: Property 'Option' does not exist on type '({ class... Remove this comment to see the full error message */}
</Select.Option>
{/* @ts-expect-error ts-migrate(2339) FIXME: Property 'Option' does not exist on type '({ class... Remove this comment to see the full error message */}
<Select.Option value="diameter" data-test="Chart.SizeMode.Diameter">
Diameter
{/* @ts-expect-error ts-migrate(2339) FIXME: Property 'Option' does not exist on type '({ class... Remove this comment to see the full error message */}
</Select.Option>
</Select>
</Section>
@@ -179,17 +203,22 @@ export default function GeneralSettings({ options, data, onOptionsChange }) {
)}
{includes(["pie"], options.globalSeriesType) && (
// @ts-expect-error ts-migrate(2745) FIXME: This JSX tag's 'children' prop expects type 'never... Remove this comment to see the full error message
<Section>
<Select
label="Direction"
data-test="Chart.PieDirection"
defaultValue={options.direction.type}
onChange={type => onOptionsChange({ direction: { type } })}>
onChange={(type: any) => onOptionsChange({ direction: { type } })}>
{/* @ts-expect-error ts-migrate(2339) FIXME: Property 'Option' does not exist on type '({ class... Remove this comment to see the full error message */}
<Select.Option value="counterclockwise" data-test="Chart.PieDirection.Counterclockwise">
Counterclockwise
{/* @ts-expect-error ts-migrate(2339) FIXME: Property 'Option' does not exist on type '({ class... Remove this comment to see the full error message */}
</Select.Option>
{/* @ts-expect-error ts-migrate(2339) FIXME: Property 'Option' does not exist on type '({ class... Remove this comment to see the full error message */}
<Select.Option value="clockwise" data-test="Chart.PieDirection.Clockwise">
Clockwise
{/* @ts-expect-error ts-migrate(2339) FIXME: Property 'Option' does not exist on type '({ class... Remove this comment to see the full error message */}
</Select.Option>
</Select>
</Section>
@@ -197,36 +226,48 @@ export default function GeneralSettings({ options, data, onOptionsChange }) {
{!includes(["custom", "heatmap"], options.globalSeriesType) && (
<React.Fragment>
{/* @ts-expect-error ts-migrate(2745) FIXME: This JSX tag's 'children' prop expects type 'never... Remove this comment to see the full error message */}
<Section>
<Select
label="Legend Placement"
data-test="Chart.LegendPlacement"
value={options.legend.enabled ? options.legend.placement : "hidden"}
onChange={handleLegendPlacementChange}>
{/* @ts-expect-error ts-migrate(2339) FIXME: Property 'Option' does not exist on type '({ class... Remove this comment to see the full error message */}
<Select.Option value="hidden" data-test="Chart.LegendPlacement.HideLegend">
Hide legend
{/* @ts-expect-error ts-migrate(2339) FIXME: Property 'Option' does not exist on type '({ class... Remove this comment to see the full error message */}
</Select.Option>
{/* @ts-expect-error ts-migrate(2339) FIXME: Property 'Option' does not exist on type '({ class... Remove this comment to see the full error message */}
<Select.Option value="auto" data-test="Chart.LegendPlacement.Auto">
Right
{/* @ts-expect-error ts-migrate(2339) FIXME: Property 'Option' does not exist on type '({ class... Remove this comment to see the full error message */}
</Select.Option>
{/* @ts-expect-error ts-migrate(2339) FIXME: Property 'Option' does not exist on type '({ class... Remove this comment to see the full error message */}
<Select.Option value="below" data-test="Chart.LegendPlacement.Below">
Bottom
{/* @ts-expect-error ts-migrate(2339) FIXME: Property 'Option' does not exist on type '({ class... Remove this comment to see the full error message */}
</Select.Option>
</Select>
</Section>
{options.legend.enabled && (
// @ts-expect-error ts-migrate(2745) FIXME: This JSX tag's 'children' prop expects type 'never... Remove this comment to see the full error message
<Section>
<Select
label="Legend Items Order"
data-test="Chart.LegendItemsOrder"
value={options.legend.traceorder}
onChange={traceorder => onOptionsChange({ legend: { traceorder } })}>
onChange={(traceorder: any) => onOptionsChange({ legend: { traceorder } })}>
{/* @ts-expect-error ts-migrate(2339) FIXME: Property 'Option' does not exist on type '({ class... Remove this comment to see the full error message */}
<Select.Option value="normal" data-test="Chart.LegendItemsOrder.Normal">
Normal
{/* @ts-expect-error ts-migrate(2339) FIXME: Property 'Option' does not exist on type '({ class... Remove this comment to see the full error message */}
</Select.Option>
{/* @ts-expect-error ts-migrate(2339) FIXME: Property 'Option' does not exist on type '({ class... Remove this comment to see the full error message */}
<Select.Option value="reversed" data-test="Chart.LegendItemsOrder.Reversed">
Reversed
{/* @ts-expect-error ts-migrate(2339) FIXME: Property 'Option' does not exist on type '({ class... Remove this comment to see the full error message */}
</Select.Option>
</Select>
</Section>
@@ -235,6 +276,7 @@ export default function GeneralSettings({ options, data, onOptionsChange }) {
)}
{includes(["box"], options.globalSeriesType) && (
// @ts-expect-error ts-migrate(2745) FIXME: This JSX tag's 'children' prop expects type 'never... Remove this comment to see the full error message
<Section>
<Checkbox
data-test="Chart.ShowPoints"
@@ -246,24 +288,30 @@ export default function GeneralSettings({ options, data, onOptionsChange }) {
)}
{!includes(["custom", "heatmap"], options.globalSeriesType) && (
// @ts-expect-error ts-migrate(2745) FIXME: This JSX tag's 'children' prop expects type 'never... Remove this comment to see the full error message
<Section>
<Select
label="Stacking"
data-test="Chart.Stacking"
defaultValue={options.series.stacking}
disabled={!includes(["line", "area", "column"], options.globalSeriesType)}
onChange={stacking => onOptionsChange({ series: { stacking } })}>
onChange={(stacking: any) => onOptionsChange({ series: { stacking } })}>
{/* @ts-expect-error ts-migrate(2339) FIXME: Property 'Option' does not exist on type '({ class... Remove this comment to see the full error message */}
<Select.Option value={null} data-test="Chart.Stacking.Disabled">
Disabled
{/* @ts-expect-error ts-migrate(2339) FIXME: Property 'Option' does not exist on type '({ class... Remove this comment to see the full error message */}
</Select.Option>
{/* @ts-expect-error ts-migrate(2339) FIXME: Property 'Option' does not exist on type '({ class... Remove this comment to see the full error message */}
<Select.Option value="stack" data-test="Chart.Stacking.Stack">
Stack
{/* @ts-expect-error ts-migrate(2339) FIXME: Property 'Option' does not exist on type '({ class... Remove this comment to see the full error message */}
</Select.Option>
</Select>
</Section>
)}
{includes(["line", "area", "column"], options.globalSeriesType) && (
// @ts-expect-error ts-migrate(2745) FIXME: This JSX tag's 'children' prop expects type 'never... Remove this comment to see the full error message
<Section>
<Checkbox
data-test="Chart.NormalizeValues"
@@ -275,17 +323,22 @@ export default function GeneralSettings({ options, data, onOptionsChange }) {
)}
{!includes(["custom", "heatmap", "bubble", "scatter"], options.globalSeriesType) && (
// @ts-expect-error ts-migrate(2745) FIXME: This JSX tag's 'children' prop expects type 'never... Remove this comment to see the full error message
<Section>
<Select
label="Missing and NULL values"
data-test="Chart.MissingValues"
defaultValue={options.missingValuesAsZero ? 1 : 0}
onChange={value => onOptionsChange({ missingValuesAsZero: !!value })}>
onChange={(value: any) => onOptionsChange({ missingValuesAsZero: !!value })}>
{/* @ts-expect-error ts-migrate(2339) FIXME: Property 'Option' does not exist on type '({ class... Remove this comment to see the full error message */}
<Select.Option value={0} data-test="Chart.MissingValues.Keep">
Do not display in chart
{/* @ts-expect-error ts-migrate(2339) FIXME: Property 'Option' does not exist on type '({ class... Remove this comment to see the full error message */}
</Select.Option>
{/* @ts-expect-error ts-migrate(2339) FIXME: Property 'Option' does not exist on type '({ class... Remove this comment to see the full error message */}
<Select.Option value={1} data-test="Chart.MissingValues.Zero">
Convert to 0 and display in chart
{/* @ts-expect-error ts-migrate(2339) FIXME: Property 'Option' does not exist on type '({ class... Remove this comment to see the full error message */}
</Select.Option>
</Select>
</Section>

View File

@@ -25,9 +25,13 @@ const ColorSchemes = [
"Custom...",
];
export default function HeatmapColorsSettings({ options, onOptionsChange }) {
export default function HeatmapColorsSettings({
options,
onOptionsChange
}: any) {
return (
<React.Fragment>
{/* @ts-expect-error ts-migrate(2745) FIXME: This JSX tag's 'children' prop expects type 'never... Remove this comment to see the full error message */}
<Section>
<Select
label="Color Scheme"
@@ -35,10 +39,12 @@ export default function HeatmapColorsSettings({ options, onOptionsChange }) {
placeholder="Choose Color Scheme..."
allowClear
value={options.colorScheme || undefined}
onChange={value => onOptionsChange({ colorScheme: value || null })}>
onChange={(value: any) => onOptionsChange({ colorScheme: value || null })}>
{map(ColorSchemes, scheme => (
// @ts-expect-error ts-migrate(2339) FIXME: Property 'Option' does not exist on type '({ class... Remove this comment to see the full error message
<Select.Option key={scheme} value={scheme} data-test={`Chart.Colors.Heatmap.ColorScheme.${scheme}`}>
{scheme}
{/* @ts-expect-error ts-migrate(2339) FIXME: Property 'Option' does not exist on type '({ class... Remove this comment to see the full error message */}
</Select.Option>
))}
</Select>
@@ -46,6 +52,7 @@ export default function HeatmapColorsSettings({ options, onOptionsChange }) {
{options.colorScheme === "Custom..." && (
<React.Fragment>
{/* @ts-expect-error ts-migrate(2745) FIXME: This JSX tag's 'children' prop expects type 'never... Remove this comment to see the full error message */}
<Section>
<ColorPicker
layout="horizontal"
@@ -55,10 +62,12 @@ export default function HeatmapColorsSettings({ options, onOptionsChange }) {
placement="topLeft"
presetColors={ColorPalette}
color={options.heatMinColor}
onChange={heatMinColor => onOptionsChange({ heatMinColor })}
onChange={(heatMinColor: any) => onOptionsChange({ heatMinColor })}
// @ts-expect-error ts-migrate(2339) FIXME: Property 'Label' does not exist on type '({ classN... Remove this comment to see the full error message
addonAfter={<ColorPicker.Label color={options.heatMinColor} presetColors={ColorPalette} />}
/>
</Section>
{/* @ts-expect-error ts-migrate(2745) FIXME: This JSX tag's 'children' prop expects type 'never... Remove this comment to see the full error message */}
<Section>
<ColorPicker
layout="horizontal"
@@ -68,7 +77,8 @@ export default function HeatmapColorsSettings({ options, onOptionsChange }) {
placement="topRight"
presetColors={ColorPalette}
color={options.heatMaxColor}
onChange={heatMaxColor => onOptionsChange({ heatMaxColor })}
onChange={(heatMaxColor: any) => onOptionsChange({ heatMaxColor })}
// @ts-expect-error ts-migrate(2339) FIXME: Property 'Label' does not exist on type '({ classN... Remove this comment to see the full error message
addonAfter={<ColorPicker.Label color={options.heatMaxColor} presetColors={ColorPalette} />}
/>
</Section>

View File

@@ -6,7 +6,7 @@ import { EditorPropTypes } from "@/visualizations/prop-types";
import ColorPalette from "@/visualizations/ColorPalette";
import getChartData from "../getChartData";
function getUniqueValues(chartData) {
function getUniqueValues(chartData: any) {
const uniqueValuesNames = new Set();
each(chartData, series => {
each(series.data, row => {
@@ -16,7 +16,11 @@ function getUniqueValues(chartData) {
return [...uniqueValuesNames];
}
export default function PieColorsSettings({ options, data, onOptionsChange }) {
export default function PieColorsSettings({
options,
data,
onOptionsChange
}: any) {
const colors = useMemo(
() => ({
Automatic: null,
@@ -29,6 +33,7 @@ export default function PieColorsSettings({ options, data, onOptionsChange }) {
() =>
map(getUniqueValues(getChartData(data.rows, options)), value => ({
key: value,
// @ts-expect-error ts-migrate(2538) FIXME: Type 'unknown' cannot be used as an index type.
color: (options.valuesOptions[value] || {}).color || null,
})),
[options, data]
@@ -56,14 +61,21 @@ export default function PieColorsSettings({ options, data, onOptionsChange }) {
title: "Color",
dataIndex: "color",
width: "1%",
render: (unused, item) => (
render: (unused: any, item: any) => (
<ColorPicker
// @ts-expect-error ts-migrate(2322) FIXME: Type 'string' is not assignable to type 'never'.
data-test={`Chart.Series.${item.key}.Color`}
// @ts-expect-error ts-migrate(2322) FIXME: Type 'boolean' is not assignable to type 'never'.
interactive
// @ts-expect-error ts-migrate(2322) FIXME: Type '{ "Indian Red": string; "Green 2": string; "... Remove this comment to see the full error message
presetColors={colors}
// @ts-expect-error ts-migrate(2322) FIXME: Type 'string' is not assignable to type 'never'.
placement="topRight"
// @ts-expect-error ts-migrate(2322) FIXME: Type 'any' is not assignable to type 'never'.
color={item.color}
onChange={value => updateValuesOption(item.key, "color", value)}
// @ts-expect-error ts-migrate(2322) FIXME: Type '(value: any) => void' is not assignable to t... Remove this comment to see the full error message
onChange={(value: any) => updateValuesOption(item.key, "color", value)}
// @ts-expect-error ts-migrate(2322) FIXME: Type 'Element' is not assignable to type 'never'.
addonAfter={<ColorPicker.Label color={item.color} presetColors={colors} />}
/>
),

View File

@@ -4,11 +4,11 @@ import enzyme from "enzyme";
import getOptions from "../getOptions";
import SeriesSettings from "./SeriesSettings";
function findByTestID(wrapper, testId) {
function findByTestID(wrapper: any, testId: any) {
return wrapper.find(`[data-test="${testId}"]`);
}
function mount(options, done) {
function mount(options: any, done: any) {
options = getOptions(options);
return enzyme.mount(
<SeriesSettings

View File

@@ -4,20 +4,21 @@ import { useDebouncedCallback } from "use-debounce";
import Table from "antd/lib/table";
import Input from "antd/lib/input";
import Radio from "antd/lib/radio";
// @ts-expect-error ts-migrate(2724) FIXME: Module '"../../../../node_modules/react-sortable-h... Remove this comment to see the full error message
import { sortableElement } from "react-sortable-hoc";
import { SortableContainer, DragHandle } from "@/components/sortable";
import { EditorPropTypes } from "@/visualizations/prop-types";
import ChartTypeSelect from "./ChartTypeSelect";
import getChartData from "../getChartData";
const SortableBodyRow = sortableElement(props => <tr {...props} />);
const SortableBodyRow = sortableElement((props: any) => <tr {...props} />);
function getTableColumns(options, updateSeriesOption, debouncedUpdateSeriesOption) {
function getTableColumns(options: any, updateSeriesOption: any, debouncedUpdateSeriesOption: any) {
const result = [
{
title: "Order",
dataIndex: "zIndex",
render: (unused, item) => (
render: (unused: any, item: any) => (
<span className="series-settings-order">
<DragHandle />
{item.zIndex + 1}
@@ -27,7 +28,7 @@ function getTableColumns(options, updateSeriesOption, debouncedUpdateSeriesOptio
{
title: "Label",
dataIndex: "name",
render: (unused, item) => (
render: (unused: any, item: any) => (
<Input
data-test={`Chart.Series.${item.key}.Label`}
placeholder={item.key}
@@ -67,8 +68,9 @@ function getTableColumns(options, updateSeriesOption, debouncedUpdateSeriesOptio
data-test={`Chart.Series.${item.key}.Type`}
dropdownMatchSelectWidth={false}
value={item.type}
// @ts-expect-error ts-migrate(2322) FIXME: Type 'string' is not assignable to type 'never'.
hiddenChartTypes={["pie", "heatmap", "bubble", "box"]}
onChange={value => updateSeriesOption(item.key, "type", value)}
onChange={(value: any) => updateSeriesOption(item.key, "type", value)}
/>
),
});
@@ -77,7 +79,11 @@ function getTableColumns(options, updateSeriesOption, debouncedUpdateSeriesOptio
return result;
}
export default function SeriesSettings({ options, data, onOptionsChange }) {
export default function SeriesSettings({
options,
data,
onOptionsChange
}: any) {
const series = useMemo(
() =>
map(
@@ -92,6 +98,7 @@ export default function SeriesSettings({ options, data, onOptionsChange }) {
({ oldIndex, newIndex }) => {
const seriesOptions = [...series];
seriesOptions.splice(newIndex, 0, ...seriesOptions.splice(oldIndex, 1));
// @ts-expect-error ts-migrate(2339) FIXME: Property 'key' does not exist on type 'Boolean'.
onOptionsChange({ seriesOptions: fromPairs(map(seriesOptions, ({ key }, zIndex) => [key, { zIndex }])) });
},
[onOptionsChange, series]
@@ -124,12 +131,14 @@ export default function SeriesSettings({ options, data, onOptionsChange }) {
lockToContainerEdges
useDragHandle
helperClass="chart-editor-series-dragged-item"
helperContainer={container => container.querySelector("tbody")}
helperContainer={(container: any) => container.querySelector("tbody")}
onSortEnd={handleSortEnd}
containerProps={{
className: "chart-editor-series",
}}>
{/* @ts-expect-error ts-migrate(2322) FIXME: Type 'Element' is not assignable to type 'null | u... Remove this comment to see the full error message */}
<Table
// @ts-expect-error ts-migrate(2322) FIXME: Type 'boolean[]' is not assignable to type 'object... Remove this comment to see the full error message
dataSource={series}
columns={columns}
components={{
@@ -137,6 +146,7 @@ export default function SeriesSettings({ options, data, onOptionsChange }) {
row: SortableBodyRow,
},
}}
// @ts-expect-error ts-migrate(2322) FIXME: Type '(item: object) => { index: any; }' is not as... Remove this comment to see the full error message
onRow={item => ({ index: item.zIndex })}
pagination={false}
/>

View File

@@ -1,47 +0,0 @@
import React from "react";
import { Section, Switch } from "@/components/visualizations/editor";
import { EditorPropTypes } from "@/visualizations/prop-types";
import AxisSettings from "./AxisSettings";
export default function XAxisSettings({ options, onOptionsChange }) {
return (
<React.Fragment>
<AxisSettings
id="XAxis"
features={{ autoDetectType: true }}
options={options.xAxis}
onChange={xAxis => onOptionsChange({ xAxis })}
/>
<Section>
<Switch
data-test="Chart.XAxis.Sort"
defaultChecked={options.sortX}
onChange={sortX => onOptionsChange({ sortX })}>
Sort Values
</Switch>
</Section>
<Section>
<Switch
data-test="Chart.XAxis.Reverse"
defaultChecked={options.reverseX}
onChange={reverseX => onOptionsChange({ reverseX })}>
Reverse Order
</Switch>
</Section>
<Section>
<Switch
data-test="Chart.XAxis.ShowLabels"
defaultChecked={options.xAxis.labels.enabled}
onChange={enabled => onOptionsChange({ xAxis: { labels: { enabled } } })}>
Show Labels
</Switch>
</Section>
</React.Fragment>
);
}
XAxisSettings.propTypes = EditorPropTypes;

View File

@@ -4,11 +4,11 @@ import enzyme from "enzyme";
import getOptions from "../getOptions";
import XAxisSettings from "./XAxisSettings";
function findByTestID(wrapper, testId) {
function findByTestID(wrapper: any, testId: any) {
return wrapper.find(`[data-test="${testId}"]`);
}
function mount(options, done) {
function mount(options: any, done: any) {
options = getOptions(options);
return enzyme.mount(
<XAxisSettings

View File

@@ -0,0 +1,66 @@
import React from "react";
import { Section, Switch } from "@/components/visualizations/editor";
import { EditorPropTypes } from "@/visualizations/prop-types";
import AxisSettings from "./AxisSettings";
export default function XAxisSettings({
options,
onOptionsChange
}: any) {
return (
<React.Fragment>
<AxisSettings
id="XAxis"
features={{ autoDetectType: true }}
options={options.xAxis}
// @ts-expect-error ts-migrate(2322) FIXME: Type '(xAxis: any) => any' is not assignable to ty... Remove this comment to see the full error message
onChange={(xAxis: any) => onOptionsChange({ xAxis })}
/>
{/* @ts-expect-error ts-migrate(2745) FIXME: This JSX tag's 'children' prop expects type 'never... Remove this comment to see the full error message */}
<Section>
{/* @ts-expect-error ts-migrate(2745) FIXME: This JSX tag's 'children' prop expects type 'never... Remove this comment to see the full error message */}
<Switch
// @ts-expect-error ts-migrate(2322) FIXME: Type 'string' is not assignable to type 'never'.
data-test="Chart.XAxis.Sort"
// @ts-expect-error ts-migrate(2322) FIXME: Type 'any' is not assignable to type 'never'.
defaultChecked={options.sortX}
// @ts-expect-error ts-migrate(2322) FIXME: Type '(sortX: any) => any' is not assignable to ty... Remove this comment to see the full error message
onChange={(sortX: any) => onOptionsChange({ sortX })}>
Sort Values
</Switch>
</Section>
{/* @ts-expect-error ts-migrate(2745) FIXME: This JSX tag's 'children' prop expects type 'never... Remove this comment to see the full error message */}
<Section>
{/* @ts-expect-error ts-migrate(2745) FIXME: This JSX tag's 'children' prop expects type 'never... Remove this comment to see the full error message */}
<Switch
// @ts-expect-error ts-migrate(2322) FIXME: Type 'string' is not assignable to type 'never'.
data-test="Chart.XAxis.Reverse"
// @ts-expect-error ts-migrate(2322) FIXME: Type 'any' is not assignable to type 'never'.
defaultChecked={options.reverseX}
// @ts-expect-error ts-migrate(2322) FIXME: Type '(reverseX: any) => any' is not assignable to... Remove this comment to see the full error message
onChange={(reverseX: any) => onOptionsChange({ reverseX })}>
Reverse Order
</Switch>
</Section>
{/* @ts-expect-error ts-migrate(2745) FIXME: This JSX tag's 'children' prop expects type 'never... Remove this comment to see the full error message */}
<Section>
{/* @ts-expect-error ts-migrate(2745) FIXME: This JSX tag's 'children' prop expects type 'never... Remove this comment to see the full error message */}
<Switch
// @ts-expect-error ts-migrate(2322) FIXME: Type 'string' is not assignable to type 'never'.
data-test="Chart.XAxis.ShowLabels"
// @ts-expect-error ts-migrate(2322) FIXME: Type 'any' is not assignable to type 'never'.
defaultChecked={options.xAxis.labels.enabled}
// @ts-expect-error ts-migrate(2322) FIXME: Type '(enabled: any) => any' is not assignable to ... Remove this comment to see the full error message
onChange={(enabled: any) => onOptionsChange({ xAxis: { labels: { enabled } } })}>
Show Labels
</Switch>
</Section>
</React.Fragment>
);
}
XAxisSettings.propTypes = EditorPropTypes;

View File

@@ -1,75 +0,0 @@
import React from "react";
import { Section, Switch } from "@/components/visualizations/editor";
import { EditorPropTypes } from "@/visualizations/prop-types";
import AxisSettings from "./AxisSettings";
export default function YAxisSettings({ options, onOptionsChange }) {
const [leftYAxis, rightYAxis] = options.yAxis;
return (
<React.Fragment>
<Section.Title>{!options.swappedAxes ? "Left Y Axis" : "X Axis"}</Section.Title>
<Section>
<AxisSettings
id="LeftYAxis"
features={{ range: true }}
options={leftYAxis}
onChange={axis => onOptionsChange({ yAxis: [axis, rightYAxis] })}
/>
</Section>
{options.globalSeriesType !== "heatmap" && !options.swappedAxes && (
<React.Fragment>
<Section.Title>Right Y Axis</Section.Title>
<Section>
<AxisSettings
id="RightYAxis"
features={{ range: true }}
options={rightYAxis}
onChange={axis => onOptionsChange({ yAxis: [leftYAxis, axis] })}
/>
</Section>
<Section>
<Switch
id="chart-editor-y-axis-align-at-zero"
data-test="Chart.YAxis.AlignAtZero"
defaultChecked={options.alignYAxesAtZero}
onChange={alignYAxesAtZero => onOptionsChange({ alignYAxesAtZero })}>
Align Y Axes at Zero
</Switch>
</Section>
</React.Fragment>
)}
{options.globalSeriesType === "heatmap" && (
<React.Fragment>
<Section>
<Switch
id="chart-editor-y-axis-sort"
data-test="Chart.LeftYAxis.Sort"
defaultChecked={options.sortY}
onChange={sortY => onOptionsChange({ sortY })}>
Sort Values
</Switch>
</Section>
<Section>
<Switch
id="chart-editor-y-axis-reverse"
data-test="Chart.LeftYAxis.Reverse"
defaultChecked={options.reverseY}
onChange={reverseY => onOptionsChange({ reverseY })}>
Reverse Order
</Switch>
</Section>
</React.Fragment>
)}
</React.Fragment>
);
}
YAxisSettings.propTypes = EditorPropTypes;

View File

@@ -4,15 +4,15 @@ import enzyme from "enzyme";
import getOptions from "../getOptions";
import YAxisSettings from "./YAxisSettings";
function findByTestID(wrapper, testId) {
function findByTestID(wrapper: any, testId: any) {
return wrapper.find(`[data-test="${testId}"]`);
}
function elementExists(wrapper, testId) {
function elementExists(wrapper: any, testId: any) {
return findByTestID(wrapper, testId).length > 0;
}
function mount(options, done) {
function mount(options: any, done: any) {
options = getOptions(options);
return enzyme.mount(
<YAxisSettings
@@ -91,6 +91,7 @@ describe("Visualizations -> Chart -> Editor -> Y-Axis Settings", () => {
describe("for non-heatmap", () => {
test("Right Y Axis should be available", () => {
// @ts-expect-error ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
const el = mount({
globalSeriesType: "column",
yAxis: [{ type: "linear" }, { type: "linear", opposite: true }],
@@ -102,6 +103,7 @@ describe("Visualizations -> Chart -> Editor -> Y-Axis Settings", () => {
describe("for heatmap", () => {
test("Right Y Axis should not be available", () => {
// @ts-expect-error ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
const el = mount({
globalSeriesType: "heatmap",
yAxis: [{ type: "linear" }, { type: "linear", opposite: true }],

View File

@@ -0,0 +1,102 @@
import React from "react";
import { Section, Switch } from "@/components/visualizations/editor";
import { EditorPropTypes } from "@/visualizations/prop-types";
import AxisSettings from "./AxisSettings";
export default function YAxisSettings({
options,
onOptionsChange
}: any) {
const [leftYAxis, rightYAxis] = options.yAxis;
return (
<React.Fragment>
{/* @ts-expect-error ts-migrate(2745) FIXME: This JSX tag's 'children' prop expects type 'never... Remove this comment to see the full error message */}
<Section.Title>{!options.swappedAxes ? "Left Y Axis" : "X Axis"}</Section.Title>
{/* @ts-expect-error ts-migrate(2745) FIXME: This JSX tag's 'children' prop expects type 'never... Remove this comment to see the full error message */}
<Section>
<AxisSettings
id="LeftYAxis"
features={{ range: true }}
options={leftYAxis}
// @ts-expect-error ts-migrate(2322) FIXME: Type '(axis: any) => any' is not assignable to typ... Remove this comment to see the full error message
onChange={(axis: any) => onOptionsChange({ yAxis: [axis, rightYAxis] })}
/>
</Section>
{options.globalSeriesType !== "heatmap" && !options.swappedAxes && (
<React.Fragment>
{/* @ts-expect-error ts-migrate(2745) FIXME: This JSX tag's 'children' prop expects type 'never... Remove this comment to see the full error message */}
<Section.Title>Right Y Axis</Section.Title>
{/* @ts-expect-error ts-migrate(2745) FIXME: This JSX tag's 'children' prop expects type 'never... Remove this comment to see the full error message */}
<Section>
<AxisSettings
id="RightYAxis"
features={{ range: true }}
options={rightYAxis}
// @ts-expect-error ts-migrate(2322) FIXME: Type '(axis: any) => any' is not assignable to typ... Remove this comment to see the full error message
onChange={(axis: any) => onOptionsChange({ yAxis: [leftYAxis, axis] })}
/>
</Section>
{/* @ts-expect-error ts-migrate(2745) FIXME: This JSX tag's 'children' prop expects type 'never... Remove this comment to see the full error message */}
<Section>
{/* @ts-expect-error ts-migrate(2745) FIXME: This JSX tag's 'children' prop expects type 'never... Remove this comment to see the full error message */}
<Switch
// @ts-expect-error ts-migrate(2322) FIXME: Type 'string' is not assignable to type 'never'.
id="chart-editor-y-axis-align-at-zero"
// @ts-expect-error ts-migrate(2322) FIXME: Type 'string' is not assignable to type 'never'.
data-test="Chart.YAxis.AlignAtZero"
// @ts-expect-error ts-migrate(2322) FIXME: Type 'any' is not assignable to type 'never'.
defaultChecked={options.alignYAxesAtZero}
// @ts-expect-error ts-migrate(2322) FIXME: Type '(alignYAxesAtZero: any) => any' is not assig... Remove this comment to see the full error message
onChange={(alignYAxesAtZero: any) => onOptionsChange({ alignYAxesAtZero })}>
Align Y Axes at Zero
</Switch>
</Section>
</React.Fragment>
)}
{options.globalSeriesType === "heatmap" && (
<React.Fragment>
{/* @ts-expect-error ts-migrate(2745) FIXME: This JSX tag's 'children' prop expects type 'never... Remove this comment to see the full error message */}
<Section>
{/* @ts-expect-error ts-migrate(2745) FIXME: This JSX tag's 'children' prop expects type 'never... Remove this comment to see the full error message */}
<Switch
// @ts-expect-error ts-migrate(2322) FIXME: Type 'string' is not assignable to type 'never'.
id="chart-editor-y-axis-sort"
// @ts-expect-error ts-migrate(2322) FIXME: Type 'string' is not assignable to type 'never'.
data-test="Chart.LeftYAxis.Sort"
// @ts-expect-error ts-migrate(2322) FIXME: Type 'any' is not assignable to type 'never'.
defaultChecked={options.sortY}
// @ts-expect-error ts-migrate(2322) FIXME: Type '(sortY: any) => any' is not assignable to ty... Remove this comment to see the full error message
onChange={(sortY: any) => onOptionsChange({ sortY })}>
Sort Values
</Switch>
</Section>
{/* @ts-expect-error ts-migrate(2745) FIXME: This JSX tag's 'children' prop expects type 'never... Remove this comment to see the full error message */}
<Section>
{/* @ts-expect-error ts-migrate(2745) FIXME: This JSX tag's 'children' prop expects type 'never... Remove this comment to see the full error message */}
<Switch
// @ts-expect-error ts-migrate(2322) FIXME: Type 'string' is not assignable to type 'never'.
id="chart-editor-y-axis-reverse"
// @ts-expect-error ts-migrate(2322) FIXME: Type 'string' is not assignable to type 'never'.
data-test="Chart.LeftYAxis.Reverse"
// @ts-expect-error ts-migrate(2322) FIXME: Type 'any' is not assignable to type 'never'.
defaultChecked={options.reverseY}
// @ts-expect-error ts-migrate(2322) FIXME: Type '(reverseY: any) => any' is not assignable to... Remove this comment to see the full error message
onChange={(reverseY: any) => onOptionsChange({ reverseY })}>
Reverse Order
</Switch>
</Section>
</React.Fragment>
)}
</React.Fragment>
);
}
YAxisSettings.propTypes = EditorPropTypes;

View File

@@ -4,15 +4,15 @@ import enzyme from "enzyme";
import getOptions from "../getOptions";
import Editor from "./index";
function findByTestID(wrapper, testId) {
function findByTestID(wrapper: any, testId: any) {
return wrapper.find(`[data-test="${testId}"]`);
}
function elementExists(wrapper, testId) {
function elementExists(wrapper: any, testId: any) {
return findByTestID(wrapper, testId).length > 0;
}
function mount(options, data) {
function mount(options: any, data: any) {
options = getOptions(options);
return enzyme.mount(<Editor visualizationName="Test" data={data} options={options} onOptionsChange={() => {}} />);
}

View File

@@ -12,48 +12,50 @@ import CustomChartSettings from "./CustomChartSettings";
import "./editor.less";
const isCustomChart = options => options.globalSeriesType === "custom";
const isPieChart = options => options.globalSeriesType === "pie";
const isCustomChart = (options: any) => options.globalSeriesType === "custom";
const isPieChart = (options: any) => options.globalSeriesType === "pie";
export default createTabbedEditor([
{
key: "General",
title: "General",
component: props => (
<React.Fragment>
<GeneralSettings {...props} />
{isCustomChart(props.options) && <CustomChartSettings {...props} />}
</React.Fragment>
),
component: (props: any) => <React.Fragment>
<GeneralSettings {...props} />
{isCustomChart(props.options) && <CustomChartSettings {...props} />}
</React.Fragment>,
},
{
key: "XAxis",
title: ({ swappedAxes }) => (!swappedAxes ? "X Axis" : "Y Axis"),
title: ({
swappedAxes
}: any) => (!swappedAxes ? "X Axis" : "Y Axis"),
component: XAxisSettings,
isAvailable: options => !isCustomChart(options) && !isPieChart(options),
isAvailable: (options: any) => !isCustomChart(options) && !isPieChart(options),
},
{
key: "YAxis",
title: ({ swappedAxes }) => (!swappedAxes ? "Y Axis" : "X Axis"),
title: ({
swappedAxes
}: any) => (!swappedAxes ? "Y Axis" : "X Axis"),
component: YAxisSettings,
isAvailable: options => !isCustomChart(options) && !isPieChart(options),
isAvailable: (options: any) => !isCustomChart(options) && !isPieChart(options),
},
{
key: "Series",
title: "Series",
component: SeriesSettings,
isAvailable: options => !isCustomChart(options),
isAvailable: (options: any) => !isCustomChart(options),
},
{
key: "Colors",
title: "Colors",
component: ColorsSettings,
isAvailable: options => !isCustomChart(options),
isAvailable: (options: any) => !isCustomChart(options),
},
{
key: "DataLabels",
title: "Data Labels",
component: DataLabelsSettings,
isAvailable: options => !isCustomChart(options),
isAvailable: (options: any) => !isCustomChart(options),
},
]);

View File

@@ -6,7 +6,10 @@ import resizeObserver from "@/services/resizeObserver";
import getChartData from "../getChartData";
import { Plotly, prepareCustomChartData, createCustomChartRenderer } from "../plotly";
export default function CustomPlotlyChart({ options, data }) {
export default function CustomPlotlyChart({
options,
data
}: any) {
const [container, setContainer] = useState(null);
const renderCustomChart = useMemo(() => createCustomChartRenderer(options.customCode, options.enableConsoleLogs), [
@@ -20,6 +23,7 @@ export default function CustomPlotlyChart({ options, data }) {
if (container) {
const unwatch = resizeObserver(container, () => {
// Clear existing data with blank data for succeeding codeCall adds data to existing plot.
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'null' is not assignable to param... Remove this comment to see the full error message
Plotly.purge(container);
renderCustomChart(plotlyData.x, plotlyData.ys, container, Plotly);
});
@@ -30,10 +34,12 @@ export default function CustomPlotlyChart({ options, data }) {
// Cleanup when component destroyed
useEffect(() => {
if (container) {
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'null' is not assignable to param... Remove this comment to see the full error message
return () => Plotly.purge(container);
}
}, [container]);
// @ts-expect-error ts-migrate(2322) FIXME: Type 'Dispatch<SetStateAction<null>>' is not assig... Remove this comment to see the full error message
return <div className="chart-visualization-container" ref={setContainer} />;
}

View File

@@ -1,10 +0,0 @@
import React from "react";
export interface PlotlyChartProps {
data: {
rows: any[];
columns: any[];
}
options: object;
}
declare const PlotlyChart: React.FC<PlotlyChartProps>;
export default PlotlyChart;

View File

@@ -6,16 +6,29 @@ import { visualizationsSettings } from "@/visualizations/visualizationsSettings"
import getChartData from "../getChartData";
import initChart from "./initChart";
export default function PlotlyChart({ options, data }) {
export interface PlotlyChartProps {
data: {
rows: any[];
columns: any[];
}
options: object;
}
export default function PlotlyChart({
options,
data
}: PlotlyChartProps) {
const [container, setContainer] = useState(null);
const [chart, setChart] = useState(null);
const errorHandler = useContext(ErrorBoundaryContext);
const errorHandlerRef = useRef();
// @ts-expect-error ts-migrate(2322) FIXME: Type '{ handleError: (error: any) => void; reset: ... Remove this comment to see the full error message
errorHandlerRef.current = errorHandler;
const isMobile = useMedia({ maxWidth: 768 });
const isMobileRef = useRef();
// @ts-expect-error ts-migrate(2322) FIXME: Type 'boolean' is not assignable to type 'undefine... Remove this comment to see the full error message
isMobileRef.current = isMobile;
useEffect(() => {
@@ -23,7 +36,8 @@ export default function PlotlyChart({ options, data }) {
let isDestroyed = false;
const chartData = getChartData(data.rows, options);
const _chart = initChart(container, options, chartData, visualizationsSettings, error => {
const _chart = initChart(container, options, chartData, visualizationsSettings, (error: any) => {
// @ts-expect-error ts-migrate(2532) FIXME: Object is possibly 'undefined'.
errorHandlerRef.current.handleError(error);
});
_chart.initialized.then(() => {
@@ -40,10 +54,12 @@ export default function PlotlyChart({ options, data }) {
useEffect(() => {
if (chart) {
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
chart.setZoomEnabled(!isMobile);
}
}, [chart, isMobile]);
// @ts-expect-error ts-migrate(2322) FIXME: Type 'Dispatch<SetStateAction<null>>' is not assig... Remove this comment to see the full error message
return <div className="chart-visualization-container" ref={setContainer} />;
}

View File

@@ -7,7 +7,10 @@ import { visualizationsSettings } from "@/visualizations/visualizationsSettings"
import "./renderer.less";
export default function Renderer({ options, ...props }) {
export default function Renderer({
options,
...props
}: any) {
if (options.globalSeriesType === "custom" && visualizationsSettings.allowCustomJSVisualizations) {
return <CustomPlotlyChart options={options} {...props} />;
}

View File

@@ -2,8 +2,8 @@ import { isArray, isObject, isString, isFunction, startsWith, reduce, merge, map
import resizeObserver from "@/services/resizeObserver";
import { Plotly, prepareData, prepareLayout, updateData, updateAxes, updateChartSize } from "../plotly";
function createErrorHandler(errorHandler) {
return error => {
function createErrorHandler(errorHandler: any) {
return (error: any) => {
// This error happens only when chart width is 20px and looks that
// it's safe to just ignore it: 1px less or more and chart will get fixed.
if (isString(error) && startsWith(error, "ax.dtick error")) {
@@ -21,16 +21,17 @@ function createErrorHandler(errorHandler) {
// `.process()` merges all updates into a single object and calls `Plotly.relayout()`. After that
// it calls all callbacks, collects their return values and does another loop if needed.
function initPlotUpdater() {
let actions = [];
let actions: any = [];
const updater = {
append(action) {
append(action: any) {
if (isArray(action) && isObject(action[0])) {
actions.push(action);
}
return updater;
},
process(plotlyElement) {
// @ts-expect-error ts-migrate(7023) FIXME: 'process' implicitly has return type 'any' because... Remove this comment to see the full error message
process(plotlyElement: any) {
if (actions.length > 0) {
const updates = reduce(actions, (updates, action) => merge(updates, action[0]), {});
const handlers = map(actions, action => (isFunction(action[1]) ? action[1] : () => null));
@@ -48,7 +49,7 @@ function initPlotUpdater() {
return updater;
}
export default function initChart(container, options, data, additionalOptions, onError) {
export default function initChart(container: any, options: any, data: any, additionalOptions: any, onError: any) {
const handleError = createErrorHandler(onError);
const plotlyOptions = {
@@ -57,6 +58,7 @@ export default function initChart(container, options, data, additionalOptions, o
};
if (additionalOptions.hidePlotlyModeBar) {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'displayModeBar' does not exist on type '... Remove this comment to see the full error message
plotlyOptions.displayModeBar = false;
}
@@ -67,7 +69,8 @@ export default function initChart(container, options, data, additionalOptions, o
let updater = initPlotUpdater();
function createSafeFunction(fn) {
function createSafeFunction(fn: any) {
// @ts-expect-error ts-migrate(7019) FIXME: Rest parameter 'args' implicitly has an 'any[]' ty... Remove this comment to see the full error message
return (...args) => {
if (!isDestroyed) {
try {
@@ -95,9 +98,10 @@ export default function initChart(container, options, data, additionalOptions, o
createSafeFunction(() => {
container.on(
"plotly_restyle",
createSafeFunction(updates => {
createSafeFunction((updates: any) => {
// This event is triggered if some plotly data/layout has changed.
// We need to catch only changes of traces visibility to update stacking
// @ts-expect-error ts-migrate(2339) FIXME: Property 'visible' does not exist on type 'object'... Remove this comment to see the full error message
if (isArray(updates) && isObject(updates[0]) && updates[0].visible) {
updateData(plotlyData, options);
updater.append(updateAxes(container, plotlyData, plotlyLayout, options)).process(container);
@@ -117,10 +121,12 @@ export default function initChart(container, options, data, additionalOptions, o
)
.catch(handleError);
// @ts-expect-error ts-migrate(7022) FIXME: 'result' implicitly has type 'any' because it does... Remove this comment to see the full error message
const result = {
initialized: promise.then(() => result),
setZoomEnabled: createSafeFunction(allowZoom => {
setZoomEnabled: createSafeFunction((allowZoom: any) => {
const layoutUpdates = { dragmode: allowZoom ? "zoom" : false };
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type '{ dragmode: string | boolean; }'... Remove this comment to see the full error message
return Plotly.relayout(container, layoutUpdates);
}),
destroy: createSafeFunction(() => {

View File

@@ -1,6 +1,6 @@
import { isNil, isObject, each, forOwn, sortBy, values } from "lodash";
function addPointToSeries(point, seriesCollection, seriesName) {
function addPointToSeries(point: any, seriesCollection: any, seriesName: any) {
if (seriesCollection[seriesName] === undefined) {
seriesCollection[seriesName] = {
name: seriesName,
@@ -12,7 +12,7 @@ function addPointToSeries(point, seriesCollection, seriesName) {
seriesCollection[seriesName].data.push(point);
}
export default function getChartData(data, options) {
export default function getChartData(data: any, options: any) {
const series = {};
const mappings = options.columnMapping;
@@ -22,9 +22,9 @@ export default function getChartData(data, options) {
let seriesName = null;
let xValue = 0;
const yValues = {};
let eValue = null;
let sizeValue = null;
let zValue = null;
let eValue: any = null;
let sizeValue: any = null;
let zValue: any = null;
forOwn(row, (value, definition) => {
definition = "" + definition;
@@ -38,14 +38,18 @@ export default function getChartData(data, options) {
if (type === "x") {
xValue = value;
// @ts-expect-error ts-migrate(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
point[type] = value;
}
if (type === "y") {
// @ts-expect-error ts-migrate(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
yValues[name] = value;
// @ts-expect-error ts-migrate(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
point[type] = value;
}
if (type === "yError") {
eValue = value;
// @ts-expect-error ts-migrate(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
point[type] = value;
}
@@ -54,11 +58,13 @@ export default function getChartData(data, options) {
}
if (type === "size") {
// @ts-expect-error ts-migrate(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
point[type] = value;
sizeValue = value;
}
if (type === "zVal") {
// @ts-expect-error ts-migrate(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
point[type] = value;
zValue = value;
}
@@ -70,16 +76,20 @@ export default function getChartData(data, options) {
if (isNil(seriesName)) {
each(yValues, (yValue, ySeriesName) => {
// @ts-expect-error ts-migrate(2322) FIXME: Type '{ x: number; y: never; $raw: any; }' is not ... Remove this comment to see the full error message
point = { x: xValue, y: yValue, $raw: point.$raw };
if (eValue !== null) {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'yError' does not exist on type '{ $raw: ... Remove this comment to see the full error message
point.yError = eValue;
}
if (sizeValue !== null) {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'size' does not exist on type '{ $raw: an... Remove this comment to see the full error message
point.size = sizeValue;
}
if (zValue !== null) {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'zVal' does not exist on type '{ $raw: an... Remove this comment to see the full error message
point.zVal = zValue;
}
addPointToSeries(point, series, ySeriesName);

View File

@@ -26,7 +26,7 @@ const DEFAULT_OPTIONS = {
missingValuesAsZero: true,
};
export default function getOptions(options) {
export default function getOptions(options: any) {
const result = merge(
{},
DEFAULT_OPTIONS,

View File

@@ -1,14 +1,17 @@
import { each } from "lodash";
import { normalizeValue } from "./utils";
export function prepareCustomChartData(series) {
const x = [];
export function prepareCustomChartData(series: any) {
const x: any = [];
const ys = {};
each(series, ({ name, data }) => {
// @ts-expect-error ts-migrate(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
ys[name] = [];
each(data, point => {
// @ts-expect-error ts-migrate(2554) FIXME: Expected 2-3 arguments, but got 1.
x.push(normalizeValue(point.x));
// @ts-expect-error ts-migrate(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
ys[name].push(normalizeValue(point.y));
});
});
@@ -16,10 +19,11 @@ export function prepareCustomChartData(series) {
return { x, ys };
}
export function createCustomChartRenderer(code, logErrorsToConsole = false) {
export function createCustomChartRenderer(code: any, logErrorsToConsole = false) {
// Create a function from custom code; catch syntax errors
let render = () => {};
try {
// @ts-expect-error ts-migrate(2322) FIXME: Type 'Function' is not assignable to type '() => v... Remove this comment to see the full error message
render = new Function("x, ys, element, Plotly", code); // eslint-disable-line no-new-func
} catch (err) {
if (logErrorsToConsole) {
@@ -28,8 +32,9 @@ export function createCustomChartRenderer(code, logErrorsToConsole = false) {
}
// Return function that will invoke custom code; catch runtime errors
return (x, ys, element, Plotly) => {
return (x: any, ys: any, element: any, Plotly: any) => {
try {
// @ts-expect-error ts-migrate(2554) FIXME: Expected 0 arguments, but got 4.
render(x, ys, element, Plotly);
} catch (err) {
if (logErrorsToConsole) {

View File

@@ -1,29 +0,0 @@
import Plotly from "plotly.js/lib/core";
import bar from "plotly.js/lib/bar";
import pie from "plotly.js/lib/pie";
import histogram from "plotly.js/lib/histogram";
import box from "plotly.js/lib/box";
import heatmap from "plotly.js/lib/heatmap";
import prepareData from "./prepareData";
import prepareLayout from "./prepareLayout";
import updateData from "./updateData";
import updateAxes from "./updateAxes";
import updateChartSize from "./updateChartSize";
import { prepareCustomChartData, createCustomChartRenderer } from "./customChartUtils";
Plotly.register([bar, pie, histogram, box, heatmap]);
Plotly.setPlotConfig({
modeBarButtonsToRemove: ["sendDataToCloud"],
});
export {
Plotly,
prepareData,
prepareLayout,
updateData,
updateAxes,
updateChartSize,
prepareCustomChartData,
createCustomChartRenderer,
};

View File

@@ -0,0 +1,36 @@
import Plotly from "plotly.js/lib/core";
// @ts-expect-error ts-migrate(7016) FIXME: Could not find a declaration file for module 'plot... Remove this comment to see the full error message
import bar from "plotly.js/lib/bar";
// @ts-expect-error ts-migrate(7016) FIXME: Could not find a declaration file for module 'plot... Remove this comment to see the full error message
import pie from "plotly.js/lib/pie";
// @ts-expect-error ts-migrate(7016) FIXME: Could not find a declaration file for module 'plot... Remove this comment to see the full error message
import histogram from "plotly.js/lib/histogram";
// @ts-expect-error ts-migrate(7016) FIXME: Could not find a declaration file for module 'plot... Remove this comment to see the full error message
import box from "plotly.js/lib/box";
// @ts-expect-error ts-migrate(7016) FIXME: Could not find a declaration file for module 'plot... Remove this comment to see the full error message
import heatmap from "plotly.js/lib/heatmap";
import prepareData from "./prepareData";
import prepareLayout from "./prepareLayout";
import updateData from "./updateData";
import updateAxes from "./updateAxes";
import updateChartSize from "./updateChartSize";
import { prepareCustomChartData, createCustomChartRenderer } from "./customChartUtils";
// @ts-expect-error ts-migrate(2339) FIXME: Property 'register' does not exist on type 'typeof... Remove this comment to see the full error message
Plotly.register([bar, pie, histogram, box, heatmap]);
// @ts-expect-error ts-migrate(2339) FIXME: Property 'setPlotConfig' does not exist on type 't... Remove this comment to see the full error message
Plotly.setPlotConfig({
modeBarButtonsToRemove: ["sendDataToCloud"],
});
export {
Plotly,
prepareData,
prepareLayout,
updateData,
updateAxes,
updateChartSize,
prepareCustomChartData,
createCustomChartRenderer,
};

View File

@@ -1,8 +1,11 @@
/* eslint-disable global-require, import/no-unresolved */
import prepareData from "./prepareData";
function cleanSeries(series) {
return series.map(({ sourceData, ...rest }) => rest);
function cleanSeries(series: any) {
return series.map(({
sourceData,
...rest
}: any) => rest);
}
describe("Visualizations", () => {

View File

@@ -3,11 +3,12 @@ import prepareHeatmapData from "./prepareHeatmapData";
import prepareDefaultData from "./prepareDefaultData";
import updateData from "./updateData";
export default function prepareData(seriesList, options) {
export default function prepareData(seriesList: any, options: any) {
switch (options.globalSeriesType) {
case "pie":
return updateData(preparePieData(seriesList, options), options);
case "heatmap":
// @ts-expect-error ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
return updateData(prepareHeatmapData(seriesList, options, options));
default:
return updateData(prepareDefaultData(seriesList, options), options);

View File

@@ -3,11 +3,11 @@ import chooseTextColorForBackground from "@/lib/chooseTextColorForBackground";
import { ColorPaletteArray } from "@/visualizations/ColorPalette";
import { cleanNumber, normalizeValue, getSeriesAxis } from "./utils";
function getSeriesColor(seriesOptions, seriesIndex) {
function getSeriesColor(seriesOptions: any, seriesIndex: any) {
return seriesOptions.color || ColorPaletteArray[seriesIndex % ColorPaletteArray.length];
}
function getHoverInfoPattern(options) {
function getHoverInfoPattern(options: any) {
const hasX = /{{\s*@@x\s*}}/.test(options.textFormat);
const hasName = /{{\s*@@name\s*}}/.test(options.textFormat);
let result = "text";
@@ -16,7 +16,7 @@ function getHoverInfoPattern(options) {
return result;
}
function prepareBarSeries(series, options, additionalOptions) {
function prepareBarSeries(series: any, options: any, additionalOptions: any) {
series.type = "bar";
series.offsetgroup = toString(additionalOptions.index);
if (options.showDataLabels) {
@@ -25,24 +25,27 @@ function prepareBarSeries(series, options, additionalOptions) {
return series;
}
function prepareLineSeries(series, options) {
function prepareLineSeries(series: any, options: any) {
series.mode = "lines" + (options.showDataLabels ? "+text" : "");
return series;
}
function prepareAreaSeries(series, options) {
function prepareAreaSeries(series: any, options: any) {
series.mode = "lines" + (options.showDataLabels ? "+text" : "");
series.fill = options.series.stacking ? "tonexty" : "tozeroy";
return series;
}
function prepareScatterSeries(series, options) {
function prepareScatterSeries(series: any, options: any) {
series.type = "scatter";
series.mode = "markers" + (options.showDataLabels ? "+text" : "");
return series;
}
function prepareBubbleSeries(series, options, { seriesColor, data }) {
function prepareBubbleSeries(series: any, options: any, {
seriesColor,
data
}: any) {
const coefficient = options.coefficient || 1;
series.mode = "markers";
series.marker = {
@@ -53,7 +56,9 @@ function prepareBubbleSeries(series, options, { seriesColor, data }) {
return series;
}
function prepareBoxSeries(series, options, { seriesColor }) {
function prepareBoxSeries(series: any, options: any, {
seriesColor
}: any) {
series.type = "box";
series.mode = "markers";
@@ -71,7 +76,7 @@ function prepareBoxSeries(series, options, { seriesColor }) {
return series;
}
function prepareSeries(series, options, additionalOptions) {
function prepareSeries(series: any, options: any, additionalOptions: any) {
const { hoverInfoPattern, index } = additionalOptions;
const seriesOptions = extend({ type: options.globalSeriesType, yAxis: 0 }, options.seriesOptions[series.name]);
@@ -85,15 +90,15 @@ function prepareSeries(series, options, additionalOptions) {
// for other types `y` is always number
const cleanYValue = includes(["bubble", "scatter"], seriesOptions.type)
? normalizeValue
: v => {
: (v: any) => {
v = cleanNumber(v);
return options.missingValuesAsZero && isNil(v) ? 0.0 : v;
};
const sourceData = new Map();
const xValues = [];
const yValues = [];
const yErrorValues = [];
const xValues: any = [];
const yValues: any = [];
const yErrorValues: any = [];
each(data, row => {
const x = normalizeValue(row.x, options.xAxis.type); // number/datetime/category
const y = cleanYValue(row.y, seriesYAxis === "y2" ? options.yAxis[1].type : options.yAxis[0].type); // depends on series type!
@@ -136,10 +141,13 @@ function prepareSeries(series, options, additionalOptions) {
case "column":
return prepareBarSeries(plotlySeries, options, additionalOptions);
case "line":
// @ts-expect-error ts-migrate(2554) FIXME: Expected 2 arguments, but got 3.
return prepareLineSeries(plotlySeries, options, additionalOptions);
case "area":
// @ts-expect-error ts-migrate(2554) FIXME: Expected 2 arguments, but got 3.
return prepareAreaSeries(plotlySeries, options, additionalOptions);
case "scatter":
// @ts-expect-error ts-migrate(2554) FIXME: Expected 2 arguments, but got 3.
return prepareScatterSeries(plotlySeries, options, additionalOptions);
case "bubble":
return prepareBubbleSeries(plotlySeries, options, additionalOptions);
@@ -150,7 +158,7 @@ function prepareSeries(series, options, additionalOptions) {
}
}
export default function prepareDefaultData(seriesList, options) {
export default function prepareDefaultData(seriesList: any, options: any) {
const additionalOptions = {
hoverInfoPattern: getHoverInfoPattern(options),
};

View File

@@ -12,7 +12,7 @@ const defaultColorScheme = [
[1, "#e92827"],
];
function prepareSeries(series, options, additionalOptions) {
function prepareSeries(series: any, options: any, additionalOptions: any) {
const { colorScheme, formatNumber } = additionalOptions;
const plotlySeries = {
@@ -24,7 +24,9 @@ function prepareSeries(series, options, additionalOptions) {
colorscale: colorScheme,
};
// @ts-expect-error ts-migrate(2322) FIXME: Type 'any[]' is not assignable to type 'never[]'.
plotlySeries.x = uniq(map(series.data, v => v.x));
// @ts-expect-error ts-migrate(2322) FIXME: Type 'any[]' is not assignable to type 'never[]'.
plotlySeries.y = uniq(map(series.data, v => v.y));
if (options.sortX) {
@@ -69,14 +71,18 @@ function prepareSeries(series, options, additionalOptions) {
if (isFinite(zMax) && options.showDataLabels) {
dataLabels.x.push(plotlySeries.x[j]);
dataLabels.y.push(plotlySeries.y[i]);
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'any' is not assignable to parame... Remove this comment to see the full error message
dataLabels.text.push(formatNumber(zValue));
if (options.colorScheme && options.colorScheme === "Custom...") {
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'string' is not assignable to par... Remove this comment to see the full error message
dataLabels.textfont.color.push("white");
} else {
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'string' is not assignable to par... Remove this comment to see the full error message
dataLabels.textfont.color.push(zValue / zMax < 0.25 ? "white" : "black");
}
}
}
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'any[]' is not assignable to para... Remove this comment to see the full error message
plotlySeries.z.push(item);
}
@@ -86,7 +92,7 @@ function prepareSeries(series, options, additionalOptions) {
return [plotlySeries];
}
export default function prepareHeatmapData(seriesList, options) {
export default function prepareHeatmapData(seriesList: any, options: any) {
let colorScheme = [];
if (!options.colorScheme) {

View File

@@ -1,11 +1,11 @@
import { isObject, isUndefined, filter, map } from "lodash";
import { getPieDimensions } from "./preparePieData";
function getAxisTitle(axis) {
function getAxisTitle(axis: any) {
return isObject(axis.title) ? axis.title.text : null;
}
function getAxisScaleType(axis) {
function getAxisScaleType(axis: any) {
switch (axis.type) {
case "datetime":
return "date";
@@ -16,7 +16,7 @@ function getAxisScaleType(axis) {
}
}
function prepareXAxis(axisOptions, additionalOptions) {
function prepareXAxis(axisOptions: any, additionalOptions: any) {
const axis = {
title: getAxisTitle(axisOptions),
type: getAxisScaleType(axisOptions),
@@ -25,20 +25,23 @@ function prepareXAxis(axisOptions, additionalOptions) {
if (additionalOptions.sortX && axis.type === "category") {
if (additionalOptions.reverseX) {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'categoryorder' does not exist on type '{... Remove this comment to see the full error message
axis.categoryorder = "category descending";
} else {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'categoryorder' does not exist on type '{... Remove this comment to see the full error message
axis.categoryorder = "category ascending";
}
}
if (!isUndefined(axisOptions.labels)) {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'showticklabels' does not exist on type '... Remove this comment to see the full error message
axis.showticklabels = axisOptions.labels.enabled;
}
return axis;
}
function prepareYAxis(axisOptions) {
function prepareYAxis(axisOptions: any) {
return {
title: getAxisTitle(axisOptions),
type: getAxisScaleType(axisOptions),
@@ -48,7 +51,7 @@ function prepareYAxis(axisOptions) {
};
}
function preparePieLayout(layout, options, data) {
function preparePieLayout(layout: any, options: any, data: any) {
const hasName = /{{\s*@@name\s*}}/.test(options.textFormat);
const { cellsInRow, cellWidth, cellHeight, xPadding } = getPieDimensions(data);
@@ -58,7 +61,9 @@ function preparePieLayout(layout, options, data) {
} else {
layout.annotations = filter(
map(data, (series, index) => {
// @ts-expect-error ts-migrate(2362) FIXME: The left-hand side of an arithmetic operation must... Remove this comment to see the full error message
const xPosition = (index % cellsInRow) * cellWidth;
// @ts-expect-error ts-migrate(2362) FIXME: The left-hand side of an arithmetic operation must... Remove this comment to see the full error message
const yPosition = Math.floor(index / cellsInRow) * cellHeight;
return {
x: xPosition + (cellWidth - xPadding) / 2,
@@ -75,8 +80,8 @@ function preparePieLayout(layout, options, data) {
return layout;
}
function prepareDefaultLayout(layout, options, data) {
const y2Series = data.filter(s => s.yaxis === "y2");
function prepareDefaultLayout(layout: any, options: any, data: any) {
const y2Series = data.filter((s: any) => s.yaxis === "y2");
layout.xaxis = prepareXAxis(options.xAxis, options);
@@ -94,14 +99,14 @@ function prepareDefaultLayout(layout, options, data) {
return layout;
}
function prepareBoxLayout(layout, options, data) {
function prepareBoxLayout(layout: any, options: any, data: any) {
layout = prepareDefaultLayout(layout, options, data);
layout.boxmode = "group";
layout.boxgroupgap = 0.5;
return layout;
}
export default function prepareLayout(element, options, data) {
export default function prepareLayout(element: any, options: any, data: any) {
const layout = {
margin: { l: 10, r: 10, b: 5, t: 20, pad: 4 },
// plot size should be at least 5x5px

View File

@@ -5,7 +5,7 @@ import { ColorPaletteArray } from "@/visualizations/ColorPalette";
import { cleanNumber, normalizeValue } from "./utils";
export function getPieDimensions(series) {
export function getPieDimensions(series: any) {
const rows = series.length > 2 ? 2 : 1;
const cellsInRow = Math.ceil(series.length / rows);
const cellWidth = 1 / cellsInRow;
@@ -16,14 +16,14 @@ export function getPieDimensions(series) {
return { rows, cellsInRow, cellWidth, cellHeight, xPadding, yPadding };
}
function getPieHoverInfoPattern(options) {
function getPieHoverInfoPattern(options: any) {
const hasX = /{{\s*@@x\s*}}/.test(options.textFormat);
let result = "text";
if (!hasX) result += "+label";
return result;
}
function prepareSeries(series, options, additionalOptions) {
function prepareSeries(series: any, options: any, additionalOptions: any) {
const {
cellWidth,
cellHeight,
@@ -41,8 +41,8 @@ function prepareSeries(series, options, additionalOptions) {
const xPosition = (index % cellsInRow) * cellWidth;
const yPosition = Math.floor(index / cellsInRow) * cellHeight;
const labels = [];
const values = [];
const labels: any = [];
const values: any = [];
const sourceData = new Map();
const seriesTotal = reduce(
series.data,
@@ -94,8 +94,9 @@ function prepareSeries(series, options, additionalOptions) {
};
}
export default function preparePieData(seriesList, options) {
export default function preparePieData(seriesList: any, options: any) {
// we will use this to assign colors for values that have no explicitly set color
// @ts-expect-error ts-migrate(2339) FIXME: Property 'scale' does not exist on type 'typeof im... Remove this comment to see the full error message
const getDefaultColor = d3.scale
.ordinal()
.domain([])
@@ -103,6 +104,7 @@ export default function preparePieData(seriesList, options) {
const valuesColors = {};
each(options.valuesOptions, (item, key) => {
if (isString(item.color) && item.color !== "") {
// @ts-expect-error ts-migrate(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
valuesColors[key] = item.color;
}
});
@@ -111,7 +113,8 @@ export default function preparePieData(seriesList, options) {
...getPieDimensions(seriesList),
hasX: includes(options.columnMapping, "x"),
hoverInfoPattern: getPieHoverInfoPattern(options),
getValueColor: v => valuesColors[v] || getDefaultColor(v),
// @ts-expect-error ts-migrate(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
getValueColor: (v: any) => valuesColors[v] || getDefaultColor(v),
};
return map(seriesList, (series, index) => prepareSeries(series, options, { ...additionalOptions, index }));

View File

@@ -1,14 +1,14 @@
import { isObject, isNumber, each } from "lodash";
function calculateAxisRange(range, min, max) {
function calculateAxisRange(range: any, min: any, max: any) {
return [isNumber(min) ? min : range[0], isNumber(max) ? max : range[1]];
}
function calculateAbsoluteDiff(value, totalRange, percentageDiff) {
function calculateAbsoluteDiff(value: any, totalRange: any, percentageDiff: any) {
return (percentageDiff * totalRange) / (1 - Math.abs(value) / totalRange - percentageDiff);
}
function alignYAxesAtZero(axisA, axisB) {
function alignYAxesAtZero(axisA: any, axisB: any) {
// Make sure the origin is included in both axes
axisA.range[1] = Math.max(0, axisA.range[1]);
axisB.range[1] = Math.max(0, axisB.range[1]);
@@ -40,9 +40,10 @@ function alignYAxesAtZero(axisA, axisB) {
}
}
export default function updateAxes(plotlyElement, seriesList, layout, options) {
export default function updateAxes(plotlyElement: any, seriesList: any, layout: any, options: any) {
const updates = {};
if (isObject(layout.yaxis)) {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'yaxis' does not exist on type '{}'.
updates.yaxis = {
...layout.yaxis,
autorange: true,
@@ -50,6 +51,7 @@ export default function updateAxes(plotlyElement, seriesList, layout, options) {
};
}
if (isObject(layout.yaxis2)) {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'yaxis2' does not exist on type '{}'.
updates.yaxis2 = {
...layout.yaxis2,
autorange: true,
@@ -64,14 +66,18 @@ export default function updateAxes(plotlyElement, seriesList, layout, options) {
if (isObject(layout.yaxis)) {
const axisOptions = options.yAxis[0];
const defaultRange = plotlyElement.layout.yaxis.range;
// @ts-expect-error ts-migrate(2339) FIXME: Property 'yaxis' does not exist on type '{}'.
updates.yaxis.autorange = false;
// @ts-expect-error ts-migrate(2339) FIXME: Property 'yaxis' does not exist on type '{}'.
updates.yaxis.range = calculateAxisRange(defaultRange, axisOptions.rangeMin, axisOptions.rangeMax);
}
if (isObject(layout.yaxis2)) {
const axisOptions = options.yAxis[1];
const defaultRange = plotlyElement.layout.yaxis2.range;
// @ts-expect-error ts-migrate(2339) FIXME: Property 'yaxis2' does not exist on type '{}'.
updates.yaxis2.autorange = false;
// @ts-expect-error ts-migrate(2339) FIXME: Property 'yaxis2' does not exist on type '{}'.
updates.yaxis2.range = calculateAxisRange(defaultRange, axisOptions.rangeMin, axisOptions.rangeMax);
}
@@ -85,19 +91,24 @@ export default function updateAxes(plotlyElement, seriesList, layout, options) {
});
const { xaxis } = layout;
// @ts-expect-error ts-migrate(2339) FIXME: Property 'yaxis' does not exist on type '{}'.
const { yaxis, yaxis2 } = updates;
if (isObject(xaxis) && isObject(yaxis)) {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'xaxis' does not exist on type '{}'.
updates.xaxis = yaxis;
// @ts-expect-error ts-migrate(2339) FIXME: Property 'yaxis' does not exist on type '{}'.
updates.yaxis = xaxis;
}
if (isObject(yaxis2)) {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'yaxis2' does not exist on type '{}'.
updates.yaxis2 = null;
}
}
// Align Y axes
if (options.alignYAxesAtZero && isObject(layout.yaxis) && isObject(layout.yaxis2)) {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'yaxis' does not exist on type '{}'.
alignYAxesAtZero(updates.yaxis, updates.yaxis2);
}

View File

@@ -1,6 +1,6 @@
import { find, pick, extend } from "lodash";
function fixLegendContainer(plotlyElement) {
function fixLegendContainer(plotlyElement: any) {
const legend = plotlyElement.querySelector(".legend");
if (legend) {
let node = legend.parentNode;
@@ -14,7 +14,7 @@ function fixLegendContainer(plotlyElement) {
}
}
function placeLegendNextToPlot(plotlyElement, layout) {
function placeLegendNextToPlot(plotlyElement: any, layout: any) {
const transformName = find(
["transform", "WebkitTransform", "MozTransform", "MsTransform", "OTransform"],
prop => prop in plotlyElement.style
@@ -32,13 +32,14 @@ function placeLegendNextToPlot(plotlyElement, layout) {
const legend = plotlyElement.querySelector(".legend");
if (legend) {
// @ts-expect-error ts-migrate(2538) FIXME: Type 'undefined' cannot be used as an index type.
legend.style[transformName] = null;
}
return [pick(layout, ["width", "height", "legend"]), null]; // no further updates
}
function placeLegendBelowPlot(plotlyElement, layout) {
function placeLegendBelowPlot(plotlyElement: any, layout: any) {
const transformName = find(
["transform", "WebkitTransform", "MozTransform", "MsTransform", "OTransform"],
prop => prop in plotlyElement.style
@@ -89,6 +90,7 @@ function placeLegendBelowPlot(plotlyElement, layout) {
// so we can split container's height half by half between them.
layout.height = Math.floor(Math.max(layoutHeight / 2, layoutHeight - (bounds.bottom - bounds.top)));
// offset the legend
// @ts-expect-error ts-migrate(2538) FIXME: Type 'undefined' cannot be used as an index type.
legend.style[transformName] = "translate(0, " + layout.height + "px)";
return [pick(layout, ["height"]), null]; // no further updates
}
@@ -96,7 +98,7 @@ function placeLegendBelowPlot(plotlyElement, layout) {
];
}
function placeLegendAuto(plotlyElement, layout) {
function placeLegendAuto(plotlyElement: any, layout: any) {
if (layout.width <= 600) {
return placeLegendBelowPlot(plotlyElement, layout);
} else {
@@ -104,7 +106,7 @@ function placeLegendAuto(plotlyElement, layout) {
}
}
export default function updateChartSize(plotlyElement, layout, options) {
export default function updateChartSize(plotlyElement: any, layout: any, options: any) {
// update layout size to plot container
// plot size should be at least 5x5px
layout.width = Math.max(5, Math.floor(plotlyElement.offsetWidth));

View File

@@ -2,11 +2,11 @@ import { isNil, each, extend, filter, identity, includes, map, sortBy } from "lo
import { createNumberFormatter, formatSimpleTemplate } from "@/lib/value-format";
import { normalizeValue } from "./utils";
function shouldUseUnifiedXAxis(options) {
function shouldUseUnifiedXAxis(options: any) {
return options.sortX && options.xAxis.type === "category" && options.globalSeriesType !== "box";
}
function defaultFormatSeriesText(item) {
function defaultFormatSeriesText(item: any) {
let result = item["@@y"];
if (item["@@yError"] !== undefined) {
result = `${result} \u00B1 ${item["@@yError"]}`;
@@ -20,18 +20,18 @@ function defaultFormatSeriesText(item) {
return result;
}
function defaultFormatSeriesTextForPie(item) {
function defaultFormatSeriesTextForPie(item: any) {
return item["@@yPercent"] + " (" + item["@@y"] + ")";
}
function createTextFormatter(options) {
function createTextFormatter(options: any) {
if (options.textFormat === "") {
return options.globalSeriesType === "pie" ? defaultFormatSeriesTextForPie : defaultFormatSeriesText;
}
return item => formatSimpleTemplate(options.textFormat, item);
return (item: any) => formatSimpleTemplate(options.textFormat, item);
}
function formatValue(value, axis, options) {
function formatValue(value: any, axis: any, options: any) {
let axisType = null;
switch (axis) {
case "x":
@@ -48,7 +48,7 @@ function formatValue(value, axis, options) {
return normalizeValue(value, axisType, options.dateTimeFormat);
}
function updateSeriesText(seriesList, options) {
function updateSeriesText(seriesList: any, options: any) {
const formatNumber = createNumberFormatter(options.numberFormat);
const formatPercent = createNumberFormatter(options.percentFormat);
const formatText = createTextFormatter(options);
@@ -61,7 +61,7 @@ function updateSeriesText(seriesList, options) {
series.text = [];
series.hover = [];
const xValues = options.globalSeriesType === "pie" ? series.labels : series.x;
xValues.forEach(x => {
xValues.forEach((x: any) => {
const text = {
"@@name": series.name,
};
@@ -74,16 +74,21 @@ function updateSeriesText(seriesList, options) {
// using default (ISO) date/time format. Here we need to use custom date/time format, so we pass original value
// to `formatValue` which will call `normalizeValue` again, but this time with different date/time format
// (if needed)
// @ts-expect-error ts-migrate(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
text["@@x"] = formatValue(item.row.x, "x", options);
// @ts-expect-error ts-migrate(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
text["@@y"] = yValueIsAny ? formatValue(item.row.y, series.yaxis, options) : formatNumber(item.y);
if (item.yError !== undefined) {
// @ts-expect-error ts-migrate(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
text["@@yError"] = formatNumber(item.yError);
}
if (item.size !== undefined) {
// @ts-expect-error ts-migrate(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
text["@@size"] = formatNumber(item.size);
}
if (options.series.percentValues || options.globalSeriesType === "pie") {
// @ts-expect-error ts-migrate(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
text["@@yPercent"] = formatPercent(Math.abs(item.yPercent));
}
@@ -94,22 +99,22 @@ function updateSeriesText(seriesList, options) {
});
}
function updatePercentValues(seriesList, options) {
function updatePercentValues(seriesList: any, options: any) {
if (options.series.percentValues) {
// Some series may not have corresponding x-values;
// do calculations for each x only for series that do have that x
const sumOfCorrespondingPoints = new Map();
each(seriesList, series => {
series.sourceData.forEach(item => {
series.sourceData.forEach((item: any) => {
const sum = sumOfCorrespondingPoints.get(item.x) || 0;
sumOfCorrespondingPoints.set(item.x, sum + Math.abs(item.y || 0.0));
});
});
each(seriesList, series => {
const yValues = [];
const yValues: any = [];
series.sourceData.forEach(item => {
series.sourceData.forEach((item: any) => {
if (isNil(item.y) && !options.missingValuesAsZero) {
item.yPercent = null;
} else {
@@ -124,11 +129,11 @@ function updatePercentValues(seriesList, options) {
}
}
function getUnifiedXAxisValues(seriesList, sorted) {
function getUnifiedXAxisValues(seriesList: any, sorted: any) {
const set = new Set();
each(seriesList, series => {
// `Map.forEach` will walk items in insertion order
series.sourceData.forEach(item => {
series.sourceData.forEach((item: any) => {
set.add(item.x);
});
});
@@ -137,7 +142,7 @@ function getUnifiedXAxisValues(seriesList, sorted) {
return sorted ? sortBy(result, identity) : result;
}
function updateUnifiedXAxisValues(seriesList, options) {
function updateUnifiedXAxisValues(seriesList: any, options: any) {
const unifiedX = getUnifiedXAxisValues(seriesList, options.sortX);
const defaultY = options.missingValuesAsZero ? 0.0 : null;
each(seriesList, series => {
@@ -158,11 +163,11 @@ function updateUnifiedXAxisValues(seriesList, options) {
});
}
function updatePieData(seriesList, options) {
function updatePieData(seriesList: any, options: any) {
updateSeriesText(seriesList, options);
}
function updateLineAreaData(seriesList, options) {
function updateLineAreaData(seriesList: any, options: any) {
// Apply "percent values" modification
updatePercentValues(seriesList, options);
if (options.series.stacking) {
@@ -176,7 +181,9 @@ function updateLineAreaData(seriesList, options) {
return null;
}
const x = series.x[i];
// @ts-expect-error ts-migrate(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
const stackedY = y + (cumulativeValues[x] || 0.0);
// @ts-expect-error ts-migrate(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
cumulativeValues[x] = stackedY;
return stackedY;
});
@@ -191,7 +198,7 @@ function updateLineAreaData(seriesList, options) {
updateSeriesText(seriesList, options);
}
function updateDefaultData(seriesList, options) {
function updateDefaultData(seriesList: any, options: any) {
// Apply "percent values" modification
updatePercentValues(seriesList, options);
@@ -205,7 +212,7 @@ function updateDefaultData(seriesList, options) {
updateSeriesText(seriesList, options);
}
export default function updateData(seriesList, options) {
export default function updateData(seriesList: any, options: any) {
// Use only visible series
const visibleSeriesList = filter(seriesList, s => s.visible === true);

View File

@@ -1,12 +1,13 @@
import { isUndefined } from "lodash";
import moment from "moment";
// @ts-expect-error ts-migrate(7016) FIXME: Could not find a declaration file for module 'plot... Remove this comment to see the full error message
import plotlyCleanNumber from "plotly.js/src/lib/clean_number";
export function cleanNumber(value) {
export function cleanNumber(value: any) {
return isUndefined(value) ? value : plotlyCleanNumber(value);
}
export function getSeriesAxis(series, options) {
export function getSeriesAxis(series: any, options: any) {
const seriesOptions = options.seriesOptions[series.name] || { type: options.globalSeriesType };
if (seriesOptions.yAxis === 1 && (!options.series.stacking || seriesOptions.type === "line")) {
return "y2";
@@ -14,7 +15,7 @@ export function getSeriesAxis(series, options) {
return "y";
}
export function normalizeValue(value, axisType, dateTimeFormat = "YYYY-MM-DD HH:mm:ss") {
export function normalizeValue(value: any, axisType: any, dateTimeFormat = "YYYY-MM-DD HH:mm:ss") {
if (axisType === "datetime" && moment.utc(value).isValid()) {
value = moment.utc(value);
}

View File

@@ -8,7 +8,10 @@ import { EditorPropTypes } from "@/visualizations/prop-types";
import useLoadGeoJson from "../hooks/useLoadGeoJson";
import { getGeoJsonBounds } from "./utils";
export default function BoundsSettings({ options, onOptionsChange }) {
export default function BoundsSettings({
options,
onOptionsChange
}: any) {
// Bounds may be changed in editor or on preview (by drag/zoom map).
// Changes from preview does not come frequently (only when user release mouse button),
// but changes from editor should be debounced.
@@ -51,42 +54,48 @@ export default function BoundsSettings({ options, onOptionsChange }) {
return (
<React.Fragment>
{/* @ts-expect-error ts-migrate(2745) FIXME: This JSX tag's 'children' prop expects type 'never... Remove this comment to see the full error message */}
<Section>
{/* @ts-expect-error ts-migrate(2322) FIXME: Type 'string' is not assignable to type 'null | un... Remove this comment to see the full error message */}
<ControlLabel label="North-East Latitude and Longitude">
{/* @ts-expect-error ts-migrate(2322) FIXME: Type 'Element' is not assignable to type 'null | u... Remove this comment to see the full error message */}
<Grid.Row gutter={15}>
<Grid.Col span={12}>
<InputNumber
disabled={!boundsAvailable}
value={boundsAvailable ? bounds[1][0] : undefined}
onChange={value => updateBounds(1, 0, value)}
onChange={(value: any) => updateBounds(1, 0, value)}
/>
</Grid.Col>
<Grid.Col span={12}>
<InputNumber
disabled={!boundsAvailable}
value={boundsAvailable ? bounds[1][1] : undefined}
onChange={value => updateBounds(1, 1, value)}
onChange={(value: any) => updateBounds(1, 1, value)}
/>
</Grid.Col>
</Grid.Row>
</ControlLabel>
</Section>
{/* @ts-expect-error ts-migrate(2745) FIXME: This JSX tag's 'children' prop expects type 'never... Remove this comment to see the full error message */}
<Section>
{/* @ts-expect-error ts-migrate(2322) FIXME: Type 'string' is not assignable to type 'null | un... Remove this comment to see the full error message */}
<ControlLabel label="South-West Latitude and Longitude">
{/* @ts-expect-error ts-migrate(2322) FIXME: Type 'Element' is not assignable to type 'null | u... Remove this comment to see the full error message */}
<Grid.Row gutter={15}>
<Grid.Col span={12}>
<InputNumber
disabled={!boundsAvailable}
value={boundsAvailable ? bounds[0][0] : undefined}
onChange={value => updateBounds(0, 0, value)}
onChange={(value: any) => updateBounds(0, 0, value)}
/>
</Grid.Col>
<Grid.Col span={12}>
<InputNumber
disabled={!boundsAvailable}
value={boundsAvailable ? bounds[0][1] : undefined}
onChange={value => updateBounds(0, 1, value)}
onChange={(value: any) => updateBounds(0, 1, value)}
/>
</Grid.Col>
</Grid.Row>

View File

@@ -4,30 +4,41 @@ import { Section, Select, InputNumber, ColorPicker } from "@/components/visualiz
import { EditorPropTypes } from "@/visualizations/prop-types";
import ColorPalette from "../ColorPalette";
export default function ColorsSettings({ options, onOptionsChange }) {
export default function ColorsSettings({
options,
onOptionsChange
}: any) {
const [onOptionsChangeDebounced] = useDebouncedCallback(onOptionsChange, 200);
return (
<React.Fragment>
{/* @ts-expect-error ts-migrate(2745) FIXME: This JSX tag's 'children' prop expects type 'never... Remove this comment to see the full error message */}
<Section>
<Select
layout="horizontal"
label="Clustering Mode"
data-test="Choropleth.Editor.ClusteringMode"
defaultValue={options.clusteringMode}
onChange={clusteringMode => onOptionsChange({ clusteringMode })}>
onChange={(clusteringMode: any) => onOptionsChange({ clusteringMode })}>
{/* @ts-expect-error ts-migrate(2339) FIXME: Property 'Option' does not exist on type '({ class... Remove this comment to see the full error message */}
<Select.Option value="q" data-test="Choropleth.Editor.ClusteringMode.q">
quantile
{/* @ts-expect-error ts-migrate(2339) FIXME: Property 'Option' does not exist on type '({ class... Remove this comment to see the full error message */}
</Select.Option>
{/* @ts-expect-error ts-migrate(2339) FIXME: Property 'Option' does not exist on type '({ class... Remove this comment to see the full error message */}
<Select.Option value="e" data-test="Choropleth.Editor.ClusteringMode.e">
equidistant
{/* @ts-expect-error ts-migrate(2339) FIXME: Property 'Option' does not exist on type '({ class... Remove this comment to see the full error message */}
</Select.Option>
{/* @ts-expect-error ts-migrate(2339) FIXME: Property 'Option' does not exist on type '({ class... Remove this comment to see the full error message */}
<Select.Option value="k" data-test="Choropleth.Editor.ClusteringMode.k">
k-means
{/* @ts-expect-error ts-migrate(2339) FIXME: Property 'Option' does not exist on type '({ class... Remove this comment to see the full error message */}
</Select.Option>
</Select>
</Section>
{/* @ts-expect-error ts-migrate(2745) FIXME: This JSX tag's 'children' prop expects type 'never... Remove this comment to see the full error message */}
<Section>
<InputNumber
layout="horizontal"
@@ -36,10 +47,11 @@ export default function ColorsSettings({ options, onOptionsChange }) {
min={3}
max={11}
defaultValue={options.steps}
onChange={steps => onOptionsChangeDebounced({ steps })}
onChange={(steps: any) => onOptionsChangeDebounced({ steps })}
/>
</Section>
{/* @ts-expect-error ts-migrate(2745) FIXME: This JSX tag's 'children' prop expects type 'never... Remove this comment to see the full error message */}
<Section>
<ColorPicker
layout="horizontal"
@@ -49,11 +61,13 @@ export default function ColorsSettings({ options, onOptionsChange }) {
placement="topRight"
color={options.colors.min}
triggerProps={{ "data-test": "Choropleth.Editor.Colors.Min" }}
onChange={min => onOptionsChange({ colors: { min } })}
onChange={(min: any) => onOptionsChange({ colors: { min } })}
// @ts-expect-error ts-migrate(2339) FIXME: Property 'Label' does not exist on type '({ classN... Remove this comment to see the full error message
addonAfter={<ColorPicker.Label color={options.colors.min} presetColors={ColorPalette} />}
/>
</Section>
{/* @ts-expect-error ts-migrate(2745) FIXME: This JSX tag's 'children' prop expects type 'never... Remove this comment to see the full error message */}
<Section>
<ColorPicker
layout="horizontal"
@@ -63,11 +77,13 @@ export default function ColorsSettings({ options, onOptionsChange }) {
placement="topRight"
color={options.colors.max}
triggerProps={{ "data-test": "Choropleth.Editor.Colors.Max" }}
onChange={max => onOptionsChange({ colors: { max } })}
onChange={(max: any) => onOptionsChange({ colors: { max } })}
// @ts-expect-error ts-migrate(2339) FIXME: Property 'Label' does not exist on type '({ classN... Remove this comment to see the full error message
addonAfter={<ColorPicker.Label color={options.colors.max} presetColors={ColorPalette} />}
/>
</Section>
{/* @ts-expect-error ts-migrate(2745) FIXME: This JSX tag's 'children' prop expects type 'never... Remove this comment to see the full error message */}
<Section>
<ColorPicker
layout="horizontal"
@@ -77,11 +93,13 @@ export default function ColorsSettings({ options, onOptionsChange }) {
placement="topRight"
color={options.colors.noValue}
triggerProps={{ "data-test": "Choropleth.Editor.Colors.NoValue" }}
onChange={noValue => onOptionsChange({ colors: { noValue } })}
onChange={(noValue: any) => onOptionsChange({ colors: { noValue } })}
// @ts-expect-error ts-migrate(2339) FIXME: Property 'Label' does not exist on type '({ classN... Remove this comment to see the full error message
addonAfter={<ColorPicker.Label color={options.colors.noValue} presetColors={ColorPalette} />}
/>
</Section>
{/* @ts-expect-error ts-migrate(2745) FIXME: This JSX tag's 'children' prop expects type 'never... Remove this comment to see the full error message */}
<Section>
<ColorPicker
layout="horizontal"
@@ -91,11 +109,13 @@ export default function ColorsSettings({ options, onOptionsChange }) {
placement="topRight"
color={options.colors.background}
triggerProps={{ "data-test": "Choropleth.Editor.Colors.Background" }}
onChange={background => onOptionsChange({ colors: { background } })}
onChange={(background: any) => onOptionsChange({ colors: { background } })}
// @ts-expect-error ts-migrate(2339) FIXME: Property 'Label' does not exist on type '({ classN... Remove this comment to see the full error message
addonAfter={<ColorPicker.Label color={options.colors.background} presetColors={ColorPalette} />}
/>
</Section>
{/* @ts-expect-error ts-migrate(2745) FIXME: This JSX tag's 'children' prop expects type 'never... Remove this comment to see the full error message */}
<Section>
<ColorPicker
layout="horizontal"
@@ -105,7 +125,8 @@ export default function ColorsSettings({ options, onOptionsChange }) {
placement="topRight"
color={options.colors.borders}
triggerProps={{ "data-test": "Choropleth.Editor.Colors.Borders" }}
onChange={borders => onOptionsChange({ colors: { borders } })}
onChange={(borders: any) => onOptionsChange({ colors: { borders } })}
// @ts-expect-error ts-migrate(2339) FIXME: Property 'Label' does not exist on type '({ classN... Remove this comment to see the full error message
addonAfter={<ColorPicker.Label color={options.colors.borders} presetColors={ColorPalette} />}
/>
</Section>

View File

@@ -1,6 +1,5 @@
import { map } from "lodash";
import React, { useMemo } from "react";
import PropTypes from "prop-types";
import { useDebouncedCallback } from "use-debounce";
import * as Grid from "antd/lib/grid";
import {
@@ -17,8 +16,15 @@ import { EditorPropTypes } from "@/visualizations/prop-types";
import useLoadGeoJson from "../hooks/useLoadGeoJson";
import { getGeoJsonFields } from "./utils";
function TemplateFormatHint({ geoJsonProperties }) {
type OwnTemplateFormatHintProps = {
geoJsonProperties?: string[];
};
type TemplateFormatHintProps = OwnTemplateFormatHintProps & typeof TemplateFormatHint.defaultProps;
function TemplateFormatHint({ geoJsonProperties }: TemplateFormatHintProps) {
return (
// @ts-expect-error ts-migrate(2746) FIXME: This JSX tag's 'children' prop expects a single ch... Remove this comment to see the full error message
<ContextHelp placement="topLeft" arrowPointAtCenter>
<div style={{ paddingBottom: 5 }}>
<div>
@@ -44,15 +50,14 @@ function TemplateFormatHint({ geoJsonProperties }) {
);
}
TemplateFormatHint.propTypes = {
geoJsonProperties: PropTypes.arrayOf(PropTypes.string),
};
TemplateFormatHint.defaultProps = {
geoJsonProperties: [],
};
export default function GeneralSettings({ options, onOptionsChange }) {
export default function GeneralSettings({
options,
onOptionsChange
}: any) {
const [onOptionsChangeDebounced] = useDebouncedCallback(onOptionsChange, 200);
const [geoJson] = useLoadGeoJson(options.mapType);
const geoJsonFields = useMemo(() => getGeoJsonFields(geoJson), [geoJson]);
@@ -61,6 +66,7 @@ export default function GeneralSettings({ options, onOptionsChange }) {
return (
<div className="choropleth-visualization-editor-format-settings">
{/* @ts-expect-error ts-migrate(2745) FIXME: This JSX tag's 'children' prop expects type 'never... Remove this comment to see the full error message */}
<Section>
<Grid.Row gutter={15}>
<Grid.Col span={12}>
@@ -73,7 +79,7 @@ export default function GeneralSettings({ options, onOptionsChange }) {
}
data-test="Choropleth.Editor.ValueFormat"
defaultValue={options.valueFormat}
onChange={event => onOptionsChangeDebounced({ valueFormat: event.target.value })}
onChange={(event: any) => onOptionsChangeDebounced({ valueFormat: event.target.value })}
/>
</Grid.Col>
<Grid.Col span={12}>
@@ -81,12 +87,13 @@ export default function GeneralSettings({ options, onOptionsChange }) {
label="Value Placeholder"
data-test="Choropleth.Editor.ValuePlaceholder"
defaultValue={options.noValuePlaceholder}
onChange={event => onOptionsChangeDebounced({ noValuePlaceholder: event.target.value })}
onChange={(event: any) => onOptionsChangeDebounced({ noValuePlaceholder: event.target.value })}
/>
</Grid.Col>
</Grid.Row>
</Section>
{/* @ts-expect-error ts-migrate(2745) FIXME: This JSX tag's 'children' prop expects type 'never... Remove this comment to see the full error message */}
<Section>
<Checkbox
data-test="Choropleth.Editor.LegendVisibility"
@@ -96,6 +103,7 @@ export default function GeneralSettings({ options, onOptionsChange }) {
</Checkbox>
</Section>
{/* @ts-expect-error ts-migrate(2745) FIXME: This JSX tag's 'children' prop expects type 'never... Remove this comment to see the full error message */}
<Section>
<Grid.Row gutter={15}>
<Grid.Col span={12}>
@@ -104,18 +112,26 @@ export default function GeneralSettings({ options, onOptionsChange }) {
data-test="Choropleth.Editor.LegendPosition"
disabled={!options.legend.visible}
defaultValue={options.legend.position}
onChange={position => onOptionsChange({ legend: { position } })}>
onChange={(position: any) => onOptionsChange({ legend: { position } })}>
{/* @ts-expect-error ts-migrate(2339) FIXME: Property 'Option' does not exist on type '({ class... Remove this comment to see the full error message */}
<Select.Option value="top-left" data-test="Choropleth.Editor.LegendPosition.TopLeft">
top / left
{/* @ts-expect-error ts-migrate(2339) FIXME: Property 'Option' does not exist on type '({ class... Remove this comment to see the full error message */}
</Select.Option>
{/* @ts-expect-error ts-migrate(2339) FIXME: Property 'Option' does not exist on type '({ class... Remove this comment to see the full error message */}
<Select.Option value="top-right" data-test="Choropleth.Editor.LegendPosition.TopRight">
top / right
{/* @ts-expect-error ts-migrate(2339) FIXME: Property 'Option' does not exist on type '({ class... Remove this comment to see the full error message */}
</Select.Option>
{/* @ts-expect-error ts-migrate(2339) FIXME: Property 'Option' does not exist on type '({ class... Remove this comment to see the full error message */}
<Select.Option value="bottom-left" data-test="Choropleth.Editor.LegendPosition.BottomLeft">
bottom / left
{/* @ts-expect-error ts-migrate(2339) FIXME: Property 'Option' does not exist on type '({ class... Remove this comment to see the full error message */}
</Select.Option>
{/* @ts-expect-error ts-migrate(2339) FIXME: Property 'Option' does not exist on type '({ class... Remove this comment to see the full error message */}
<Select.Option value="bottom-right" data-test="Choropleth.Editor.LegendPosition.BottomRight">
bottom / right
{/* @ts-expect-error ts-migrate(2339) FIXME: Property 'Option' does not exist on type '({ class... Remove this comment to see the full error message */}
</Select.Option>
</Select>
</Grid.Col>
@@ -125,12 +141,13 @@ export default function GeneralSettings({ options, onOptionsChange }) {
label="Legend Text Alignment"
disabled={!options.legend.visible}
defaultValue={options.legend.alignText}
onChange={event => onOptionsChange({ legend: { alignText: event.target.value } })}
onChange={(event: any) => onOptionsChange({ legend: { alignText: event.target.value } })}
/>
</Grid.Col>
</Grid.Row>
</Section>
{/* @ts-expect-error ts-migrate(2745) FIXME: This JSX tag's 'children' prop expects type 'never... Remove this comment to see the full error message */}
<Section>
<Checkbox
data-test="Choropleth.Editor.TooltipEnabled"
@@ -140,16 +157,18 @@ export default function GeneralSettings({ options, onOptionsChange }) {
</Checkbox>
</Section>
{/* @ts-expect-error ts-migrate(2745) FIXME: This JSX tag's 'children' prop expects type 'never... Remove this comment to see the full error message */}
<Section>
<Input
label={<React.Fragment>Tooltip Template {templateFormatHint}</React.Fragment>}
data-test="Choropleth.Editor.TooltipTemplate"
disabled={!options.tooltip.enabled}
defaultValue={options.tooltip.template}
onChange={event => onOptionsChangeDebounced({ tooltip: { template: event.target.value } })}
onChange={(event: any) => onOptionsChangeDebounced({ tooltip: { template: event.target.value } })}
/>
</Section>
{/* @ts-expect-error ts-migrate(2745) FIXME: This JSX tag's 'children' prop expects type 'never... Remove this comment to see the full error message */}
<Section>
<Checkbox
data-test="Choropleth.Editor.PopupEnabled"
@@ -159,6 +178,7 @@ export default function GeneralSettings({ options, onOptionsChange }) {
</Checkbox>
</Section>
{/* @ts-expect-error ts-migrate(2745) FIXME: This JSX tag's 'children' prop expects type 'never... Remove this comment to see the full error message */}
<Section>
<TextArea
label={<React.Fragment>Popup Template {templateFormatHint}</React.Fragment>}
@@ -166,7 +186,7 @@ export default function GeneralSettings({ options, onOptionsChange }) {
disabled={!options.popup.enabled}
rows={4}
defaultValue={options.popup.template}
onChange={event => onOptionsChangeDebounced({ popup: { template: event.target.value } })}
onChange={(event: any) => onOptionsChangeDebounced({ popup: { template: event.target.value } })}
/>
</Section>
</div>

Some files were not shown because too many files have changed in this diff Show More