diff --git a/.gitignore b/.gitignore
index b044fc2c8..d2a57a1fe 100644
--- a/.gitignore
+++ b/.gitignore
@@ -18,3 +18,4 @@ application-dev-localhost.yaml
server/api-service/lowcoder-server/src/main/resources/application-local-dev.yaml
translations/locales/node_modules/
server/api-service/lowcoder-server/src/main/resources/application-local-dev-ee.yaml
+node_modules
diff --git a/README.md b/README.md
index 6ba2fff86..ede4bcc29 100644
--- a/README.md
+++ b/README.md
@@ -7,15 +7,22 @@
Create software applications (internal and customer-facing!) and Meeting/Collaboration tools for your Company and your Customers with minimal coding experience.
- Lowcoder is the best Retool, Appsmith or Tooljet Alternative.
+ We think, Lowcoder is simply better than Retool, Appsmith Tooljet, Outsystems or Mendix.
+---
-
-
+## 🎥 Lowcoder Intro Video
+
+
+
+
+
Click the image above to watch the video on YouTube 📺
+
+---
## 📢 Use Lowcoder in 3 steps
1. Connect to any data sources or APIs.
-2. Build flexible and responsive UI with 100+ components and free layout / design possibilities.
+2. Build flexible and responsive UI with 120+ components and free layout / design possibilities.
3. Share with colleagues and customers.
## 💡 Why Lowcoder
@@ -23,9 +30,9 @@ One platform for everything instead so many different softwares. (like Website B
It's cumbersome to create a single app. You had to design user interfaces, write code in multiple languages and frameworks, and understand how all of that code works together.
-NewGen Lowcode Platforms like Retool and others are great for their simplicity and flexibility - like Lowcoder too, but they can also be limited in different ways, especially when it comes to "external" applications for everyone.
+NewGen Lowcode Platforms like Retool and others are great for their simplicity and flexibility - like Lowcoder too, but they can also be limited in different ways, especially when it comes to "external" applications for everyone - because their pricing focusses to internal apps and "pay per User".
-Lowcoder wants to take a step forward. More specifically, Lowcoder is:
+With Lowcoder we did a step forward. More specifically, Lowcoder is:
- An all-in-one IDE to create internal or customer-facing (external) apps.
- A place to create, build and share building blocks of web applications and whole websites.
- The tool and community to support your business, and lower the cost and time to develop interactive applications.
@@ -34,9 +41,9 @@ Lowcoder wants to take a step forward. More specifically, Lowcoder is:
- The only platform which has extensibility plugin architecture [Check Community Contributions](https://www.npmjs.com/search?q=lowcoder-comp)
## 🪄 Features
-- **Visual UI builder** with 100+ built-in components. Save 90% of time to build apps.
+- **Visual UI builder** with 120+ built-in components. Save 90% of time to build apps.
- **Modules** for reusable (!) embedable component sets in the UI builder.
-- **Embed Lowcoder Apps as native parts of any Website** instead of iFrame (!). [Demo](https://lowcoder.cloud/about), [Docu](https://docs.lowcoder.cloud/lowcoder-documentation/lowcoder-extension/native-embed-sdk)
+- **Embed Lowcoder Apps as native parts of any Website** instead of iFrame (!). [Demo](http://demo-lowcoder.42web.io/ecommerce/), [Docu](https://docs.lowcoder.cloud/lowcoder-documentation/lowcoder-extension/native-embed-sdk)
- **Video Meeting Components** to create your own individual Web-Meeting tool.
- **Query Library** for reusable data queries of your data sources.
- **Custom components** to develop own components and use them in the UI builder.
@@ -107,7 +114,3 @@ Accelerate the growth of Lowcoder and unleash its potential with your Sponsorshi
[Be a Sponsor](https://github.com/sponsors/lowcoder-org)
Like ... [@Darkjamin](https://github.com/Darkjamin), [@spacegoats-io](https://github.com/spacegoats-io), [@Jomedya](https://github.com/Jomedya), [@CHSchuepfer](https://github.com/CHSchuepfer), Thank you very much!!
-
-## Intro Video
-
-[](https://youtu.be/s4ltAqS0hzM?feature=shared)
diff --git a/client/VERSION b/client/VERSION
index bd4053bfb..e46a05b19 100644
--- a/client/VERSION
+++ b/client/VERSION
@@ -1 +1 @@
-2.6.3
\ No newline at end of file
+2.6.4
\ No newline at end of file
diff --git a/client/config/test/transform/babelTransform.js b/client/config/test/transform/babelTransform.js
index 703cac21a..36f6cf0d8 100644
--- a/client/config/test/transform/babelTransform.js
+++ b/client/config/test/transform/babelTransform.js
@@ -8,6 +8,13 @@ export default babelJest.createTransformer({
runtime: "automatic",
},
],
+ [
+ "babel-preset-vite",
+ {
+ "env": true,
+ "glob": false
+ }
+ ]
],
babelrc: false,
configFile: false,
diff --git a/client/package.json b/client/package.json
index e84c1dbea..f8a736710 100644
--- a/client/package.json
+++ b/client/package.json
@@ -1,6 +1,6 @@
{
"name": "lowcoder-frontend",
- "version": "2.6.3",
+ "version": "2.6.4",
"type": "module",
"private": true,
"workspaces": [
@@ -43,6 +43,7 @@
"add": "^2.0.6",
"babel-jest": "^29.3.0",
"babel-preset-react-app": "^10.0.1",
+ "babel-preset-vite": "^1.1.3",
"husky": "^8.0.1",
"jest": "^29.5.0",
"jest-canvas-mock": "^2.5.2",
diff --git a/client/packages/lowcoder-cli/actions/build.js b/client/packages/lowcoder-cli/actions/build.js
index 04e754e99..7ed38e8f5 100644
--- a/client/packages/lowcoder-cli/actions/build.js
+++ b/client/packages/lowcoder-cli/actions/build.js
@@ -3,6 +3,7 @@ import fsExtra from "fs-extra";
import { build } from "vite";
import { writeFileSync, existsSync, readFileSync, readdirSync } from "fs";
import { resolve } from "path";
+import { pathToFileURL } from "url";
import paths from "../config/paths.js";
import "../util/log.js";
import chalk from "chalk";
@@ -80,7 +81,9 @@ export default async function buildAction(options) {
console.log("");
console.cyan("Building...");
- const viteConfig = await import(paths.appViteConfigJs).default;
+ const viteConfigURL = pathToFileURL(paths.appViteConfigJs);
+ const viteConfig = await import(viteConfigURL).default;
+ console.log(paths.appViteConfigJs);
await build(viteConfig);
// write package.json
diff --git a/client/packages/lowcoder-comps/package.json b/client/packages/lowcoder-comps/package.json
index 7cf6fc1af..4fb56a02f 100644
--- a/client/packages/lowcoder-comps/package.json
+++ b/client/packages/lowcoder-comps/package.json
@@ -1,6 +1,6 @@
{
"name": "lowcoder-comps",
- "version": "2.6.3",
+ "version": "2.6.5",
"type": "module",
"license": "MIT",
"dependencies": {
@@ -23,6 +23,7 @@
"agora-rtm-sdk": "^1.5.1",
"big.js": "^6.2.1",
"echarts-extension-gmap": "^1.6.0",
+ "echarts-gl": "^2.0.9",
"echarts-wordcloud": "^2.1.0",
"lowcoder-cli": "workspace:^",
"lowcoder-sdk": "workspace:^",
@@ -58,6 +59,62 @@
"h": 40
}
},
+ "barChart": {
+ "name": "Bar Chart",
+ "icon": "./icons/icon-chart.svg",
+ "layoutInfo": {
+ "w": 12,
+ "h": 40
+ }
+ },
+ "lineChart": {
+ "name": "Line Chart",
+ "icon": "./icons/icon-chart.svg",
+ "layoutInfo": {
+ "w": 12,
+ "h": 40
+ }
+ },
+ "pieChart": {
+ "name": "Pie Chart",
+ "icon": "./icons/icon-chart.svg",
+ "layoutInfo": {
+ "w": 12,
+ "h": 40
+ }
+ },
+ "scatterChart": {
+ "name": "Scatter Chart",
+ "icon": "./icons/icon-chart.svg",
+ "layoutInfo": {
+ "w": 12,
+ "h": 40
+ }
+ },
+ "boxplotChart": {
+ "name": "Boxplot Chart",
+ "icon": "./icons/icon-chart.svg",
+ "layoutInfo": {
+ "w": 12,
+ "h": 40
+ }
+ },
+ "parallelChart": {
+ "name": "Parallel Chart",
+ "icon": "./icons/icon-chart.svg",
+ "layoutInfo": {
+ "w": 12,
+ "h": 40
+ }
+ },
+ "line3dChart": {
+ "name": "Line3D Chart",
+ "icon": "./icons/icon-chart.svg",
+ "layoutInfo": {
+ "w": 12,
+ "h": 40
+ }
+ },
"imageEditor": {
"name": "Image Editor",
"icon": "./icons/icon-chart.svg",
diff --git a/client/packages/lowcoder-comps/src/comps/barChartComp/barChartComp.tsx b/client/packages/lowcoder-comps/src/comps/barChartComp/barChartComp.tsx
new file mode 100644
index 000000000..e13818586
--- /dev/null
+++ b/client/packages/lowcoder-comps/src/comps/barChartComp/barChartComp.tsx
@@ -0,0 +1,320 @@
+import {
+ changeChildAction,
+ changeValueAction,
+ CompAction,
+ CompActionTypes,
+ wrapChildAction,
+} from "lowcoder-core";
+import { AxisFormatterComp, EchartsAxisType } from "../basicChartComp/chartConfigs/cartesianAxisConfig";
+import { barChartChildrenMap, ChartSize, getDataKeys } from "./barChartConstants";
+import { barChartPropertyView } from "./barChartPropertyView";
+import _ from "lodash";
+import { useContext, useEffect, useMemo, useRef, useState } from "react";
+import ReactResizeDetector from "react-resize-detector";
+import ReactECharts from "../basicChartComp/reactEcharts";
+import {
+ childrenToProps,
+ depsConfig,
+ genRandomKey,
+ NameConfig,
+ UICompBuilder,
+ withDefault,
+ withExposingConfigs,
+ withViewFn,
+ ThemeContext,
+ chartColorPalette,
+ getPromiseAfterDispatch,
+ dropdownControl,
+ JSONObject,
+} from "lowcoder-sdk";
+import { getEchartsLocale, trans } from "i18n/comps";
+import { ItemColorComp } from "comps/basicChartComp/chartConfigs/lineChartConfig";
+import {
+ echartsConfigOmitChildren,
+ getEchartsConfig,
+ getSelectedPoints,
+} from "./barChartUtils";
+import 'echarts-extension-gmap';
+import log from "loglevel";
+
+let clickEventCallback = () => {};
+
+const chartModeOptions = [
+ {
+ label: "ECharts JSON",
+ value: "json",
+ }
+] as const;
+
+let BarChartTmpComp = (function () {
+ return new UICompBuilder({mode:dropdownControl(chartModeOptions,'ui'),...barChartChildrenMap}, () => null)
+ .setPropertyViewFn(barChartPropertyView)
+ .build();
+})();
+
+BarChartTmpComp = withViewFn(BarChartTmpComp, (comp) => {
+ const mode = comp.children.mode.getView();
+ const onUIEvent = comp.children.onUIEvent.getView();
+ const onEvent = comp.children.onEvent.getView();
+ const echartsCompRef = useRef();
+ const [chartSize, setChartSize] = useState();
+ const firstResize = useRef(true);
+ const theme = useContext(ThemeContext);
+ const defaultChartTheme = {
+ color: chartColorPalette,
+ backgroundColor: "#fff",
+ };
+
+ let themeConfig = defaultChartTheme;
+ try {
+ themeConfig = theme?.theme.chart ? JSON.parse(theme?.theme.chart) : defaultChartTheme;
+ } catch (error) {
+ log.error('theme chart error: ', error);
+ }
+
+ const triggerClickEvent = async (dispatch: any, action: CompAction) => {
+ await getPromiseAfterDispatch(
+ dispatch,
+ action,
+ { autoHandleAfterReduce: true }
+ );
+ onEvent('click');
+ }
+
+ useEffect(() => {
+ const echartsCompInstance = echartsCompRef?.current?.getEchartsInstance();
+ if (!echartsCompInstance) {
+ return _.noop;
+ }
+ echartsCompInstance?.on("click", (param: any) => {
+ document.dispatchEvent(new CustomEvent("clickEvent", {
+ bubbles: true,
+ detail: {
+ action: 'click',
+ data: param.data,
+ }
+ }));
+ triggerClickEvent(
+ comp.dispatch,
+ changeChildAction("lastInteractionData", param.data, false)
+ );
+ });
+ return () => {
+ echartsCompInstance?.off("click");
+ document.removeEventListener('clickEvent', clickEventCallback)
+ };
+ }, []);
+
+ useEffect(() => {
+ // bind events
+ const echartsCompInstance = echartsCompRef?.current?.getEchartsInstance();
+ if (!echartsCompInstance) {
+ return _.noop;
+ }
+ echartsCompInstance?.on("selectchanged", (param: any) => {
+ const option: any = echartsCompInstance?.getOption();
+ document.dispatchEvent(new CustomEvent("clickEvent", {
+ bubbles: true,
+ detail: {
+ action: param.fromAction,
+ data: getSelectedPoints(param, option)
+ }
+ }));
+
+ if (param.fromAction === "select") {
+ comp.dispatch(changeChildAction("selectedPoints", getSelectedPoints(param, option), false));
+ onUIEvent("select");
+ } else if (param.fromAction === "unselect") {
+ comp.dispatch(changeChildAction("selectedPoints", getSelectedPoints(param, option), false));
+ onUIEvent("unselect");
+ }
+
+ triggerClickEvent(
+ comp.dispatch,
+ changeChildAction("lastInteractionData", getSelectedPoints(param, option), false)
+ );
+ });
+ // unbind
+ return () => {
+ echartsCompInstance?.off("selectchanged");
+ document.removeEventListener('clickEvent', clickEventCallback)
+ };
+ }, [onUIEvent]);
+
+ const echartsConfigChildren = _.omit(comp.children, echartsConfigOmitChildren);
+ const childrenProps = childrenToProps(echartsConfigChildren);
+ const option = useMemo(() => {
+ return getEchartsConfig(
+ childrenProps as ToViewReturn,
+ chartSize,
+ themeConfig
+ );
+ }, [theme, childrenProps, chartSize, ...Object.values(echartsConfigChildren)]);
+
+ useEffect(() => {
+ comp.children.mapInstance.dispatch(changeValueAction(null, false))
+ if(comp.children.mapInstance.value) return;
+ }, [option])
+
+ return (
+ {
+ if (w && h) {
+ setChartSize({ w: w, h: h });
+ }
+ if (!firstResize.current) {
+ // ignore the first resize, which will impact the loading animation
+ echartsCompRef.current?.getEchartsInstance().resize();
+ } else {
+ firstResize.current = false;
+ }
+ }}
+ >
+ (echartsCompRef.current = e)}
+ style={{ height: "100%" }}
+ notMerge
+ lazyUpdate
+ opts={{ locale: getEchartsLocale() }}
+ option={option}
+ mode={mode}
+ />
+
+ );
+});
+
+function getYAxisFormatContextValue(
+ data: Array,
+ yAxisType: EchartsAxisType,
+ yAxisName?: string
+) {
+ const dataSample = yAxisName && data.length > 0 && data[0][yAxisName];
+ let contextValue = dataSample;
+ if (yAxisType === "time") {
+ // to timestamp
+ const time =
+ typeof dataSample === "number" || typeof dataSample === "string"
+ ? new Date(dataSample).getTime()
+ : null;
+ if (time) contextValue = time;
+ }
+ return contextValue;
+}
+
+BarChartTmpComp = class extends BarChartTmpComp {
+ private lastYAxisFormatContextVal?: JSONValue;
+ private lastColorContext?: JSONObject;
+
+ updateContext(comp: this) {
+ // the context value of axis format
+ let resultComp = comp;
+ const data = comp.children.data.getView();
+ const sampleSeries = comp.children.series.getView().find((s) => !s.getView().hide);
+ const yAxisContextValue = getYAxisFormatContextValue(
+ data,
+ comp.children.yConfig.children.yAxisType.getView(),
+ sampleSeries?.children.columnName.getView()
+ );
+ if (yAxisContextValue !== comp.lastYAxisFormatContextVal) {
+ comp.lastYAxisFormatContextVal = yAxisContextValue;
+ resultComp = comp.setChild(
+ "yConfig",
+ comp.children.yConfig.reduce(
+ wrapChildAction(
+ "formatter",
+ AxisFormatterComp.changeContextDataAction({ value: yAxisContextValue })
+ )
+ )
+ );
+ }
+ // item color context
+ const colorContextVal = {
+ seriesName: sampleSeries?.children.seriesName.getView(),
+ value: yAxisContextValue,
+ };
+ if (
+ comp.children.chartConfig.children.comp.children.hasOwnProperty("itemColor") &&
+ !_.isEqual(colorContextVal, comp.lastColorContext)
+ ) {
+ comp.lastColorContext = colorContextVal;
+ resultComp = resultComp.setChild(
+ "chartConfig",
+ comp.children.chartConfig.reduce(
+ wrapChildAction(
+ "comp",
+ wrapChildAction("itemColor", ItemColorComp.changeContextDataAction(colorContextVal))
+ )
+ )
+ );
+ }
+ return resultComp;
+ }
+
+ override reduce(action: CompAction): this {
+ const comp = super.reduce(action);
+ if (action.type === CompActionTypes.UPDATE_NODES_V2) {
+ const newData = comp.children.data.getView();
+ // data changes
+ if (comp.children.data !== this.children.data) {
+ setTimeout(() => {
+ // update x-axis value
+ const keys = getDataKeys(newData);
+ if (keys.length > 0 && !keys.includes(comp.children.xAxisKey.getView())) {
+ comp.children.xAxisKey.dispatch(changeValueAction(keys[0] || ""));
+ }
+ // pass to child series comp
+ comp.children.series.dispatchDataChanged(newData);
+ }, 0);
+ }
+ return this.updateContext(comp);
+ }
+ return comp;
+ }
+
+ override autoHeight(): boolean {
+ return false;
+ }
+};
+
+let BarChartComp = withExposingConfigs(BarChartTmpComp, [
+ depsConfig({
+ name: "selectedPoints",
+ desc: trans("chart.selectedPointsDesc"),
+ depKeys: ["selectedPoints"],
+ func: (input) => {
+ return input.selectedPoints;
+ },
+ }),
+ depsConfig({
+ name: "lastInteractionData",
+ desc: trans("chart.lastInteractionDataDesc"),
+ depKeys: ["lastInteractionData"],
+ func: (input) => {
+ return input.lastInteractionData;
+ },
+ }),
+ depsConfig({
+ name: "data",
+ desc: trans("chart.dataDesc"),
+ depKeys: ["data", "mode"],
+ func: (input) =>[] ,
+ }),
+ new NameConfig("title", trans("chart.titleDesc")),
+]);
+
+
+export const BarChartCompWithDefault = withDefault(BarChartComp, {
+ xAxisKey: "date",
+ series: [
+ {
+ dataIndex: genRandomKey(),
+ seriesName: trans("chart.spending"),
+ columnName: "spending",
+ },
+ {
+ dataIndex: genRandomKey(),
+ seriesName: trans("chart.budget"),
+ columnName: "budget",
+ },
+ ],
+});
diff --git a/client/packages/lowcoder-comps/src/comps/barChartComp/barChartConstants.tsx b/client/packages/lowcoder-comps/src/comps/barChartComp/barChartConstants.tsx
new file mode 100644
index 000000000..668b569be
--- /dev/null
+++ b/client/packages/lowcoder-comps/src/comps/barChartComp/barChartConstants.tsx
@@ -0,0 +1,323 @@
+import {
+ jsonControl,
+ JSONObject,
+ stateComp,
+ toJSONObjectArray,
+ toObject,
+ BoolControl,
+ withDefault,
+ StringControl,
+ NumberControl,
+ FunctionControl,
+ dropdownControl,
+ eventHandlerControl,
+ valueComp,
+ withType,
+ uiChildren,
+ clickEvent,
+ styleControl,
+ EchartDefaultTextStyle,
+ EchartDefaultChartStyle,
+ toArray
+} from "lowcoder-sdk";
+import { RecordConstructorToComp, RecordConstructorToView } from "lowcoder-core";
+import { BarChartConfig } from "../basicChartComp/chartConfigs/barChartConfig";
+import { XAxisConfig, YAxisConfig } from "../basicChartComp/chartConfigs/cartesianAxisConfig";
+import { LegendConfig } from "../basicChartComp/chartConfigs/legendConfig";
+import { EchartsLegendConfig } from "../basicChartComp/chartConfigs/echartsLegendConfig";
+import { EchartsLabelConfig } from "../basicChartComp/chartConfigs/echartsLabelConfig";
+import { LineChartConfig } from "../basicChartComp/chartConfigs/lineChartConfig";
+import { PieChartConfig } from "../basicChartComp/chartConfigs/pieChartConfig";
+import { ScatterChartConfig } from "../basicChartComp/chartConfigs/scatterChartConfig";
+import { SeriesListComp } from "./seriesComp";
+import { EChartsOption } from "echarts";
+import { i18nObjs, trans } from "i18n/comps";
+import { GaugeChartConfig } from "../basicChartComp/chartConfigs/gaugeChartConfig";
+import { FunnelChartConfig } from "../basicChartComp/chartConfigs/funnelChartConfig";
+import {EchartsTitleVerticalConfig} from "../chartComp/chartConfigs/echartsTitleVerticalConfig";
+import {EchartsTitleConfig} from "../basicChartComp/chartConfigs/echartsTitleConfig";
+
+export const ChartTypeOptions = [
+ {
+ label: trans("chart.bar"),
+ value: "bar",
+ },
+ {
+ label: trans("chart.line"),
+ value: "line",
+ },
+ {
+ label: trans("chart.scatter"),
+ value: "scatter",
+ },
+ {
+ label: trans("chart.pie"),
+ value: "pie",
+ },
+] as const;
+
+export const UIEventOptions = [
+ {
+ label: trans("chart.select"),
+ value: "select",
+ description: trans("chart.selectDesc"),
+ },
+ {
+ label: trans("chart.unSelect"),
+ value: "unselect",
+ description: trans("chart.unselectDesc"),
+ },
+] as const;
+
+export const MapEventOptions = [
+ {
+ label: trans("chart.mapReady"),
+ value: "mapReady",
+ description: trans("chart.mapReadyDesc"),
+ },
+ {
+ label: trans("chart.zoomLevelChange"),
+ value: "zoomLevelChange",
+ description: trans("chart.zoomLevelChangeDesc"),
+ },
+ {
+ label: trans("chart.centerPositionChange"),
+ value: "centerPositionChange",
+ description: trans("chart.centerPositionChangeDesc"),
+ },
+] as const;
+
+export const XAxisDirectionOptions = [
+ {
+ label: trans("chart.horizontal"),
+ value: "horizontal",
+ },
+ {
+ label: trans("chart.vertical"),
+ value: "vertical",
+ },
+] as const;
+
+export type XAxisDirectionType = ValueFromOption;
+
+export const noDataAxisConfig = {
+ animation: false,
+ xAxis: {
+ type: "category",
+ name: trans("chart.noData"),
+ nameLocation: "middle",
+ data: [],
+ axisLine: {
+ lineStyle: {
+ color: "#8B8FA3",
+ },
+ },
+ },
+ yAxis: {
+ type: "value",
+ axisLabel: {
+ color: "#8B8FA3",
+ },
+ splitLine: {
+ lineStyle: {
+ color: "#F0F0F0",
+ },
+ },
+ },
+ tooltip: {
+ show: false,
+ },
+ series: [
+ {
+ data: [700],
+ type: "line",
+ itemStyle: {
+ opacity: 0,
+ },
+ },
+ ],
+} as EChartsOption;
+
+export const noDataPieChartConfig = {
+ animation: false,
+ tooltip: {
+ show: false,
+ },
+ legend: {
+ formatter: trans("chart.unknown"),
+ top: "bottom",
+ selectedMode: false,
+ },
+ color: ["#B8BBCC", "#CED0D9", "#DCDEE6", "#E6E6EB"],
+ series: [
+ {
+ type: "pie",
+ radius: "35%",
+ center: ["25%", "50%"],
+ silent: true,
+ label: {
+ show: false,
+ },
+ data: [
+ {
+ name: "1",
+ value: 70,
+ },
+ {
+ name: "2",
+ value: 68,
+ },
+ {
+ name: "3",
+ value: 48,
+ },
+ {
+ name: "4",
+ value: 40,
+ },
+ ],
+ },
+ {
+ type: "pie",
+ radius: "35%",
+ center: ["75%", "50%"],
+ silent: true,
+ label: {
+ show: false,
+ },
+ data: [
+ {
+ name: "1",
+ value: 70,
+ },
+ {
+ name: "2",
+ value: 68,
+ },
+ {
+ name: "3",
+ value: 48,
+ },
+ {
+ name: "4",
+ value: 40,
+ },
+ ],
+ },
+ ],
+} as EChartsOption;
+
+export type ChartSize = { w: number; h: number };
+
+export const getDataKeys = (data: Array) => {
+ if (!data) {
+ return [];
+ }
+ const dataKeys: Array = [];
+ data.slice(0, 50).forEach((d) => {
+ Object.keys(d).forEach((key) => {
+ if (!dataKeys.includes(key)) {
+ dataKeys.push(key);
+ }
+ });
+ });
+ return dataKeys;
+};
+
+const ChartOptionMap = {
+ bar: BarChartConfig,
+ line: LineChartConfig,
+ pie: PieChartConfig,
+ scatter: ScatterChartConfig,
+};
+
+const EchartsOptionMap = {
+ funnel: FunnelChartConfig,
+ gauge: GaugeChartConfig,
+};
+
+const ChartOptionComp = withType(ChartOptionMap, "bar");
+const EchartsOptionComp = withType(EchartsOptionMap, "funnel");
+export type CharOptionCompType = keyof typeof ChartOptionMap;
+
+export const chartUiModeChildren = {
+ title: withDefault(StringControl, trans("echarts.defaultTitle")),
+ data: jsonControl(toJSONObjectArray, i18nObjs.defaultDataSource),
+ xAxisKey: valueComp(""), // x-axis, key from data
+ xAxisDirection: dropdownControl(XAxisDirectionOptions, "horizontal"),
+ xAxisData: jsonControl(toArray, []),
+ series: SeriesListComp,
+ xConfig: XAxisConfig,
+ yConfig: YAxisConfig,
+ legendConfig: LegendConfig,
+ chartConfig: ChartOptionComp,
+ onUIEvent: eventHandlerControl(UIEventOptions),
+};
+
+let chartJsonModeChildren: any = {
+ echartsOption: jsonControl(toObject, i18nObjs.defaultEchartsJsonOption),
+ echartsTitle: withDefault(StringControl, trans("echarts.defaultTitle")),
+ echartsLegendConfig: EchartsLegendConfig,
+ echartsLabelConfig: EchartsLabelConfig,
+ echartsConfig: EchartsOptionComp,
+ echartsTitleVerticalConfig: EchartsTitleVerticalConfig,
+ echartsTitleConfig:EchartsTitleConfig,
+
+ left:withDefault(NumberControl,trans('chart.defaultLeft')),
+ right:withDefault(NumberControl,trans('chart.defaultRight')),
+ top:withDefault(NumberControl,trans('chart.defaultTop')),
+ bottom:withDefault(NumberControl,trans('chart.defaultBottom')),
+
+ tooltip: withDefault(BoolControl, true),
+ legendVisibility: withDefault(BoolControl, true),
+}
+if (EchartDefaultChartStyle && EchartDefaultTextStyle) {
+ chartJsonModeChildren = {
+ ...chartJsonModeChildren,
+ chartStyle: styleControl(EchartDefaultChartStyle, 'chartStyle'),
+ titleStyle: styleControl(EchartDefaultTextStyle, 'titleStyle'),
+ xAxisStyle: styleControl(EchartDefaultTextStyle, 'xAxis'),
+ yAxisStyle: styleControl(EchartDefaultTextStyle, 'yAxisStyle'),
+ legendStyle: styleControl(EchartDefaultTextStyle, 'legendStyle'),
+ }
+}
+
+const chartMapModeChildren = {
+ mapInstance: stateComp(),
+ getMapInstance: FunctionControl,
+ mapApiKey: withDefault(StringControl, ''),
+ mapZoomLevel: withDefault(NumberControl, 3),
+ mapCenterLng: withDefault(NumberControl, 15.932644),
+ mapCenterLat: withDefault(NumberControl, 50.942063),
+ mapOptions: jsonControl(toObject, i18nObjs.defaultMapJsonOption),
+ onMapEvent: eventHandlerControl(MapEventOptions),
+ showCharts: withDefault(BoolControl, true),
+}
+
+export type UIChartDataType = {
+ seriesName: string;
+ // coordinate chart
+ x?: any;
+ y?: any;
+ // pie or funnel
+ itemName?: any;
+ value?: any;
+};
+
+export type NonUIChartDataType = {
+ name: string;
+ value: any;
+}
+
+export const barChartChildrenMap = {
+ selectedPoints: stateComp>([]),
+ lastInteractionData: stateComp | NonUIChartDataType>({}),
+ onEvent: eventHandlerControl([clickEvent] as const),
+ ...chartUiModeChildren,
+ ...chartJsonModeChildren,
+ ...chartMapModeChildren,
+};
+
+const chartUiChildrenMap = uiChildren(barChartChildrenMap);
+export type ChartCompPropsType = RecordConstructorToView;
+export type ChartCompChildrenType = RecordConstructorToComp;
diff --git a/client/packages/lowcoder-comps/src/comps/barChartComp/barChartPropertyView.tsx b/client/packages/lowcoder-comps/src/comps/barChartComp/barChartPropertyView.tsx
new file mode 100644
index 000000000..5f3d41879
--- /dev/null
+++ b/client/packages/lowcoder-comps/src/comps/barChartComp/barChartPropertyView.tsx
@@ -0,0 +1,150 @@
+import { changeChildAction, CompAction } from "lowcoder-core";
+import { ChartCompChildrenType, ChartTypeOptions,getDataKeys } from "./barChartConstants";
+import { newSeries } from "./seriesComp";
+import {
+ CustomModal,
+ Dropdown,
+ hiddenPropertyView,
+ Option,
+ RedButton,
+ Section,
+ sectionNames,
+ controlItem,
+} from "lowcoder-sdk";
+import { trans } from "i18n/comps";
+
+export function barChartPropertyView(
+ children: ChartCompChildrenType,
+ dispatch: (action: CompAction) => void
+) {
+ const series = children.series.getView();
+ const columnOptions = getDataKeys(children.data.getView()).map((key) => ({
+ label: key,
+ value: key,
+ }));
+
+ const uiModePropertyView = (
+ <>
+
+ {children.chartConfig.getPropertyView()}
+ {
+ dispatch(changeChildAction("xAxisKey", value));
+ }}
+ />
+ {children.chartConfig.getView().subtype === "waterfall" && children.xAxisData.propertyView({
+ label: "X-Label-Data"
+ })}
+ s.getView().seriesName}
+ popoverTitle={(s) => s.getView().columnName}
+ content={(s, index) => (
+ <>
+ {s.getPropertyViewWithData(columnOptions)}
+ {
+ {
+ CustomModal.confirm({
+ title: trans("chart.delete"),
+ content: trans("chart.confirmDelete") + `${s.getView().seriesName}?`,
+ onConfirm: () =>
+ children.series.dispatch(children.series.deleteAction(index)),
+ confirmBtnType: "delete",
+ okText: trans("chart.delete"),
+ });
+ }}
+ >
+ {trans("chart.delete")}
+
+ }
+ >
+ )}
+ onAdd={() => {
+ if (columnOptions.length <= 0) {
+ return;
+ }
+ children.series.dispatch(
+ children.series.pushAction(
+ newSeries(trans("chart.customSeries"), columnOptions[0].value)
+ )
+ );
+ }}
+ onMove={(fromIndex, toIndex) => {
+ const action = children.series.arrayMoveAction(fromIndex, toIndex);
+ children.series.dispatch(action);
+ }}
+ hide={(s) => s.getView().hide}
+ onHide={(s, hide) => s.children.hide.dispatchChangeValueAction(hide)}
+ dataIndex={(s) => s.getView().dataIndex}
+ />
+
+
+
+ {children.onUIEvent.propertyView({title: trans("chart.chartEventHandlers")})}
+
+
+ {children.onEvent.propertyView()}
+
+
+
+ {children.echartsTitleConfig.getPropertyView()}
+ {children.echartsTitleVerticalConfig.getPropertyView()}
+ {children.legendConfig.getPropertyView()}
+ {children.title.propertyView({ label: trans("chart.title") })}
+ {children.left.propertyView({ label: trans("chart.left"), tooltip: trans("echarts.leftTooltip") })}
+ {children.right.propertyView({ label: trans("chart.right"), tooltip: trans("echarts.rightTooltip") })}
+ {children.top.propertyView({ label: trans("chart.top"), tooltip: trans("echarts.topTooltip") })}
+ {children.bottom.propertyView({ label: trans("chart.bottom"), tooltip: trans("echarts.bottomTooltip") })}
+ {children.chartConfig.children.compType.getView() !== "pie" && (
+ <>
+ {children.xAxisDirection.propertyView({
+ label: trans("chart.xAxisDirection"),
+ radioButton: true,
+ })}
+ {children.xConfig.getPropertyView()}
+ {children.yConfig.getPropertyView()}
+ >
+ )}
+ {hiddenPropertyView(children)}
+ {children.tooltip.propertyView({label: trans("echarts.tooltip"), tooltip: trans("echarts.tooltipTooltip")})}
+
+
+ {children.chartStyle?.getPropertyView()}
+
+
+ {children.titleStyle?.getPropertyView()}
+
+
+ {children.xAxisStyle?.getPropertyView()}
+
+
+ {children.yAxisStyle?.getPropertyView()}
+
+
+ {children.legendStyle?.getPropertyView()}
+
+
+ {children.data.propertyView({
+ label: trans("chart.data"),
+ })}
+
+ >
+ );
+
+ const getChatConfigByMode = (mode: string) => {
+ switch(mode) {
+ case "ui":
+ return uiModePropertyView;
+ }
+ }
+ return (
+ <>
+ {getChatConfigByMode(children.mode.getView())}
+ >
+ );
+}
diff --git a/client/packages/lowcoder-comps/src/comps/barChartComp/barChartUtils.ts b/client/packages/lowcoder-comps/src/comps/barChartComp/barChartUtils.ts
new file mode 100644
index 000000000..72abe79f7
--- /dev/null
+++ b/client/packages/lowcoder-comps/src/comps/barChartComp/barChartUtils.ts
@@ -0,0 +1,396 @@
+import {
+ CharOptionCompType,
+ ChartCompPropsType,
+ ChartSize,
+ noDataAxisConfig,
+ noDataPieChartConfig,
+} from "comps/barChartComp/barChartConstants";
+import { getPieRadiusAndCenter } from "comps/basicChartComp/chartConfigs/pieChartConfig";
+import { EChartsOptionWithMap } from "../basicChartComp/reactEcharts/types";
+import _ from "lodash";
+import { chartColorPalette, isNumeric, JSONObject, loadScript } from "lowcoder-sdk";
+import { calcXYConfig } from "comps/basicChartComp/chartConfigs/cartesianAxisConfig";
+import Big from "big.js";
+import { googleMapsApiUrl } from "../basicChartComp/chartConfigs/chartUrls";
+import opacityToHex from "../../util/opacityToHex";
+import parseBackground from "../../util/gradientBackgroundColor";
+import {ba} from "@fullcalendar/core/internal-common";
+import {chartStyleWrapper, styleWrapper} from "../../util/styleWrapper";
+
+export function transformData(
+ originData: JSONObject[],
+ xAxis: string,
+ seriesColumnNames: string[]
+) {
+ // aggregate data by x-axis
+ const transformedData: JSONObject[] = [];
+ originData.reduce((prev, cur) => {
+ if (cur === null || cur === undefined) {
+ return prev;
+ }
+ const groupValue = cur[xAxis] as string;
+ if (!prev[groupValue]) {
+ // init as 0
+ const initValue: any = {};
+ seriesColumnNames.forEach((name) => {
+ initValue[name] = 0;
+ });
+ prev[groupValue] = initValue;
+ transformedData.push(prev[groupValue]);
+ }
+ // remain the x-axis data
+ prev[groupValue][xAxis] = groupValue;
+ seriesColumnNames.forEach((key) => {
+ if (key === xAxis) {
+ return;
+ } else if (isNumeric(cur[key])) {
+ const bigNum = Big(cur[key]);
+ prev[groupValue][key] = bigNum.add(prev[groupValue][key]).toNumber();
+ } else {
+ prev[groupValue][key] += 1;
+ }
+ });
+ return prev;
+ }, {} as any);
+ return transformedData;
+}
+
+const notAxisChartSet: Set = new Set(["pie"] as const);
+const notAxisChartSubtypeSet: Set = new Set(["polar"] as const);
+export const echartsConfigOmitChildren = [
+ "hidden",
+ "selectedPoints",
+ "onUIEvent",
+ "mapInstance"
+] as const;
+type EchartsConfigProps = Omit;
+
+
+export function isAxisChart(type: CharOptionCompType, subtype: string) {
+ return !notAxisChartSet.has(type) && !notAxisChartSubtypeSet.has(subtype);
+}
+
+export function getSeriesConfig(props: EchartsConfigProps) {
+ let visibleSeries = props.series.filter((s) => !s.getView().hide);
+ if(props.chartConfig.subtype === "waterfall") {
+ const seriesOn = visibleSeries[0];
+ const seriesPlaceholder = visibleSeries[0];
+ visibleSeries = [seriesPlaceholder, seriesOn];
+ }
+ const seriesLength = visibleSeries.length;
+ return visibleSeries.map((s, index) => {
+ if (isAxisChart(props.chartConfig.type, props.chartConfig.subtype)) {
+ let encodeX: string, encodeY: string;
+ const horizontalX = props.xAxisDirection === "horizontal";
+ let itemStyle = props.chartConfig.itemStyle;
+ // FIXME: need refactor... chartConfig returns a function with paramters
+ if (props.chartConfig.type === "bar") {
+ // barChart's border radius, depend on x-axis direction and stack state
+ const borderRadius = horizontalX ? [2, 2, 0, 0] : [0, 2, 2, 0];
+ if (props.chartConfig.stack && index === visibleSeries.length - 1) {
+ itemStyle = { ...itemStyle, borderRadius: borderRadius };
+ } else if (!props.chartConfig.stack) {
+ itemStyle = { ...itemStyle, borderRadius: borderRadius };
+ }
+
+ if(props.chartConfig.subtype === "waterfall" && index === 0) {
+ itemStyle = {
+ borderColor: 'transparent',
+ color: 'transparent'
+ }
+ }
+ }
+ if (horizontalX) {
+ encodeX = props.xAxisKey;
+ encodeY = s.getView().columnName;
+ } else {
+ encodeX = s.getView().columnName;
+ encodeY = props.xAxisKey;
+ }
+ return {
+ name: props.chartConfig.subtype === "waterfall" && index === 0?" ":s.getView().seriesName,
+ columnName: props.chartConfig.subtype === "waterfall" && index === 0?" ":s.getView().columnName,
+ selectedMode: "single",
+ select: {
+ itemStyle: {
+ borderColor: "#000",
+ },
+ },
+ encode: {
+ x: encodeX,
+ y: encodeY,
+ },
+ // each type of chart's config
+ ...props.chartConfig,
+ itemStyle: itemStyle,
+ label: {
+ ...props.chartConfig.label,
+ ...(!horizontalX && { position: "outside" }),
+ },
+ };
+ } else {
+ const radiusAndCenter = getPieRadiusAndCenter(seriesLength, index, props.chartConfig);
+ return {
+ ...props.chartConfig,
+ columnName: s.getView().columnName,
+ radius: radiusAndCenter.radius,
+ center: radiusAndCenter.center,
+ name: s.getView().seriesName,
+ selectedMode: "single",
+ encode: {
+ itemName: props.xAxisKey,
+ value: s.getView().columnName,
+ },
+ };
+ }
+ });
+}
+
+// https://echarts.apache.org/en/option.html
+export function getEchartsConfig(
+ props: EchartsConfigProps,
+ chartSize?: ChartSize,
+ theme?: any,
+): EChartsOptionWithMap {
+ // axisChart
+ const axisChart = isAxisChart(props.chartConfig.type, props.chartConfig.subtype);
+ const gridPos = {
+ left: `${props?.left}%`,
+ right: `${props?.right}%`,
+ bottom: `${props?.bottom}%`,
+ top: `${props?.top}%`,
+ };
+ let config: any = {
+ title: {
+ text: props.title,
+ top: props.echartsTitleVerticalConfig.top,
+ left:props.echartsTitleConfig.top,
+ textStyle: {
+ ...styleWrapper(props?.titleStyle, theme?.titleStyle)
+ }
+ },
+ backgroundColor: parseBackground( props?.chartStyle?.background || theme?.chartStyle?.backgroundColor || "#FFFFFF"),
+ legend: {
+ ...props.legendConfig,
+ textStyle: {
+ ...styleWrapper(props?.legendStyle, theme?.legendStyle, 15)
+ }
+ },
+ tooltip: props.tooltip && {
+ trigger: "axis",
+ axisPointer: {
+ type: "line",
+ lineStyle: {
+ color: "rgba(0,0,0,0.2)",
+ width: 2,
+ type: "solid"
+ }
+ }
+ },
+ grid: {
+ ...gridPos,
+ containLabel: true,
+ },
+ };
+ if(props.chartConfig.race) {
+ config = {
+ ...config,
+ // Disable init animation.
+ animationDuration: 0,
+ animationDurationUpdate: 2000,
+ animationEasing: 'linear',
+ animationEasingUpdate: 'linear',
+ }
+ }
+ if (props.data.length <= 0) {
+ // no data
+ return {
+ ...config,
+ ...(axisChart ? noDataAxisConfig : noDataPieChartConfig),
+ };
+ }
+ const yAxisConfig = props.yConfig();
+ const seriesColumnNames = props.series
+ .filter((s) => !s.getView().hide)
+ .map((s) => s.getView().columnName);
+ // y-axis is category and time, data doesn't need to aggregate
+ let transformedData =
+ yAxisConfig.type === "category" || yAxisConfig.type === "time" ? props.echartsOption.length && props.echartsOption || props.data : transformData(props.echartsOption.length && props.echartsOption || props.data, props.xAxisKey, seriesColumnNames);
+
+ if(props.chartConfig.subtype === "waterfall") {
+ config.legend = undefined;
+ let sum = transformedData.reduce((acc, item) => {
+ if(typeof item[seriesColumnNames[0]] === 'number') return acc + item[seriesColumnNames[0]];
+ else return acc;
+ }, 0)
+ const total = sum;
+ transformedData.map(d => {
+ d[` `] = sum - d[seriesColumnNames[0]];
+ sum = d[` `];
+ })
+ transformedData = [{[" "]: 0, [seriesColumnNames[0]]: total, [props.xAxisKey]: "Total"}, ...transformedData]
+ }
+
+ if(props.chartConfig.subtype === "polar") {
+ config = {
+ ...config,
+ polar: {
+ radius: [props.chartConfig.polarData.polarRadiusStart, props.chartConfig.polarData.polarRadiusEnd],
+ },
+ radiusAxis: {
+ type: props.chartConfig.polarData.polarIsTangent?'category':undefined,
+ data: props.chartConfig.polarData.polarIsTangent && props.chartConfig.polarData.labelData.length!==0?props.chartConfig.polarData.labelData:undefined,
+ max: props.chartConfig.polarData.polarIsTangent?undefined:props.chartConfig.polarData.radiusAxisMax || undefined,
+ },
+ angleAxis: {
+ type: props.chartConfig.polarData.polarIsTangent?undefined:'category',
+ data: !props.chartConfig.polarData.polarIsTangent && props.chartConfig.polarData.labelData.length!==0?props.chartConfig.polarData.labelData:undefined,
+ max: props.chartConfig.polarData.polarIsTangent?props.chartConfig.polarData.radiusAxisMax || undefined:undefined,
+ startAngle: props.chartConfig.polarData.polarStartAngle,
+ endAngle: props.chartConfig.polarData.polarEndAngle,
+ },
+ }
+ }
+
+ config = {
+ ...config,
+ dataset: [
+ {
+ source: transformedData,
+ sourceHeader: false,
+ },
+ ],
+ series: getSeriesConfig(props).map(series => ({
+ ...series,
+ encode: {
+ ...series.encode,
+ y: series.name,
+ },
+ itemStyle: {
+ ...series.itemStyle,
+ ...chartStyleWrapper(props?.chartStyle, theme?.chartStyle)
+ },
+ lineStyle: {
+ ...chartStyleWrapper(props?.chartStyle, theme?.chartStyle)
+ },
+ data: transformedData.map((i: any) => i[series.columnName])
+ })),
+ };
+ if (axisChart) {
+ // pure chart's size except the margin around
+ let chartRealSize;
+ if (chartSize) {
+ const rightSize =
+ typeof gridPos.right === "number"
+ ? gridPos.right
+ : (chartSize.w * parseFloat(gridPos.right)) / 100.0;
+ chartRealSize = {
+ // actually it's self-adaptive with the x-axis label on the left, not that accurate but work
+ w: chartSize.w - gridPos.left - rightSize,
+ // also self-adaptive on the bottom
+ h: chartSize.h - gridPos.top - gridPos.bottom,
+ right: rightSize,
+ };
+ }
+ const finalXyConfig = calcXYConfig(
+ props.xConfig,
+ yAxisConfig,
+ props.xAxisDirection,
+ transformedData.map((d) => d[props.xAxisKey]),
+ chartRealSize
+ );
+ config = {
+ ...config,
+ // @ts-ignore
+ xAxis: {
+ ...finalXyConfig.xConfig,
+ axisLabel: {
+ ...styleWrapper(props?.xAxisStyle, theme?.xAxisStyle, 11)
+ },
+ data: finalXyConfig.xConfig.type === "category" && (props.xAxisData as []).length!==0?props?.xAxisData:transformedData.map((i: any) => i[props.xAxisKey]),
+ },
+ // @ts-ignore
+ yAxis: {
+ ...finalXyConfig.yConfig,
+ axisLabel: {
+ ...styleWrapper(props?.yAxisStyle, theme?.yAxisStyle, 11)
+ },
+ data: finalXyConfig.yConfig.type === "category" && (props.xAxisData as []).length!==0?props?.xAxisData:transformedData.map((i: any) => i[props.xAxisKey]),
+ },
+ };
+
+ if(props.chartConfig.race) {
+ config = {
+ ...config,
+ xAxis: {
+ ...config.xAxis,
+ animationDuration: 300,
+ animationDurationUpdate: 300
+ },
+ yAxis: {
+ ...config.yAxis,
+ animationDuration: 300,
+ animationDurationUpdate: 300
+ },
+ }
+ }
+ }
+ // console.log("Echarts transformedData and config", transformedData, config);
+ return config;
+}
+
+export function getSelectedPoints(param: any, option: any) {
+ const series = option.series;
+ const dataSource = _.isArray(option.dataset) && option.dataset[0]?.source;
+ if (series && dataSource) {
+ return param.selected.flatMap((selectInfo: any) => {
+ const seriesInfo = series[selectInfo.seriesIndex];
+ if (!seriesInfo || !seriesInfo.encode) {
+ return [];
+ }
+ return selectInfo.dataIndex.map((index: any) => {
+ const commonResult = {
+ seriesName: seriesInfo.name,
+ };
+ if (seriesInfo.encode.itemName && seriesInfo.encode.value) {
+ return {
+ ...commonResult,
+ itemName: dataSource[index][seriesInfo.encode.itemName],
+ value: dataSource[index][seriesInfo.encode.value],
+ };
+ } else {
+ return {
+ ...commonResult,
+ x: dataSource[index][seriesInfo.encode.x],
+ y: dataSource[index][seriesInfo.encode.y],
+ };
+ }
+ });
+ });
+ }
+ return [];
+}
+
+export function loadGoogleMapsScript(apiKey: string) {
+ const mapsUrl = `${googleMapsApiUrl}?key=${apiKey}`;
+ const scripts = document.getElementsByTagName('script');
+ // is script already loaded
+ let scriptIndex = _.findIndex(scripts, (script) => script.src.endsWith(mapsUrl));
+ if(scriptIndex > -1) {
+ return scripts[scriptIndex];
+ }
+ // is script loaded with diff api_key, remove the script and load again
+ scriptIndex = _.findIndex(scripts, (script) => script.src.startsWith(googleMapsApiUrl));
+ if(scriptIndex > -1) {
+ scripts[scriptIndex].remove();
+ }
+
+ const script = document.createElement("script");
+ script.type = "text/javascript";
+ script.src = mapsUrl;
+ script.async = true;
+ script.defer = true;
+ window.document.body.appendChild(script);
+
+ return script;
+}
diff --git a/client/packages/lowcoder-comps/src/comps/barChartComp/seriesComp.tsx b/client/packages/lowcoder-comps/src/comps/barChartComp/seriesComp.tsx
new file mode 100644
index 000000000..9ded885b5
--- /dev/null
+++ b/client/packages/lowcoder-comps/src/comps/barChartComp/seriesComp.tsx
@@ -0,0 +1,119 @@
+import {
+ BoolControl,
+ StringControl,
+ list,
+ JSONObject,
+ isNumeric,
+ genRandomKey,
+ Dropdown,
+ OptionsType,
+ MultiCompBuilder,
+ valueComp,
+} from "lowcoder-sdk";
+import { trans } from "i18n/comps";
+
+import { ConstructorToComp, ConstructorToDataType, ConstructorToView } from "lowcoder-core";
+import { CompAction, CustomAction, customAction, isMyCustomAction } from "lowcoder-core";
+
+export type SeriesCompType = ConstructorToComp;
+export type RawSeriesCompType = ConstructorToView;
+type SeriesDataType = ConstructorToDataType;
+
+type ActionDataType = {
+ type: "chartDataChanged";
+ chartData: Array;
+};
+
+export function newSeries(name: string, columnName: string): SeriesDataType {
+ return {
+ seriesName: name,
+ columnName: columnName,
+ dataIndex: genRandomKey(),
+ };
+}
+
+const seriesChildrenMap = {
+ columnName: StringControl,
+ seriesName: StringControl,
+ hide: BoolControl,
+ // unique key, for sort
+ dataIndex: valueComp(""),
+};
+
+const SeriesTmpComp = new MultiCompBuilder(seriesChildrenMap, (props) => {
+ return props;
+})
+ .setPropertyViewFn(() => {
+ return <>>;
+ })
+ .build();
+
+class SeriesComp extends SeriesTmpComp {
+ getPropertyViewWithData(columnOptions: OptionsType): React.ReactNode {
+ return (
+ <>
+ {this.children.seriesName.propertyView({
+ label: trans("chart.seriesName"),
+ })}
+ {
+ this.children.columnName.dispatchChangeValueAction(value);
+ }}
+ />
+ >
+ );
+ }
+}
+
+const SeriesListTmpComp = list(SeriesComp);
+
+export class SeriesListComp extends SeriesListTmpComp {
+ override reduce(action: CompAction): this {
+ if (isMyCustomAction(action, "chartDataChanged")) {
+ // auto generate series
+ const actions = this.genExampleSeriesActions(action.value.chartData);
+ return this.reduce(this.multiAction(actions));
+ }
+ return super.reduce(action);
+ }
+
+ private genExampleSeriesActions(chartData: Array) {
+ const actions: CustomAction[] = [];
+ if (!chartData || chartData.length <= 0 || !chartData[0]) {
+ return actions;
+ }
+ let delCnt = 0;
+ const existColumns = this.getView().map((s) => s.getView().columnName);
+ // delete series not in data
+ existColumns.forEach((columnName) => {
+ if (chartData[0]?.[columnName] === undefined) {
+ actions.push(this.deleteAction(0));
+ delCnt++;
+ }
+ });
+ if (existColumns.length > delCnt) {
+ // don't generate example if exists
+ return actions;
+ }
+ // generate example series
+ const exampleKeys = Object.keys(chartData[0])
+ .filter((key) => {
+ return !existColumns.includes(key) && isNumeric(chartData[0][key]);
+ })
+ .slice(0, 3);
+ exampleKeys.forEach((key) => actions.push(this.pushAction(newSeries(key, key))));
+ return actions;
+ }
+
+ dispatchDataChanged(chartData: Array): void {
+ this.dispatch(
+ customAction({
+ type: "chartDataChanged",
+ chartData: chartData,
+ })
+ );
+ }
+}
diff --git a/client/packages/lowcoder-comps/src/comps/basicChartComp/chartConfigs/barChartConfig.tsx b/client/packages/lowcoder-comps/src/comps/basicChartComp/chartConfigs/barChartConfig.tsx
index 6c91fe252..ee1188335 100644
--- a/client/packages/lowcoder-comps/src/comps/basicChartComp/chartConfigs/barChartConfig.tsx
+++ b/client/packages/lowcoder-comps/src/comps/basicChartComp/chartConfigs/barChartConfig.tsx
@@ -1,11 +1,19 @@
import {
BoolControl,
+ NumberControl,
+ StringControl,
+ withDefault,
dropdownControl,
MultiCompBuilder,
showLabelPropertyView,
+ ColorControl,
+ Dropdown,
+ toArray,
+ jsonControl,
} from "lowcoder-sdk";
+import { changeChildAction, CompAction } from "lowcoder-core";
import { BarSeriesOption } from "echarts";
-import { trans } from "i18n/comps";
+import { i18nObjs, trans } from "i18n/comps";
const BarTypeOptions = [
{
@@ -13,8 +21,12 @@ const BarTypeOptions = [
value: "basicBar",
},
{
- label: trans("chart.stackedBar"),
- value: "stackedBar",
+ label: trans("chart.waterfallBar"),
+ value: "waterfall",
+ },
+ {
+ label: trans("chart.polar"),
+ value: "polar",
},
] as const;
@@ -23,27 +35,105 @@ export const BarChartConfig = (function () {
{
showLabel: BoolControl,
type: dropdownControl(BarTypeOptions, "basicBar"),
+ barWidth: withDefault(NumberControl, i18nObjs.defaultBarChartOption.barWidth),
+ showBackground: BoolControl,
+ backgroundColor: withDefault(ColorControl, i18nObjs.defaultBarChartOption.barBg),
+ radiusAxisMax: NumberControl,
+ polarRadiusStart: withDefault(StringControl, '30'),
+ polarRadiusEnd: withDefault(StringControl, '80%'),
+ polarStartAngle: withDefault(NumberControl, 90),
+ polarEndAngle: withDefault(NumberControl, -180),
+ polarIsTangent: withDefault(BoolControl, false),
+ stack: withDefault(BoolControl, false),
+ race: withDefault(BoolControl, false),
+ labelData: jsonControl(toArray, []),
},
(props): BarSeriesOption => {
const config: BarSeriesOption = {
type: "bar",
+ subtype: props.type,
+ realtimeSort: props.race,
+ seriesLayoutBy: props.race?'column':undefined,
label: {
show: props.showLabel,
position: "top",
+ valueAnimation: props.race,
+ },
+ barWidth: `${props.barWidth}%`,
+ showBackground: props.showBackground,
+ backgroundStyle: {
+ color: props.backgroundColor,
},
+ polarData: {
+ radiusAxisMax: props.radiusAxisMax,
+ polarRadiusStart: props.polarRadiusStart,
+ polarRadiusEnd: props.polarRadiusEnd,
+ polarStartAngle: props.polarStartAngle,
+ polarEndAngle: props.polarEndAngle,
+ labelData: props.labelData,
+ polarIsTangent: props.polarIsTangent,
+ },
+ race: props.race,
};
- if (props.type === "stackedBar") {
+ if (props.stack) {
config.stack = "stackValue";
}
+ if (props.type === "waterfall") {
+ config.label = undefined;
+ config.stack = "stackValue";
+ }
+ if (props.type === "polar") {
+ config.coordinateSystem = 'polar';
+ }
return config;
}
)
- .setPropertyViewFn((children) => (
+ .setPropertyViewFn((children, dispatch: (action: CompAction) => void) => (
<>
+ {
+ dispatch(changeChildAction("type", value));
+ }}
+ />
{showLabelPropertyView(children)}
- {children.type.propertyView({
- label: trans("chart.barType"),
- radioButton: true,
+ {children.barWidth.propertyView({
+ label: trans("barChart.barWidth"),
+ })}
+ {children.type.getView() !== "waterfall" && children.race.propertyView({
+ label: trans("barChart.race"),
+ })}
+ {children.type.getView() !== "waterfall" && children.stack.propertyView({
+ label: trans("barChart.stack"),
+ })}
+ {children.showBackground.propertyView({
+ label: trans("barChart.showBg"),
+ })}
+ {children.showBackground.getView() && children.backgroundColor.propertyView({
+ label: trans("barChart.bgColor"),
+ })}
+ {children.type.getView() === "polar" && children.polarIsTangent.propertyView({
+ label: trans("barChart.polarIsTangent"),
+ })}
+ {children.type.getView() === "polar" && children.polarStartAngle.propertyView({
+ label: trans("barChart.polarStartAngle"),
+ })}
+ {children.type.getView() === "polar" && children.polarEndAngle.propertyView({
+ label: trans("barChart.polarEndAngle"),
+ })}
+ {children.type.getView() === "polar" && children.radiusAxisMax.propertyView({
+ label: trans("barChart.radiusAxisMax"),
+ })}
+ {children.type.getView() === "polar" && children.polarRadiusStart.propertyView({
+ label: trans("barChart.polarRadiusStart"),
+ })}
+ {children.type.getView() === "polar" && children.polarRadiusEnd.propertyView({
+ label: trans("barChart.polarRadiusEnd"),
+ })}
+ {children.type.getView() === "polar" && children.labelData.propertyView({
+ label: trans("barChart.polarLabelData"),
})}
>
))
diff --git a/client/packages/lowcoder-comps/src/comps/basicChartComp/chartConfigs/lineChartConfig.tsx b/client/packages/lowcoder-comps/src/comps/basicChartComp/chartConfigs/lineChartConfig.tsx
index 266e5fbf7..1b88d4a06 100644
--- a/client/packages/lowcoder-comps/src/comps/basicChartComp/chartConfigs/lineChartConfig.tsx
+++ b/client/packages/lowcoder-comps/src/comps/basicChartComp/chartConfigs/lineChartConfig.tsx
@@ -3,28 +3,18 @@ import {
MultiCompBuilder,
BoolControl,
dropdownControl,
+ jsonControl,
+ toArray,
showLabelPropertyView,
withContext,
+ ColorControl,
StringControl,
+ NumberControl,
+ withDefault,
ColorOrBoolCodeControl,
} from "lowcoder-sdk";
import { trans } from "i18n/comps";
-const BarTypeOptions = [
- {
- label: trans("chart.basicLine"),
- value: "basicLine",
- },
- {
- label: trans("chart.stackedLine"),
- value: "stackedLine",
- },
- {
- label: trans("chart.areaLine"),
- value: "areaLine",
- },
-] as const;
-
export const ItemColorComp = withContext(
new MultiCompBuilder({ value: ColorOrBoolCodeControl }, (props) => props.value)
.setPropertyViewFn((children) =>
@@ -38,13 +28,83 @@ export const ItemColorComp = withContext(
["seriesName", "value"] as const
);
+export const SymbolOptions = [
+ {
+ label: trans("chart.rect"),
+ value: "rect",
+ },
+ {
+ label: trans("chart.circle"),
+ value: "circle",
+ },
+ {
+ label: trans("chart.roundRect"),
+ value: "roundRect",
+ },
+ {
+ label: trans("chart.triangle"),
+ value: "triangle",
+ },
+ {
+ label: trans("chart.diamond"),
+ value: "diamond",
+ },
+ {
+ label: trans("chart.pin"),
+ value: "pin",
+ },
+ {
+ label: trans("chart.arrow"),
+ value: "arrow",
+ },
+ {
+ label: trans("chart.none"),
+ value: "none",
+ },
+ {
+ label: trans("chart.emptyCircle"),
+ value: "emptyCircle",
+ },
+] as const;
+
+export const BorderTypeOptions = [
+ {
+ label: trans("lineChart.solid"),
+ value: "solid",
+ },
+ {
+ label: trans("lineChart.dashed"),
+ value: "dashed",
+ },
+ {
+ label: trans("lineChart.dotted"),
+ value: "dotted",
+ },
+] as const;
+
export const LineChartConfig = (function () {
return new MultiCompBuilder(
{
showLabel: BoolControl,
- type: dropdownControl(BarTypeOptions, "basicLine"),
+ showEndLabel: BoolControl,
+ stacked: BoolControl,
+ area: BoolControl,
smooth: BoolControl,
+ polar: BoolControl,
itemColor: ItemColorComp,
+ symbol: dropdownControl(SymbolOptions, "emptyCircle"),
+ symbolSize: withDefault(NumberControl, 4),
+ radiusAxisMax: NumberControl,
+ polarRadiusStart: withDefault(StringControl, '30'),
+ polarRadiusEnd: withDefault(StringControl, '80%'),
+ polarStartAngle: withDefault(NumberControl, 90),
+ polarEndAngle: withDefault(NumberControl, -180),
+ polarIsTangent: withDefault(BoolControl, false),
+ labelData: jsonControl(toArray, []),
+ //series-line.itemStyle
+ borderColor: ColorControl,
+ borderWidth: NumberControl,
+ borderType: dropdownControl(BorderTypeOptions, 'solid'),
},
(props): LineSeriesOption => {
const config: LineSeriesOption = {
@@ -52,15 +112,13 @@ export const LineChartConfig = (function () {
label: {
show: props.showLabel,
},
+ symbol: props.symbol,
+ symbolSize: props.symbolSize,
itemStyle: {
color: (params) => {
- if (!params.encode || !params.dimensionNames) {
- return params.color;
- }
- const dataKey = params.dimensionNames[params.encode["y"][0]];
const color = (props.itemColor as any)({
seriesName: params.seriesName,
- value: (params.data as any)[dataKey],
+ value: params.data,
});
if (color === "true") {
return "red";
@@ -69,27 +127,96 @@ export const LineChartConfig = (function () {
}
return color;
},
+ borderColor: props.borderColor,
+ borderWidth: props.borderWidth,
+ borderType: props.borderType,
+ },
+ polarData: {
+ polar: props.polar,
+ radiusAxisMax: props.radiusAxisMax,
+ polarRadiusStart: props.polarRadiusStart,
+ polarRadiusEnd: props.polarRadiusEnd,
+ polarStartAngle: props.polarStartAngle,
+ polarEndAngle: props.polarEndAngle,
+ labelData: props.labelData,
+ polarIsTangent: props.polarIsTangent,
},
};
- if (props.type === "stackedLine") {
+ if (props.stacked) {
config.stack = "stackValue";
- } else if (props.type === "areaLine") {
+ }
+ if (props.area) {
config.areaStyle = {};
}
if (props.smooth) {
config.smooth = true;
}
+ if (props.showEndLabel) {
+ config.endLabel = {
+ show: true,
+ formatter: '{a}',
+ distance: 20
+ }
+ }
+ if (props.polar) {
+ config.coordinateSystem = 'polar';
+ }
return config;
}
)
.setPropertyViewFn((children) => (
<>
- {children.type.propertyView({
- label: trans("chart.lineType"),
+ {children.stacked.propertyView({
+ label: trans("lineChart.stacked"),
+ })}
+ {children.area.propertyView({
+ label: trans("lineChart.area"),
+ })}
+ {children.polar.propertyView({
+ label: trans("lineChart.polar"),
+ })}
+ {children.polar.getView() && children.polarIsTangent.propertyView({
+ label: trans("barChart.polarIsTangent"),
+ })}
+ {children.polar.getView() && children.polarStartAngle.propertyView({
+ label: trans("barChart.polarStartAngle"),
+ })}
+ {children.polar.getView() && children.polarEndAngle.propertyView({
+ label: trans("barChart.polarEndAngle"),
+ })}
+ {children.polar.getView() && children.radiusAxisMax.propertyView({
+ label: trans("barChart.radiusAxisMax"),
+ })}
+ {children.polar.getView() && children.polarRadiusStart.propertyView({
+ label: trans("barChart.polarRadiusStart"),
+ })}
+ {children.polar.getView() && children.polarRadiusEnd.propertyView({
+ label: trans("barChart.polarRadiusEnd"),
+ })}
+ {children.polar.getView() && children.labelData.propertyView({
+ label: trans("barChart.polarLabelData"),
})}
{showLabelPropertyView(children)}
+ {children.showEndLabel.propertyView({
+ label: trans("lineChart.showEndLabel"),
+ })}
{children.smooth.propertyView({ label: trans("chart.smooth") })}
+ {children.symbol.propertyView({
+ label: trans("lineChart.symbol"),
+ })}
+ {children.symbolSize.propertyView({
+ label: trans("lineChart.symbolSize"),
+ })}
{children.itemColor.getPropertyView()}
+ {children.borderColor.propertyView({
+ label: trans("lineChart.borderColor"),
+ })}
+ {children.borderWidth.propertyView({
+ label: trans("lineChart.borderWidth"),
+ })}
+ {children.borderType.propertyView({
+ label: trans("lineChart.borderType"),
+ })}
>
))
.build();
diff --git a/client/packages/lowcoder-comps/src/comps/basicChartComp/chartConfigs/pieChartConfig.tsx b/client/packages/lowcoder-comps/src/comps/basicChartComp/chartConfigs/pieChartConfig.tsx
index 0861fb6ba..e8781d5c3 100644
--- a/client/packages/lowcoder-comps/src/comps/basicChartComp/chartConfigs/pieChartConfig.tsx
+++ b/client/packages/lowcoder-comps/src/comps/basicChartComp/chartConfigs/pieChartConfig.tsx
@@ -1,6 +1,11 @@
import { MultiCompBuilder } from "lowcoder-sdk";
import { PieSeriesOption } from "echarts";
-import { dropdownControl } from "lowcoder-sdk";
+import {
+ dropdownControl,
+ NumberControl,
+ StringControl,
+ withDefault,
+ } from "lowcoder-sdk";
import { ConstructorToView } from "lowcoder-core";
import { trans } from "i18n/comps";
@@ -17,6 +22,14 @@ const BarTypeOptions = [
label: trans("chart.rosePie"),
value: "rosePie",
},
+ {
+ label: trans("chart.calendarPie"),
+ value: "calendarPie",
+ },
+ {
+ label: trans("chart.geoPie"),
+ value: "geoPie",
+ },
] as const;
// radius percent for each pie chart when one line has [1, 2, 3] pie charts
@@ -28,20 +41,37 @@ export const PieChartConfig = (function () {
return new MultiCompBuilder(
{
type: dropdownControl(BarTypeOptions, "basicPie"),
+ cellSize: withDefault(NumberControl, 40),
+ range: withDefault(StringControl, "2021-09"),
+ mapUrl: withDefault(StringControl, "https://echarts.apache.org/examples/data/asset/geo/USA.json"),
},
(props): PieSeriesOption => {
const config: PieSeriesOption = {
type: "pie",
+ subtype: props.type,
label: {
show: true,
formatter: "{d}%",
},
+ range: props.range,
};
if (props.type === "rosePie") {
config.roseType = "area";
- } else if (props.type === "doughnutPie") {
+ }
+ if (props.type === "doughnutPie") {
config.radius = ["40%", "60%"];
}
+ if (props.type === "calendarPie") {
+ config.coordinateSystem = 'calendar';
+ config.cellSize = [props.cellSize, props.cellSize];
+ config.label = {
+ ...config.label,
+ position: 'inside'
+ };
+ }
+ if (props.type === "geoPie") {
+ config.mapUrl = props.mapUrl;
+ }
return config;
}
)
@@ -50,6 +80,15 @@ export const PieChartConfig = (function () {
{children.type.propertyView({
label: trans("chart.pieType"),
})}
+ {children.type.getView() === "calendarPie" && children.cellSize.propertyView({
+ label: trans("lineChart.cellSize"),
+ })}
+ {children.type.getView() === "calendarPie" && children.range.propertyView({
+ label: trans("lineChart.range"),
+ })}
+ {children.type.getView() === "geoPie" && children.mapUrl.propertyView({
+ label: trans("pieChart.mapUrl"),
+ })}
>
))
.build();
diff --git a/client/packages/lowcoder-comps/src/comps/basicChartComp/chartConfigs/scatterChartConfig.tsx b/client/packages/lowcoder-comps/src/comps/basicChartComp/chartConfigs/scatterChartConfig.tsx
index edb339bdb..34b5f2cb6 100644
--- a/client/packages/lowcoder-comps/src/comps/basicChartComp/chartConfigs/scatterChartConfig.tsx
+++ b/client/packages/lowcoder-comps/src/comps/basicChartComp/chartConfigs/scatterChartConfig.tsx
@@ -2,6 +2,10 @@ import {
MultiCompBuilder,
dropdownControl,
BoolControl,
+ StringControl,
+ NumberControl,
+ ColorControl,
+ withDefault,
showLabelPropertyView,
} from "lowcoder-sdk";
import { ScatterSeriesOption } from "echarts";
@@ -38,7 +42,19 @@ export const ScatterChartConfig = (function () {
return new MultiCompBuilder(
{
showLabel: BoolControl,
+ labelIndex: withDefault(NumberControl, 2),
shape: dropdownControl(ScatterShapeOptions, "circle"),
+ singleAxis: BoolControl,
+ boundaryGap: withDefault(BoolControl, true),
+ visualMap: BoolControl,
+ visualMapMin: NumberControl,
+ visualMapMax: NumberControl,
+ visualMapDimension: NumberControl,
+ visualMapColorMin: ColorControl,
+ visualMapColorMax: ColorControl,
+ polar: BoolControl,
+ heatmap: BoolControl,
+ heatmapMonth: withDefault(StringControl, "2021-09"),
},
(props): ScatterSeriesOption => {
return {
@@ -46,16 +62,82 @@ export const ScatterChartConfig = (function () {
symbol: props.shape,
label: {
show: props.showLabel,
+ position: 'right',
+ formatter: function (param) {
+ return param.data[props.labelIndex];
+ },
},
+ labelLayout: function () {
+ return {
+ x: '88%',
+ moveOverlap: 'shiftY'
+ };
+ },
+ labelLine: {
+ show: true,
+ length2: 5,
+ lineStyle: {
+ color: '#bbb'
+ }
+ },
+ singleAxis: props.singleAxis,
+ boundaryGap: props.boundaryGap,
+ visualMapData: {
+ visualMap: props.visualMap,
+ visualMapMin: props.visualMapMin,
+ visualMapMax: props.visualMapMax,
+ visualMapDimension: props.visualMapDimension,
+ visualMapColorMin: props.visualMapColorMin,
+ visualMapColorMax: props.visualMapColorMax,
+ },
+ polar: props.polar,
+ heatmap: props.heatmap,
+ heatmapMonth: props.heatmapMonth,
};
}
)
.setPropertyViewFn((children) => (
<>
{showLabelPropertyView(children)}
+ {children.showLabel.getView() && children.labelIndex.propertyView({
+ label: trans("scatterChart.labelIndex"),
+ })}
+ {children.boundaryGap.propertyView({
+ label: trans("scatterChart.boundaryGap"),
+ })}
{children.shape.propertyView({
label: trans("chart.scatterShape"),
})}
+ {children.singleAxis.propertyView({
+ label: trans("scatterChart.singleAxis"),
+ })}
+ {children.visualMap.propertyView({
+ label: trans("scatterChart.visualMap"),
+ })}
+ {children.visualMap.getView() && children.visualMapMin.propertyView({
+ label: trans("scatterChart.visualMapMin"),
+ })}
+ {children.visualMap.getView() && children.visualMapMax.propertyView({
+ label: trans("scatterChart.visualMapMax"),
+ })}
+ {children.visualMap.getView() && children.visualMapDimension.propertyView({
+ label: trans("scatterChart.visualMapDimension"),
+ })}
+ {children.visualMap.getView() && children.visualMapColorMin.propertyView({
+ label: trans("scatterChart.visualMapColorMin"),
+ })}
+ {children.visualMap.getView() && children.visualMapColorMax.propertyView({
+ label: trans("scatterChart.visualMapColorMax"),
+ })}
+ {children.visualMap.getView() && children.heatmap.propertyView({
+ label: trans("scatterChart.heatmap"),
+ })}
+ {children.visualMap.getView() && children.heatmapMonth.propertyView({
+ label: trans("scatterChart.heatmapMonth"),
+ })}
+ {children.polar.propertyView({
+ label: trans("scatterChart.polar"),
+ })}
>
))
.build();
diff --git a/client/packages/lowcoder-comps/src/comps/basicChartComp/chartUtils.ts b/client/packages/lowcoder-comps/src/comps/basicChartComp/chartUtils.ts
index 402011e6c..6c5020690 100644
--- a/client/packages/lowcoder-comps/src/comps/basicChartComp/chartUtils.ts
+++ b/client/packages/lowcoder-comps/src/comps/basicChartComp/chartUtils.ts
@@ -276,7 +276,7 @@ export function getEchartsConfig(
},
};
}
- // log.log("Echarts transformedData and config", transformedData, config);
+ // console.log("Echarts transformedData and config", transformedData, config);
return config;
}
diff --git a/client/packages/lowcoder-comps/src/comps/basicChartComp/reactEcharts/index.ts b/client/packages/lowcoder-comps/src/comps/basicChartComp/reactEcharts/index.ts
index dcb57f0f9..da1f165a1 100644
--- a/client/packages/lowcoder-comps/src/comps/basicChartComp/reactEcharts/index.ts
+++ b/client/packages/lowcoder-comps/src/comps/basicChartComp/reactEcharts/index.ts
@@ -1,4 +1,5 @@
import * as echarts from "echarts";
+import "echarts-gl";
import "echarts-wordcloud";
import { EChartsReactProps, EChartsInstance, EChartsOptionWithMap } from "./types";
import EChartsReactCore from "./core";
diff --git a/client/packages/lowcoder-comps/src/comps/boxplotChartComp/boxplotChartComp.tsx b/client/packages/lowcoder-comps/src/comps/boxplotChartComp/boxplotChartComp.tsx
new file mode 100644
index 000000000..8cd1910b1
--- /dev/null
+++ b/client/packages/lowcoder-comps/src/comps/boxplotChartComp/boxplotChartComp.tsx
@@ -0,0 +1,282 @@
+import {
+ changeChildAction,
+ changeValueAction,
+ CompAction,
+ CompActionTypes,
+ wrapChildAction,
+} from "lowcoder-core";
+import { AxisFormatterComp, EchartsAxisType } from "../basicChartComp/chartConfigs/cartesianAxisConfig";
+import { boxplotChartChildrenMap, ChartSize, getDataKeys } from "./boxplotChartConstants";
+import { boxplotChartPropertyView } from "./boxplotChartPropertyView";
+import _ from "lodash";
+import { useContext, useEffect, useMemo, useRef, useState } from "react";
+import ReactResizeDetector from "react-resize-detector";
+import ReactECharts from "../basicChartComp/reactEcharts";
+import * as echarts from "echarts";
+import {
+ childrenToProps,
+ depsConfig,
+ genRandomKey,
+ NameConfig,
+ UICompBuilder,
+ withDefault,
+ withExposingConfigs,
+ withViewFn,
+ ThemeContext,
+ chartColorPalette,
+ getPromiseAfterDispatch,
+ dropdownControl,
+} from "lowcoder-sdk";
+import { getEchartsLocale, i18nObjs, trans } from "i18n/comps";
+import {
+ echartsConfigOmitChildren,
+ getEchartsConfig,
+ getSelectedPoints,
+} from "./boxplotChartUtils";
+import 'echarts-extension-gmap';
+import log from "loglevel";
+
+let clickEventCallback = () => {};
+
+const chartModeOptions = [
+ {
+ label: "UI",
+ value: "ui",
+ }
+] as const;
+
+let BoxplotChartTmpComp = (function () {
+ return new UICompBuilder({mode:dropdownControl(chartModeOptions,'ui'),...boxplotChartChildrenMap}, () => null)
+ .setPropertyViewFn(boxplotChartPropertyView)
+ .build();
+})();
+
+BoxplotChartTmpComp = withViewFn(BoxplotChartTmpComp, (comp) => {
+ const mode = comp.children.mode.getView();
+ const onUIEvent = comp.children.onUIEvent.getView();
+ const onEvent = comp.children.onEvent.getView();
+ const echartsCompRef = useRef();
+ const [chartSize, setChartSize] = useState();
+ const firstResize = useRef(true);
+ const theme = useContext(ThemeContext);
+ const defaultChartTheme = {
+ color: chartColorPalette,
+ backgroundColor: "#fff",
+ };
+
+ let themeConfig = defaultChartTheme;
+ try {
+ themeConfig = theme?.theme.chart ? JSON.parse(theme?.theme.chart) : defaultChartTheme;
+ } catch (error) {
+ log.error('theme chart error: ', error);
+ }
+
+ const triggerClickEvent = async (dispatch: any, action: CompAction) => {
+ await getPromiseAfterDispatch(
+ dispatch,
+ action,
+ { autoHandleAfterReduce: true }
+ );
+ onEvent('click');
+ }
+
+ useEffect(() => {
+ const echartsCompInstance = echartsCompRef?.current?.getEchartsInstance();
+ if (!echartsCompInstance) {
+ return _.noop;
+ }
+ echartsCompInstance?.on("click", (param: any) => {
+ document.dispatchEvent(new CustomEvent("clickEvent", {
+ bubbles: true,
+ detail: {
+ action: 'click',
+ data: param.data,
+ }
+ }));
+ triggerClickEvent(
+ comp.dispatch,
+ changeChildAction("lastInteractionData", param.data, false)
+ );
+ });
+ return () => {
+ echartsCompInstance?.off("click");
+ document.removeEventListener('clickEvent', clickEventCallback)
+ };
+ }, []);
+
+ useEffect(() => {
+ // bind events
+ const echartsCompInstance = echartsCompRef?.current?.getEchartsInstance();
+ if (!echartsCompInstance) {
+ return _.noop;
+ }
+ echartsCompInstance?.on("selectchanged", (param: any) => {
+ const option: any = echartsCompInstance?.getOption();
+ document.dispatchEvent(new CustomEvent("clickEvent", {
+ bubbles: true,
+ detail: {
+ action: param.fromAction,
+ data: getSelectedPoints(param, option)
+ }
+ }));
+
+ if (param.fromAction === "select") {
+ comp.dispatch(changeChildAction("selectedPoints", getSelectedPoints(param, option), false));
+ onUIEvent("select");
+ } else if (param.fromAction === "unselect") {
+ comp.dispatch(changeChildAction("selectedPoints", getSelectedPoints(param, option), false));
+ onUIEvent("unselect");
+ }
+
+ triggerClickEvent(
+ comp.dispatch,
+ changeChildAction("lastInteractionData", getSelectedPoints(param, option), false)
+ );
+ });
+ // unbind
+ return () => {
+ echartsCompInstance?.off("selectchanged");
+ document.removeEventListener('clickEvent', clickEventCallback)
+ };
+ }, [onUIEvent]);
+
+ const echartsConfigChildren = _.omit(comp.children, echartsConfigOmitChildren);
+ const childrenProps = childrenToProps(echartsConfigChildren);
+
+ const option = useMemo(() => {
+ return getEchartsConfig(
+ childrenProps as ToViewReturn,
+ chartSize,
+ themeConfig
+ );
+ }, [theme, childrenProps, chartSize, ...Object.values(echartsConfigChildren)]);
+
+ return (
+ {
+ if (w && h) {
+ setChartSize({ w: w, h: h });
+ }
+ if (!firstResize.current) {
+ // ignore the first resize, which will impact the loading animation
+ echartsCompRef.current?.getEchartsInstance().resize();
+ } else {
+ firstResize.current = false;
+ }
+ }}
+ >
+ (echartsCompRef.current = e)}
+ style={{ height: "100%" }}
+ notMerge
+ lazyUpdate
+ opts={{ locale: getEchartsLocale() }}
+ option={option}
+ mode={mode}
+ />
+
+ );
+});
+
+function getYAxisFormatContextValue(
+ data: Array,
+ yAxisType: EchartsAxisType,
+ yAxisName?: string
+) {
+ const dataSample = yAxisName && data.length > 0 && data[0][yAxisName];
+ let contextValue = dataSample;
+ if (yAxisType === "time") {
+ // to timestamp
+ const time =
+ typeof dataSample === "number" || typeof dataSample === "string"
+ ? new Date(dataSample).getTime()
+ : null;
+ if (time) contextValue = time;
+ }
+ return contextValue;
+}
+
+BoxplotChartTmpComp = class extends BoxplotChartTmpComp {
+ private lastYAxisFormatContextVal?: JSONValue;
+ private lastColorContext?: JSONObject;
+
+ updateContext(comp: this) {
+ // the context value of axis format
+ let resultComp = comp;
+ const data = comp.children.data.getView();
+ const yAxisContextValue = getYAxisFormatContextValue(
+ data,
+ comp.children.yConfig.children.yAxisType.getView(),
+ );
+ if (yAxisContextValue !== comp.lastYAxisFormatContextVal) {
+ comp.lastYAxisFormatContextVal = yAxisContextValue;
+ resultComp = comp.setChild(
+ "yConfig",
+ comp.children.yConfig.reduce(
+ wrapChildAction(
+ "formatter",
+ AxisFormatterComp.changeContextDataAction({ value: yAxisContextValue })
+ )
+ )
+ );
+ }
+ return resultComp;
+ }
+
+ override reduce(action: CompAction): this {
+ const comp = super.reduce(action);
+ if (action.type === CompActionTypes.UPDATE_NODES_V2) {
+ const newData = comp.children.data.getView();
+ // data changes
+ if (comp.children.data !== this.children.data) {
+ setTimeout(() => {
+ // update x-axis value
+ const keys = getDataKeys(newData);
+ if (keys.length > 0 && !keys.includes(comp.children.xAxisKey.getView())) {
+ comp.children.xAxisKey.dispatch(changeValueAction(keys[0] || ""));
+ }
+ if (keys.length > 0 && !keys.includes(comp.children.yAxisKey.getView())) {
+ comp.children.yAxisKey.dispatch(changeValueAction(keys[1] || ""));
+ }
+ }, 0);
+ }
+ return this.updateContext(comp);
+ }
+ return comp;
+ }
+
+ override autoHeight(): boolean {
+ return false;
+ }
+};
+
+let BoxplotChartComp = withExposingConfigs(BoxplotChartTmpComp, [
+ depsConfig({
+ name: "selectedPoints",
+ desc: trans("chart.selectedPointsDesc"),
+ depKeys: ["selectedPoints"],
+ func: (input) => {
+ return input.selectedPoints;
+ },
+ }),
+ depsConfig({
+ name: "lastInteractionData",
+ desc: trans("chart.lastInteractionDataDesc"),
+ depKeys: ["lastInteractionData"],
+ func: (input) => {
+ return input.lastInteractionData;
+ },
+ }),
+ depsConfig({
+ name: "data",
+ desc: trans("chart.dataDesc"),
+ depKeys: ["data", "mode"],
+ func: (input) =>[] ,
+ }),
+ new NameConfig("title", trans("chart.titleDesc")),
+]);
+
+
+export const BoxplotChartCompWithDefault = withDefault(BoxplotChartComp, {
+ xAxisKey: "date",
+});
diff --git a/client/packages/lowcoder-comps/src/comps/boxplotChartComp/boxplotChartConstants.tsx b/client/packages/lowcoder-comps/src/comps/boxplotChartComp/boxplotChartConstants.tsx
new file mode 100644
index 000000000..ffec6b31e
--- /dev/null
+++ b/client/packages/lowcoder-comps/src/comps/boxplotChartComp/boxplotChartConstants.tsx
@@ -0,0 +1,248 @@
+import {
+ jsonControl,
+ stateComp,
+ toJSONObjectArray,
+ toObject,
+ BoolControl,
+ ColorControl,
+ withDefault,
+ StringControl,
+ NumberControl,
+ dropdownControl,
+ list,
+ eventHandlerControl,
+ valueComp,
+ withType,
+ uiChildren,
+ clickEvent,
+ toArray,
+ styleControl,
+ EchartDefaultTextStyle,
+ EchartDefaultChartStyle,
+ MultiCompBuilder,
+} from "lowcoder-sdk";
+import { RecordConstructorToComp, RecordConstructorToView } from "lowcoder-core";
+import { XAxisConfig, YAxisConfig } from "../basicChartComp/chartConfigs/cartesianAxisConfig";
+import { LegendConfig } from "../basicChartComp/chartConfigs/legendConfig";
+import { EchartsLegendConfig } from "../basicChartComp/chartConfigs/echartsLegendConfig";
+import { EchartsLabelConfig } from "../basicChartComp/chartConfigs/echartsLabelConfig";
+import { EChartsOption } from "echarts";
+import { i18nObjs, trans } from "i18n/comps";
+import {EchartsTitleVerticalConfig} from "../chartComp/chartConfigs/echartsTitleVerticalConfig";
+import {EchartsTitleConfig} from "../basicChartComp/chartConfigs/echartsTitleConfig";
+
+export const UIEventOptions = [
+ {
+ label: trans("chart.select"),
+ value: "select",
+ description: trans("chart.selectDesc"),
+ },
+ {
+ label: trans("chart.unSelect"),
+ value: "unselect",
+ description: trans("chart.unselectDesc"),
+ },
+] as const;
+
+export const XAxisDirectionOptions = [
+ {
+ label: trans("chart.horizontal"),
+ value: "horizontal",
+ },
+ {
+ label: trans("chart.vertical"),
+ value: "vertical",
+ },
+] as const;
+
+export type XAxisDirectionType = ValueFromOption;
+
+export const noDataAxisConfig = {
+ animation: false,
+ xAxis: {
+ type: "category",
+ name: trans("chart.noData"),
+ nameLocation: "middle",
+ data: [],
+ axisLine: {
+ lineStyle: {
+ color: "#8B8FA3",
+ },
+ },
+ },
+ yAxis: {
+ type: "value",
+ axisLabel: {
+ color: "#8B8FA3",
+ },
+ splitLine: {
+ lineStyle: {
+ color: "#F0F0F0",
+ },
+ },
+ },
+ tooltip: {
+ show: false,
+ },
+ series: [
+ {
+ data: [700],
+ type: "line",
+ itemStyle: {
+ opacity: 0,
+ },
+ },
+ ],
+} as EChartsOption;
+
+export const noDataBoxplotChartConfig = {
+ animation: false,
+ tooltip: {
+ show: false,
+ },
+ legend: {
+ formatter: trans("chart.unknown"),
+ top: "bottom",
+ selectedMode: false,
+ },
+ color: ["#B8BBCC", "#CED0D9", "#DCDEE6", "#E6E6EB"],
+ series: [
+ {
+ type: "boxplot",
+ radius: "35%",
+ center: ["25%", "50%"],
+ silent: true,
+ label: {
+ show: false,
+ },
+ data: [
+ {
+ name: "1",
+ value: 70,
+ },
+ {
+ name: "2",
+ value: 68,
+ },
+ {
+ name: "3",
+ value: 48,
+ },
+ {
+ name: "4",
+ value: 40,
+ },
+ ],
+ },
+ {
+ type: "boxplot",
+ radius: "35%",
+ center: ["75%", "50%"],
+ silent: true,
+ label: {
+ show: false,
+ },
+ data: [
+ {
+ name: "1",
+ value: 70,
+ },
+ {
+ name: "2",
+ value: 68,
+ },
+ {
+ name: "3",
+ value: 48,
+ },
+ {
+ name: "4",
+ value: 40,
+ },
+ ],
+ },
+ ],
+} as EChartsOption;
+
+export type ChartSize = { w: number; h: number };
+
+export const getDataKeys = (data: Array) => {
+ if (!data) {
+ return [];
+ }
+ const dataKeys: Array = [];
+ data[0].forEach((key) => {
+ if (!dataKeys.includes(key)) {
+ dataKeys.push(key);
+ }
+ });
+ return dataKeys;
+};
+
+export const chartUiModeChildren = {
+ title: withDefault(StringControl, trans("echarts.defaultTitle")),
+ data: jsonControl(toArray, i18nObjs.defaultDatasourceBoxplot),
+ xAxisKey: valueComp(""), // x-axis, key from data
+ xAxisDirection: dropdownControl(XAxisDirectionOptions, "horizontal"),
+ xAxisData: jsonControl(toArray, []),
+ yAxisKey: valueComp(""), // x-axis, key from data
+ xConfig: XAxisConfig,
+ yConfig: YAxisConfig,
+ legendConfig: LegendConfig,
+ onUIEvent: eventHandlerControl(UIEventOptions),
+};
+
+let chartJsonModeChildren: any = {
+ echartsOption: jsonControl(toObject, i18nObjs.defaultEchartsJsonOption),
+ echartsTitle: withDefault(StringControl, trans("echarts.defaultTitle")),
+ echartsLegendConfig: EchartsLegendConfig,
+ echartsLabelConfig: EchartsLabelConfig,
+ echartsTitleVerticalConfig: EchartsTitleVerticalConfig,
+ echartsTitleConfig:EchartsTitleConfig,
+
+ left:withDefault(NumberControl,trans('chart.defaultLeft')),
+ right:withDefault(NumberControl,trans('chart.defaultRight')),
+ top:withDefault(NumberControl,trans('chart.defaultTop')),
+ bottom:withDefault(NumberControl,trans('chart.defaultBottom')),
+
+ tooltip: withDefault(BoolControl, true),
+ legendVisibility: withDefault(BoolControl, true),
+}
+
+if (EchartDefaultChartStyle && EchartDefaultTextStyle) {
+ chartJsonModeChildren = {
+ ...chartJsonModeChildren,
+ chartStyle: styleControl(EchartDefaultChartStyle, 'chartStyle'),
+ titleStyle: styleControl(EchartDefaultTextStyle, 'titleStyle'),
+ xAxisStyle: styleControl(EchartDefaultTextStyle, 'xAxis'),
+ yAxisStyle: styleControl(EchartDefaultTextStyle, 'yAxisStyle'),
+ legendStyle: styleControl(EchartDefaultTextStyle, 'legendStyle'),
+ }
+}
+
+export type UIChartDataType = {
+ seriesName: string;
+ // coordinate chart
+ x?: any;
+ y?: any;
+ // boxplot or funnel
+ itemName?: any;
+ value?: any;
+};
+
+export type NonUIChartDataType = {
+ name: string;
+ value: any;
+}
+
+export const boxplotChartChildrenMap = {
+ selectedPoints: stateComp>([]),
+ lastInteractionData: stateComp | NonUIChartDataType>({}),
+ onEvent: eventHandlerControl([clickEvent] as const),
+ ...chartUiModeChildren,
+ ...chartJsonModeChildren,
+};
+
+const chartUiChildrenMap = uiChildren(boxplotChartChildrenMap);
+export type ChartCompPropsType = RecordConstructorToView;
+export type ChartCompChildrenType = RecordConstructorToComp;
diff --git a/client/packages/lowcoder-comps/src/comps/boxplotChartComp/boxplotChartPropertyView.tsx b/client/packages/lowcoder-comps/src/comps/boxplotChartComp/boxplotChartPropertyView.tsx
new file mode 100644
index 000000000..b6694e910
--- /dev/null
+++ b/client/packages/lowcoder-comps/src/comps/boxplotChartComp/boxplotChartPropertyView.tsx
@@ -0,0 +1,95 @@
+import { changeChildAction, CompAction } from "lowcoder-core";
+import { ChartCompChildrenType, getDataKeys } from "./boxplotChartConstants";
+import {
+ CustomModal,
+ Dropdown,
+ hiddenPropertyView,
+ Option,
+ RedButton,
+ Section,
+ sectionNames,
+ controlItem,
+} from "lowcoder-sdk";
+import { trans } from "i18n/comps";
+
+export function boxplotChartPropertyView(
+ children: ChartCompChildrenType,
+ dispatch: (action: CompAction) => void
+) {
+ const columnOptions = getDataKeys(children.data.getView()).map((key) => ({
+ label: key,
+ value: key,
+ }));
+
+ const uiModePropertyView = (
+ <>
+
+ {
+ dispatch(changeChildAction("xAxisKey", value));
+ }}
+ />
+ {
+ dispatch(changeChildAction("yAxisKey", value));
+ }}
+ />
+
+
+
+ {children.onUIEvent.propertyView({title: trans("chart.chartEventHandlers")})}
+
+
+ {children.onEvent.propertyView()}
+
+
+
+ {children.echartsTitleConfig.getPropertyView()}
+ {children.echartsTitleVerticalConfig.getPropertyView()}
+ {children.legendConfig.getPropertyView()}
+ {children.title.propertyView({ label: trans("chart.title") })}
+ {children.left.propertyView({ label: trans("chart.left"), tooltip: trans("echarts.leftTooltip") })}
+ {children.right.propertyView({ label: trans("chart.right"), tooltip: trans("echarts.rightTooltip") })}
+ {children.top.propertyView({ label: trans("chart.top"), tooltip: trans("echarts.topTooltip") })}
+ {children.bottom.propertyView({ label: trans("chart.bottom"), tooltip: trans("echarts.bottomTooltip") })}
+ {hiddenPropertyView(children)}
+ {children.tooltip.propertyView({label: trans("echarts.tooltip"), tooltip: trans("echarts.tooltipTooltip")})}
+
+
+ {children.chartStyle?.getPropertyView()}
+
+
+ {children.titleStyle?.getPropertyView()}
+
+
+ {children.xAxisStyle?.getPropertyView()}
+
+
+ {children.yAxisStyle?.getPropertyView()}
+
+
+ {children.data.propertyView({
+ label: trans("chart.data"),
+ })}
+
+ >
+ );
+
+ const getChatConfigByMode = (mode: string) => {
+ switch(mode) {
+ case "ui":
+ return uiModePropertyView;
+ }
+ }
+ return (
+ <>
+ {getChatConfigByMode(children.mode.getView())}
+ >
+ );
+}
diff --git a/client/packages/lowcoder-comps/src/comps/boxplotChartComp/boxplotChartUtils.ts b/client/packages/lowcoder-comps/src/comps/boxplotChartComp/boxplotChartUtils.ts
new file mode 100644
index 000000000..2bc1904d4
--- /dev/null
+++ b/client/packages/lowcoder-comps/src/comps/boxplotChartComp/boxplotChartUtils.ts
@@ -0,0 +1,293 @@
+import {
+ ChartCompPropsType,
+ ChartSize,
+ noDataBoxplotChartConfig,
+} from "comps/boxplotChartComp/boxplotChartConstants";
+import { EChartsOptionWithMap } from "../basicChartComp/reactEcharts/types";
+import _ from "lodash";
+import { googleMapsApiUrl } from "../basicChartComp/chartConfigs/chartUrls";
+import parseBackground from "../../util/gradientBackgroundColor";
+import {chartStyleWrapper, styleWrapper} from "../../util/styleWrapper";
+// Define the configuration interface to match the original transform
+
+interface AggregateConfig {
+ resultDimensions: Array<{
+ name: string;
+ from: string;
+ method?: string; // e.g., 'min', 'Q1', 'median', 'Q3', 'max'
+ }>;
+ groupBy: string;
+}
+
+// Custom transform function
+function customAggregateTransform(params: {
+ upstream: { source: any[] };
+ config: AggregateConfig;
+}): any[] {
+ const { upstream, config } = params;
+ const data = upstream.source;
+
+ // Assume data is an array of arrays, with the first row as headers
+ const headers = data[0];
+ const rows = data.slice(1);
+
+ // Find the index of the groupBy column
+ const groupByIndex = headers.indexOf(config.groupBy);
+ if (groupByIndex === -1) {
+ return [];
+ }
+
+ // Group rows by the groupBy column
+ const groups: { [key: string]: any[][] } = {};
+ rows.forEach(row => {
+ const key = row[groupByIndex];
+ if (!groups[key]) {
+ groups[key] = [];
+ }
+ groups[key].push(row);
+ });
+
+ // Define aggregation functions
+ const aggregators: {
+ [method: string]: (values: number[]) => number;
+ } = {
+ min: values => Math.min(...values),
+ max: values => Math.max(...values),
+ Q1: values => percentile(values, 25),
+ median: values => percentile(values, 50),
+ Q3: values => percentile(values, 75),
+ };
+
+ // Helper function to calculate percentiles (Q1, median, Q3)
+ function percentile(arr: number[], p: number): number {
+ const sorted = arr.slice().sort((a, b) => a - b);
+ const index = (p / 100) * (sorted.length - 1);
+ const i = Math.floor(index);
+ const f = index - i;
+ if (i === sorted.length - 1) {
+ return sorted[i];
+ }
+ return sorted[i] + f * (sorted[i + 1] - sorted[i]);
+ }
+
+ // Prepare output headers from resultDimensions
+ const outputHeaders = config.resultDimensions.map(dim => dim.name);
+
+ // Compute aggregated data for each group
+ const aggregatedData: any[][] = [];
+ for (const key in groups) {
+ const groupRows = groups[key];
+ const row: any[] = [];
+
+ config.resultDimensions.forEach(dim => {
+ if (dim.from === config.groupBy) {
+ // Include the group key directly
+ row.push(key);
+ } else {
+ // Find the index of the 'from' column
+ const fromIndex = headers.indexOf(dim.from);
+ if (fromIndex === -1) {
+ return;
+ }
+ // Extract values for the 'from' column in this group
+ const values = groupRows
+ .map(r => parseFloat(r[fromIndex]))
+ .filter(v => !isNaN(v));
+ if (dim.method && aggregators[dim.method]) {
+ // Apply the aggregation method
+ row.push(aggregators[dim.method](values));
+ } else {
+ return;
+ }
+ }
+ });
+
+ aggregatedData.push(row);
+ }
+
+ // Return the transformed data with headers
+ return [outputHeaders, ...aggregatedData];
+}
+
+export const echartsConfigOmitChildren = [
+ "hidden",
+ "selectedPoints",
+ "onUIEvent",
+ "mapInstance"
+] as const;
+type EchartsConfigProps = Omit;
+
+// https://echarts.apache.org/en/option.html
+export function getEchartsConfig(
+ props: EchartsConfigProps,
+ chartSize?: ChartSize,
+ theme?: any,
+): EChartsOptionWithMap {
+ const gridPos = {
+ left: `${props?.left}%`,
+ right: `${props?.right}%`,
+ bottom: `${props?.bottom}%`,
+ top: `${props?.top}%`,
+ };
+
+ let config: any = {
+ title: {
+ text: props.title,
+ top: props.echartsTitleVerticalConfig.top,
+ left:props.echartsTitleConfig.top,
+ textStyle: {
+ ...styleWrapper(props?.titleStyle, theme?.titleStyle)
+ }
+ },
+ backgroundColor: parseBackground( props?.chartStyle?.background || theme?.chartStyle?.backgroundColor || "#FFFFFF"),
+ tooltip: props.tooltip && {
+ trigger: "axis",
+ axisPointer: {
+ type: "line",
+ lineStyle: {
+ color: "rgba(0,0,0,0.2)",
+ width: 2,
+ type: "solid"
+ }
+ }
+ },
+ grid: {
+ ...gridPos,
+ containLabel: true,
+ },
+ xAxis: {
+ name: props.xAxisKey,
+ nameLocation: 'middle',
+ nameGap: 30,
+ scale: true,
+ axisLabel: {
+ ...styleWrapper(props?.xAxisStyle, theme?.xAxisStyle, 11)
+ }
+ },
+ yAxis: {
+ type: "category",
+ axisLabel: {
+ ...styleWrapper(props?.yAxisStyle, theme?.yAxisStyle, 11)
+ }
+ },
+ dataset: [
+ {
+ id: 'raw',
+ source: customAggregateTransform({upstream: {source: props.data as any[]}, config:{
+ resultDimensions: [
+ { name: 'min', from: props.xAxisKey, method: 'min' },
+ { name: 'Q1', from: props.xAxisKey, method: 'Q1' },
+ { name: 'median', from: props.xAxisKey, method: 'median' },
+ { name: 'Q3', from: props.xAxisKey, method: 'Q3' },
+ { name: 'max', from: props.xAxisKey, method: 'max' },
+ { name: props.yAxisKey, from: props.yAxisKey }
+ ],
+ groupBy: props.yAxisKey
+ }}),
+ },
+ {
+ id: 'finaldataset',
+ fromDatasetId: 'raw',
+ transform: [
+ {
+ type: 'sort',
+ config: {
+ dimension: 'Q3',
+ order: 'asc'
+ }
+ }
+ ]
+ }
+ ],
+ };
+
+ if (props.data.length <= 0) {
+ // no data
+ return {
+ ...config,
+ ...noDataBoxplotChartConfig,
+ };
+ }
+ const yAxisConfig = props.yConfig();
+ // y-axis is category and time, data doesn't need to aggregate
+ let transformedData = props.data;
+
+ config = {
+ ...config,
+ series: [{
+ name: props.xAxisKey,
+ type: 'boxplot',
+ datasetId: 'finaldataset',
+ encode: {
+ x: ['min', 'Q1', 'median', 'Q3', 'max'],
+ y: props.yAxisKey,
+ itemName: [props.yAxisKey],
+ tooltip: ['min', 'Q1', 'median', 'Q3', 'max']
+ },
+ itemStyle: {
+ color: '#b8c5f2',
+ ...chartStyleWrapper(props?.chartStyle, theme?.chartStyle)
+ },
+ }],
+ };
+ if(config.series[0].itemStyle.borderWidth === 0) config.series[0].itemStyle.borderWidth = 1;
+
+ // console.log("Echarts transformedData and config", transformedData, config);
+ return config;
+}
+
+export function getSelectedPoints(param: any, option: any) {
+ const series = option.series;
+ const dataSource = _.isArray(option.dataset) && option.dataset[0]?.source;
+ if (series && dataSource) {
+ return param.selected.flatMap((selectInfo: any) => {
+ const seriesInfo = series[selectInfo.seriesIndex];
+ if (!seriesInfo || !seriesInfo.encode) {
+ return [];
+ }
+ return selectInfo.dataIndex.map((index: any) => {
+ const commonResult = {
+ seriesName: seriesInfo.name,
+ };
+ if (seriesInfo.encode.itemName && seriesInfo.encode.value) {
+ return {
+ ...commonResult,
+ itemName: dataSource[index][seriesInfo.encode.itemName],
+ value: dataSource[index][seriesInfo.encode.value],
+ };
+ } else {
+ return {
+ ...commonResult,
+ x: dataSource[index][seriesInfo.encode.x],
+ y: dataSource[index][seriesInfo.encode.y],
+ };
+ }
+ });
+ });
+ }
+ return [];
+}
+
+export function loadGoogleMapsScript(apiKey: string) {
+ const mapsUrl = `${googleMapsApiUrl}?key=${apiKey}`;
+ const scripts = document.getElementsByTagName('script');
+ // is script already loaded
+ let scriptIndex = _.findIndex(scripts, (script) => script.src.endsWith(mapsUrl));
+ if(scriptIndex > -1) {
+ return scripts[scriptIndex];
+ }
+ // is script loaded with diff api_key, remove the script and load again
+ scriptIndex = _.findIndex(scripts, (script) => script.src.startsWith(googleMapsApiUrl));
+ if(scriptIndex > -1) {
+ scripts[scriptIndex].remove();
+ }
+
+ const script = document.createElement("script");
+ script.type = "text/javascript";
+ script.src = mapsUrl;
+ script.async = true;
+ script.defer = true;
+ window.document.body.appendChild(script);
+
+ return script;
+}
diff --git a/client/packages/lowcoder-comps/src/comps/chartComp/chartConfigs/barChartConfig.tsx b/client/packages/lowcoder-comps/src/comps/chartComp/chartConfigs/barChartConfig.tsx
index 6c91fe252..707b16170 100644
--- a/client/packages/lowcoder-comps/src/comps/chartComp/chartConfigs/barChartConfig.tsx
+++ b/client/packages/lowcoder-comps/src/comps/chartComp/chartConfigs/barChartConfig.tsx
@@ -5,7 +5,7 @@ import {
showLabelPropertyView,
} from "lowcoder-sdk";
import { BarSeriesOption } from "echarts";
-import { trans } from "i18n/comps";
+import { i18nObjs, trans } from "i18n/comps";
const BarTypeOptions = [
{
diff --git a/client/packages/lowcoder-comps/src/comps/line3dChartComp/images/default_ambient_cubemap_texture.hdr b/client/packages/lowcoder-comps/src/comps/line3dChartComp/images/default_ambient_cubemap_texture.hdr
new file mode 100644
index 000000000..4d53b3609
Binary files /dev/null and b/client/packages/lowcoder-comps/src/comps/line3dChartComp/images/default_ambient_cubemap_texture.hdr differ
diff --git a/client/packages/lowcoder-comps/src/comps/line3dChartComp/images/default_base_texture.jpg b/client/packages/lowcoder-comps/src/comps/line3dChartComp/images/default_base_texture.jpg
new file mode 100644
index 000000000..c4a5d335c
Binary files /dev/null and b/client/packages/lowcoder-comps/src/comps/line3dChartComp/images/default_base_texture.jpg differ
diff --git a/client/packages/lowcoder-comps/src/comps/line3dChartComp/images/default_environment.jpg b/client/packages/lowcoder-comps/src/comps/line3dChartComp/images/default_environment.jpg
new file mode 100644
index 000000000..314999840
Binary files /dev/null and b/client/packages/lowcoder-comps/src/comps/line3dChartComp/images/default_environment.jpg differ
diff --git a/client/packages/lowcoder-comps/src/comps/line3dChartComp/images/default_height_texture.jpg b/client/packages/lowcoder-comps/src/comps/line3dChartComp/images/default_height_texture.jpg
new file mode 100644
index 000000000..9f8dcdf31
Binary files /dev/null and b/client/packages/lowcoder-comps/src/comps/line3dChartComp/images/default_height_texture.jpg differ
diff --git a/client/packages/lowcoder-comps/src/comps/line3dChartComp/line3dChartComp.tsx b/client/packages/lowcoder-comps/src/comps/line3dChartComp/line3dChartComp.tsx
new file mode 100644
index 000000000..712e224b2
--- /dev/null
+++ b/client/packages/lowcoder-comps/src/comps/line3dChartComp/line3dChartComp.tsx
@@ -0,0 +1,282 @@
+import {
+ changeChildAction,
+ changeValueAction,
+ CompAction,
+ CompActionTypes,
+ wrapChildAction,
+} from "lowcoder-core";
+import { AxisFormatterComp, EchartsAxisType } from "../basicChartComp/chartConfigs/cartesianAxisConfig";
+import { line3dChartChildrenMap, ChartSize, getDataKeys } from "./line3dChartConstants";
+import { line3dChartPropertyView } from "./line3dChartPropertyView";
+import _ from "lodash";
+import { useContext, useEffect, useMemo, useRef, useState } from "react";
+import ReactResizeDetector from "react-resize-detector";
+import ReactECharts from "../basicChartComp/reactEcharts";
+import * as echarts from "echarts";
+import {
+ childrenToProps,
+ depsConfig,
+ genRandomKey,
+ NameConfig,
+ UICompBuilder,
+ withDefault,
+ withExposingConfigs,
+ withViewFn,
+ ThemeContext,
+ chartColorPalette,
+ getPromiseAfterDispatch,
+ dropdownControl,
+} from "lowcoder-sdk";
+import { getEchartsLocale, i18nObjs, trans } from "i18n/comps";
+import {
+ echartsConfigOmitChildren,
+ getEchartsConfig,
+ getSelectedPoints,
+} from "./line3dChartUtils";
+import 'echarts-extension-gmap';
+import log from "loglevel";
+
+let clickEventCallback = () => {};
+
+const chartModeOptions = [
+ {
+ label: "UI",
+ value: "ui",
+ }
+] as const;
+
+let Line3DChartTmpComp = (function () {
+ return new UICompBuilder({mode:dropdownControl(chartModeOptions,'ui'),...line3dChartChildrenMap}, () => null)
+ .setPropertyViewFn(line3dChartPropertyView)
+ .build();
+})();
+
+Line3DChartTmpComp = withViewFn(Line3DChartTmpComp, (comp) => {
+ const mode = comp.children.mode.getView();
+ const onUIEvent = comp.children.onUIEvent.getView();
+ const onEvent = comp.children.onEvent.getView();
+ const echartsCompRef = useRef();
+ const [chartSize, setChartSize] = useState();
+ const firstResize = useRef(true);
+ const theme = useContext(ThemeContext);
+ const defaultChartTheme = {
+ color: chartColorPalette,
+ backgroundColor: "#fff",
+ };
+
+ let themeConfig = defaultChartTheme;
+ try {
+ themeConfig = theme?.theme.chart ? JSON.parse(theme?.theme.chart) : defaultChartTheme;
+ } catch (error) {
+ log.error('theme chart error: ', error);
+ }
+
+ const triggerClickEvent = async (dispatch: any, action: CompAction) => {
+ await getPromiseAfterDispatch(
+ dispatch,
+ action,
+ { autoHandleAfterReduce: true }
+ );
+ onEvent('click');
+ }
+
+ useEffect(() => {
+ const echartsCompInstance = echartsCompRef?.current?.getEchartsInstance();
+ if (!echartsCompInstance) {
+ return _.noop;
+ }
+ echartsCompInstance?.on("click", (param: any) => {
+ document.dispatchEvent(new CustomEvent("clickEvent", {
+ bubbles: true,
+ detail: {
+ action: 'click',
+ data: param.data,
+ }
+ }));
+ triggerClickEvent(
+ comp.dispatch,
+ changeChildAction("lastInteractionData", param.data, false)
+ );
+ });
+ return () => {
+ echartsCompInstance?.off("click");
+ document.removeEventListener('clickEvent', clickEventCallback)
+ };
+ }, []);
+
+ useEffect(() => {
+ // bind events
+ const echartsCompInstance = echartsCompRef?.current?.getEchartsInstance();
+ if (!echartsCompInstance) {
+ return _.noop;
+ }
+ echartsCompInstance?.on("selectchanged", (param: any) => {
+ const option: any = echartsCompInstance?.getOption();
+ document.dispatchEvent(new CustomEvent("clickEvent", {
+ bubbles: true,
+ detail: {
+ action: param.fromAction,
+ data: getSelectedPoints(param, option)
+ }
+ }));
+
+ if (param.fromAction === "select") {
+ comp.dispatch(changeChildAction("selectedPoints", getSelectedPoints(param, option), false));
+ onUIEvent("select");
+ } else if (param.fromAction === "unselect") {
+ comp.dispatch(changeChildAction("selectedPoints", getSelectedPoints(param, option), false));
+ onUIEvent("unselect");
+ }
+
+ triggerClickEvent(
+ comp.dispatch,
+ changeChildAction("lastInteractionData", getSelectedPoints(param, option), false)
+ );
+ });
+ // unbind
+ return () => {
+ echartsCompInstance?.off("selectchanged");
+ document.removeEventListener('clickEvent', clickEventCallback)
+ };
+ }, [onUIEvent]);
+
+ const echartsConfigChildren = _.omit(comp.children, echartsConfigOmitChildren);
+ const childrenProps = childrenToProps(echartsConfigChildren);
+
+ const option = useMemo(() => {
+ return getEchartsConfig(
+ childrenProps as ToViewReturn,
+ chartSize,
+ themeConfig
+ );
+ }, [theme, childrenProps, chartSize, ...Object.values(echartsConfigChildren)]);
+
+ return (
+ {
+ if (w && h) {
+ setChartSize({ w: w, h: h });
+ }
+ if (!firstResize.current) {
+ // ignore the first resize, which will impact the loading animation
+ echartsCompRef.current?.getEchartsInstance().resize();
+ } else {
+ firstResize.current = false;
+ }
+ }}
+ >
+ (echartsCompRef.current = e)}
+ style={{ height: "100%" }}
+ notMerge
+ lazyUpdate
+ opts={{ locale: getEchartsLocale() }}
+ option={option}
+ mode={mode}
+ />
+
+ );
+});
+
+function getYAxisFormatContextValue(
+ data: Array,
+ yAxisType: EchartsAxisType,
+ yAxisName?: string
+) {
+ const dataSample = yAxisName && data.length > 0 && data[0][yAxisName];
+ let contextValue = dataSample;
+ if (yAxisType === "time") {
+ // to timestamp
+ const time =
+ typeof dataSample === "number" || typeof dataSample === "string"
+ ? new Date(dataSample).getTime()
+ : null;
+ if (time) contextValue = time;
+ }
+ return contextValue;
+}
+
+Line3DChartTmpComp = class extends Line3DChartTmpComp {
+ private lastYAxisFormatContextVal?: JSONValue;
+ private lastColorContext?: JSONObject;
+
+ updateContext(comp: this) {
+ // the context value of axis format
+ let resultComp = comp;
+ const data = comp.children.data.getView();
+ const yAxisContextValue = getYAxisFormatContextValue(
+ data,
+ comp.children.yConfig.children.yAxisType.getView(),
+ );
+ if (yAxisContextValue !== comp.lastYAxisFormatContextVal) {
+ comp.lastYAxisFormatContextVal = yAxisContextValue;
+ resultComp = comp.setChild(
+ "yConfig",
+ comp.children.yConfig.reduce(
+ wrapChildAction(
+ "formatter",
+ AxisFormatterComp.changeContextDataAction({ value: yAxisContextValue })
+ )
+ )
+ );
+ }
+ return resultComp;
+ }
+
+ override reduce(action: CompAction): this {
+ const comp = super.reduce(action);
+ if (action.type === CompActionTypes.UPDATE_NODES_V2) {
+ const newData = comp.children.data.getView();
+ // data changes
+ if (comp.children.data !== this.children.data) {
+ setTimeout(() => {
+ // update x-axis value
+ const keys = getDataKeys(newData);
+ if (keys.length > 0 && !keys.includes(comp.children.xAxisKey.getView())) {
+ comp.children.xAxisKey.dispatch(changeValueAction(keys[0] || ""));
+ }
+ if (keys.length > 0 && !keys.includes(comp.children.yAxisKey.getView())) {
+ comp.children.yAxisKey.dispatch(changeValueAction(keys[1] || ""));
+ }
+ }, 0);
+ }
+ return this.updateContext(comp);
+ }
+ return comp;
+ }
+
+ override autoHeight(): boolean {
+ return false;
+ }
+};
+
+let Line3DChartComp = withExposingConfigs(Line3DChartTmpComp, [
+ depsConfig({
+ name: "selectedPoints",
+ desc: trans("chart.selectedPointsDesc"),
+ depKeys: ["selectedPoints"],
+ func: (input) => {
+ return input.selectedPoints;
+ },
+ }),
+ depsConfig({
+ name: "lastInteractionData",
+ desc: trans("chart.lastInteractionDataDesc"),
+ depKeys: ["lastInteractionData"],
+ func: (input) => {
+ return input.lastInteractionData;
+ },
+ }),
+ depsConfig({
+ name: "data",
+ desc: trans("chart.dataDesc"),
+ depKeys: ["data", "mode"],
+ func: (input) =>[] ,
+ }),
+ new NameConfig("title", trans("chart.titleDesc")),
+]);
+
+
+export const Line3DChartCompWithDefault = withDefault(Line3DChartComp, {
+ xAxisKey: "date",
+});
diff --git a/client/packages/lowcoder-comps/src/comps/line3dChartComp/line3dChartConstants.tsx b/client/packages/lowcoder-comps/src/comps/line3dChartComp/line3dChartConstants.tsx
new file mode 100644
index 000000000..41a405c55
--- /dev/null
+++ b/client/packages/lowcoder-comps/src/comps/line3dChartComp/line3dChartConstants.tsx
@@ -0,0 +1,176 @@
+import {
+ jsonControl,
+ stateComp,
+ toJSONObjectArray,
+ toObject,
+ BoolControl,
+ ColorControl,
+ withDefault,
+ StringControl,
+ NumberControl,
+ dropdownControl,
+ list,
+ eventHandlerControl,
+ valueComp,
+ withType,
+ uiChildren,
+ clickEvent,
+ toArray,
+ styleControl,
+ EchartDefaultTextStyle,
+ EchartDefaultChartStyle,
+ MultiCompBuilder,
+} from "lowcoder-sdk";
+import { RecordConstructorToComp, RecordConstructorToView } from "lowcoder-core";
+import { XAxisConfig, YAxisConfig } from "../basicChartComp/chartConfigs/cartesianAxisConfig";
+import { LegendConfig } from "../basicChartComp/chartConfigs/legendConfig";
+import { EchartsLegendConfig } from "../basicChartComp/chartConfigs/echartsLegendConfig";
+import { EchartsLabelConfig } from "../basicChartComp/chartConfigs/echartsLabelConfig";
+import { EChartsOption } from "echarts";
+import { i18nObjs, trans } from "i18n/comps";
+import {EchartsTitleVerticalConfig} from "../chartComp/chartConfigs/echartsTitleVerticalConfig";
+import {EchartsTitleConfig} from "../basicChartComp/chartConfigs/echartsTitleConfig";
+
+export const UIEventOptions = [
+ {
+ label: trans("chart.select"),
+ value: "select",
+ description: trans("chart.selectDesc"),
+ },
+ {
+ label: trans("chart.unSelect"),
+ value: "unselect",
+ description: trans("chart.unselectDesc"),
+ },
+] as const;
+
+export const XAxisDirectionOptions = [
+ {
+ label: trans("chart.horizontal"),
+ value: "horizontal",
+ },
+ {
+ label: trans("chart.vertical"),
+ value: "vertical",
+ },
+] as const;
+
+export type XAxisDirectionType = ValueFromOption;
+
+export const noDataAxisConfig = {
+ animation: false,
+ xAxis: {
+ type: "category",
+ name: trans("chart.noData"),
+ nameLocation: "middle",
+ data: [],
+ axisLine: {
+ lineStyle: {
+ color: "#8B8FA3",
+ },
+ },
+ },
+ yAxis: {
+ type: "value",
+ axisLabel: {
+ color: "#8B8FA3",
+ },
+ splitLine: {
+ lineStyle: {
+ color: "#F0F0F0",
+ },
+ },
+ },
+ tooltip: {
+ show: false,
+ },
+ series: [
+ {
+ data: [700],
+ type: "line",
+ itemStyle: {
+ opacity: 0,
+ },
+ },
+ ],
+} as EChartsOption;
+
+export const noDataLine3DChartConfig = {
+ animation: false,
+ tooltip: {
+ show: false,
+ },
+ legend: {
+ formatter: trans("chart.unknown"),
+ top: "bottom",
+ selectedMode: false,
+ },
+ color: ["#B8BBCC", "#CED0D9", "#DCDEE6", "#E6E6EB"],
+ series: [],
+} as EChartsOption;
+
+export type ChartSize = { w: number; h: number };
+
+export const getDataKeys = (data: Array) => {
+ if (!data) {
+ return [];
+ }
+ const dataKeys: Array = [];
+ data[0].forEach((key) => {
+ if (!dataKeys.includes(key)) {
+ dataKeys.push(key);
+ }
+ });
+ return dataKeys;
+};
+
+export const chartUiModeChildren = {
+ title: withDefault(StringControl, trans("echarts.defaultTitle")),
+ data: jsonControl(toArray, i18nObjs.defaultDatasource3DGlobe),
+ xAxisKey: valueComp(""), // x-axis, key from data
+ xAxisDirection: dropdownControl(XAxisDirectionOptions, "horizontal"),
+ xAxisData: jsonControl(toArray, []),
+ yAxisKey: valueComp(""), // x-axis, key from data
+ xConfig: XAxisConfig,
+ yConfig: YAxisConfig,
+ legendConfig: LegendConfig,
+ environment: withDefault(StringControl, trans("line3dchart.defaultEnvironment")),
+ baseTexture: withDefault(StringControl, trans("line3dchart.defaultBaseTexture")),
+ heightTexture: withDefault(StringControl, trans("line3dchart.defaultHeightTexture")),
+ background: withDefault(ColorControl, "black"),
+ lineStyleWidth: withDefault(NumberControl, 1),
+ lineStyleColor: withDefault(ColorControl, "rgb(50, 50, 150)"),
+ lineStyleOpacity: withDefault(NumberControl, 0.1),
+ effectShow: withDefault(BoolControl, true),
+ effectWidth: withDefault(NumberControl, 2),
+ effectLength: withDefault(NumberControl, 0.15),
+ effectOpacity: withDefault(NumberControl, 1),
+ effectColor: withDefault(ColorControl, 'rgb(30, 30, 60)'),
+ onUIEvent: eventHandlerControl(UIEventOptions),
+};
+
+export type UIChartDataType = {
+ seriesName: string;
+ // coordinate chart
+ x?: any;
+ y?: any;
+ // line3d or funnel
+ itemName?: any;
+ value?: any;
+};
+
+export type NonUIChartDataType = {
+ name: string;
+ value: any;
+}
+
+export const line3dChartChildrenMap = {
+ selectedPoints: stateComp>([]),
+ lastInteractionData: stateComp | NonUIChartDataType>({}),
+ onEvent: eventHandlerControl([clickEvent] as const),
+ ...chartUiModeChildren,
+};
+
+const chartUiChildrenMap = uiChildren(line3dChartChildrenMap);
+export type ChartCompPropsType = RecordConstructorToView;
+export type ChartCompChildrenType = RecordConstructorToComp;
diff --git a/client/packages/lowcoder-comps/src/comps/line3dChartComp/line3dChartPropertyView.tsx b/client/packages/lowcoder-comps/src/comps/line3dChartComp/line3dChartPropertyView.tsx
new file mode 100644
index 000000000..bbcebf358
--- /dev/null
+++ b/client/packages/lowcoder-comps/src/comps/line3dChartComp/line3dChartPropertyView.tsx
@@ -0,0 +1,62 @@
+import { changeChildAction, CompAction } from "lowcoder-core";
+import { ChartCompChildrenType, getDataKeys } from "./line3dChartConstants";
+import {
+ CustomModal,
+ Dropdown,
+ hiddenPropertyView,
+ Option,
+ RedButton,
+ Section,
+ sectionNames,
+ controlItem,
+} from "lowcoder-sdk";
+import { trans } from "i18n/comps";
+
+export function line3dChartPropertyView(
+ children: ChartCompChildrenType,
+ dispatch: (action: CompAction) => void
+) {
+ const uiModePropertyView = (
+ <>
+
+ {children.environment.propertyView({label: trans("line3dchart.environment")})}
+ {children.baseTexture.propertyView({label: trans("line3dchart.baseTexture")})}
+ {children.heightTexture.propertyView({label: trans("line3dchart.heightTexture")})}
+ {children.background.propertyView({label: trans("line3dchart.background")})}
+ {children.lineStyleWidth.propertyView({label: trans("line3dchart.lineStyleWidth")})}
+ {children.lineStyleColor.propertyView({label: trans("line3dchart.lineStyleColor")})}
+ {children.lineStyleOpacity.propertyView({label: trans("line3dchart.lineStyleOpacity")})}
+ {children.effectShow.propertyView({label: trans("line3dchart.effectShow")})}
+ {children.effectShow.getView() && children.effectWidth.propertyView({label: trans("line3dchart.effectTrailWidth")})}
+ {children.effectShow.getView() && children.effectLength.propertyView({label: trans("line3dchart.effectTrailLength")})}
+ {children.effectShow.getView() && children.effectOpacity.propertyView({label: trans("line3dchart.effectTrailOpacity")})}
+ {children.effectShow.getView() && children.effectColor.propertyView({label: trans("line3dchart.effectTrailColor")})}
+
+
+
+ {children.onUIEvent.propertyView({title: trans("chart.chartEventHandlers")})}
+
+
+ {children.onEvent.propertyView()}
+
+
+
+ {children.data.propertyView({
+ label: trans("chart.data"),
+ })}
+
+ >
+ );
+
+ const getChatConfigByMode = (mode: string) => {
+ switch(mode) {
+ case "ui":
+ return uiModePropertyView;
+ }
+ }
+ return (
+ <>
+ {getChatConfigByMode(children.mode.getView())}
+ >
+ );
+}
diff --git a/client/packages/lowcoder-comps/src/comps/line3dChartComp/line3dChartUtils.ts b/client/packages/lowcoder-comps/src/comps/line3dChartComp/line3dChartUtils.ts
new file mode 100644
index 000000000..d1be05edf
--- /dev/null
+++ b/client/packages/lowcoder-comps/src/comps/line3dChartComp/line3dChartUtils.ts
@@ -0,0 +1,239 @@
+import {
+ ChartCompPropsType,
+ ChartSize,
+ noDataLine3DChartConfig,
+} from "comps/line3dChartComp/line3dChartConstants";
+import { EChartsOptionWithMap } from "../basicChartComp/reactEcharts/types";
+import _ from "lodash";
+import { googleMapsApiUrl } from "../basicChartComp/chartConfigs/chartUrls";
+import parseBackground from "../../util/gradientBackgroundColor";
+import {chartStyleWrapper, styleWrapper} from "../../util/styleWrapper";
+// Define the configuration interface to match the original transform
+
+interface AggregateConfig {
+ resultDimensions: Array<{
+ name: string;
+ from: string;
+ method?: string; // e.g., 'min', 'Q1', 'median', 'Q3', 'max'
+ }>;
+ groupBy: string;
+}
+
+// Custom transform function
+function customAggregateTransform(params: {
+ upstream: { source: any[] };
+ config: AggregateConfig;
+}): any[] {
+ const { upstream, config } = params;
+ const data = upstream.source;
+
+ // Assume data is an array of arrays, with the first row as headers
+ const headers = data[0];
+ const rows = data.slice(1);
+
+ // Find the index of the groupBy column
+ const groupByIndex = headers.indexOf(config.groupBy);
+ if (groupByIndex === -1) {
+ return [];
+ }
+
+ // Group rows by the groupBy column
+ const groups: { [key: string]: any[][] } = {};
+ rows.forEach(row => {
+ const key = row[groupByIndex];
+ if (!groups[key]) {
+ groups[key] = [];
+ }
+ groups[key].push(row);
+ });
+
+ // Define aggregation functions
+ const aggregators: {
+ [method: string]: (values: number[]) => number;
+ } = {
+ min: values => Math.min(...values),
+ max: values => Math.max(...values),
+ Q1: values => percentile(values, 25),
+ median: values => percentile(values, 50),
+ Q3: values => percentile(values, 75),
+ };
+
+ // Helper function to calculate percentiles (Q1, median, Q3)
+ function percentile(arr: number[], p: number): number {
+ const sorted = arr.slice().sort((a, b) => a - b);
+ const index = (p / 100) * (sorted.length - 1);
+ const i = Math.floor(index);
+ const f = index - i;
+ if (i === sorted.length - 1) {
+ return sorted[i];
+ }
+ return sorted[i] + f * (sorted[i + 1] - sorted[i]);
+ }
+
+ // Prepare output headers from resultDimensions
+ const outputHeaders = config.resultDimensions.map(dim => dim.name);
+
+ // Compute aggregated data for each group
+ const aggregatedData: any[][] = [];
+ for (const key in groups) {
+ const groupRows = groups[key];
+ const row: any[] = [];
+
+ config.resultDimensions.forEach(dim => {
+ if (dim.from === config.groupBy) {
+ // Include the group key directly
+ row.push(key);
+ } else {
+ // Find the index of the 'from' column
+ const fromIndex = headers.indexOf(dim.from);
+ if (fromIndex === -1) {
+ return;
+ }
+ // Extract values for the 'from' column in this group
+ const values = groupRows
+ .map(r => parseFloat(r[fromIndex]))
+ .filter(v => !isNaN(v));
+ if (dim.method && aggregators[dim.method]) {
+ // Apply the aggregation method
+ row.push(aggregators[dim.method](values));
+ } else {
+ return;
+ }
+ }
+ });
+
+ aggregatedData.push(row);
+ }
+
+ // Return the transformed data with headers
+ return [outputHeaders, ...aggregatedData];
+}
+
+export const echartsConfigOmitChildren = [
+ "hidden",
+ "selectedPoints",
+ "onUIEvent",
+ "mapInstance"
+] as const;
+type EchartsConfigProps = Omit;
+
+// https://echarts.apache.org/en/option.html
+export function getEchartsConfig(
+ props: EchartsConfigProps,
+ chartSize?: ChartSize,
+ theme?: any,
+): EChartsOptionWithMap {
+ let config: any = {
+ backgroundColor: props.background,
+ globe: {
+ environment: props.environment,
+ baseTexture: props.baseTexture,
+ heightTexture: props.heightTexture,
+ shading: 'realistic',
+ realisticMaterial: {
+ roughness: 0.2,
+ metalness: 0
+ },
+ postEffect: {
+ enable: true,
+ depthOfField: {
+ enable: false,
+ focalDistance: 150
+ }
+ },
+ displacementScale: 0.1,
+ displacementQuality: 'high',
+ temporalSuperSampling: {
+ enable: true
+ },
+ light: {
+ ambient: {
+ intensity: 0.4
+ },
+ main: {
+ intensity: 0.4
+ },
+ },
+ viewControl: {
+ autoRotate: false
+ },
+ silent: true
+ },
+ series: {
+ type: 'lines3D',
+ coordinateSystem: 'globe',
+ blendMode: 'lighter',
+ lineStyle: {
+ width: props.lineStyleWidth,
+ color: props.lineStyleColor,
+ opacity: props.lineStyleOpacity
+ },
+ data: props.data,
+ effect: {
+ show: props.effectShow,
+ trailWidth: props.effectWidth,
+ trailLength: props.effectLength,
+ trailOpacity: props.effectOpacity,
+ trailColor: props.effectColor
+ },
+ }
+ };
+ console.log(config);
+ return config;
+}
+
+export function getSelectedPoints(param: any, option: any) {
+ const series = option.series;
+ const dataSource = _.isArray(option.dataset) && option.dataset[0]?.source;
+ if (series && dataSource) {
+ return param.selected.flatMap((selectInfo: any) => {
+ const seriesInfo = series[selectInfo.seriesIndex];
+ if (!seriesInfo || !seriesInfo.encode) {
+ return [];
+ }
+ return selectInfo.dataIndex.map((index: any) => {
+ const commonResult = {
+ seriesName: seriesInfo.name,
+ };
+ if (seriesInfo.encode.itemName && seriesInfo.encode.value) {
+ return {
+ ...commonResult,
+ itemName: dataSource[index][seriesInfo.encode.itemName],
+ value: dataSource[index][seriesInfo.encode.value],
+ };
+ } else {
+ return {
+ ...commonResult,
+ x: dataSource[index][seriesInfo.encode.x],
+ y: dataSource[index][seriesInfo.encode.y],
+ };
+ }
+ });
+ });
+ }
+ return [];
+}
+
+export function loadGoogleMapsScript(apiKey: string) {
+ const mapsUrl = `${googleMapsApiUrl}?key=${apiKey}`;
+ const scripts = document.getElementsByTagName('script');
+ // is script already loaded
+ let scriptIndex = _.findIndex(scripts, (script) => script.src.endsWith(mapsUrl));
+ if(scriptIndex > -1) {
+ return scripts[scriptIndex];
+ }
+ // is script loaded with diff api_key, remove the script and load again
+ scriptIndex = _.findIndex(scripts, (script) => script.src.startsWith(googleMapsApiUrl));
+ if(scriptIndex > -1) {
+ scripts[scriptIndex].remove();
+ }
+
+ const script = document.createElement("script");
+ script.type = "text/javascript";
+ script.src = mapsUrl;
+ script.async = true;
+ script.defer = true;
+ window.document.body.appendChild(script);
+
+ return script;
+}
diff --git a/client/packages/lowcoder-comps/src/comps/lineChartComp/lineChartComp.tsx b/client/packages/lowcoder-comps/src/comps/lineChartComp/lineChartComp.tsx
new file mode 100644
index 000000000..be3e5bf65
--- /dev/null
+++ b/client/packages/lowcoder-comps/src/comps/lineChartComp/lineChartComp.tsx
@@ -0,0 +1,314 @@
+import {
+ changeChildAction,
+ changeValueAction,
+ CompAction,
+ CompActionTypes,
+ wrapChildAction,
+} from "lowcoder-core";
+import { AxisFormatterComp, EchartsAxisType } from "../basicChartComp/chartConfigs/cartesianAxisConfig";
+import { lineChartChildrenMap, ChartSize, getDataKeys } from "./lineChartConstants";
+import { lineChartPropertyView } from "./lineChartPropertyView";
+import _ from "lodash";
+import { useContext, useEffect, useMemo, useRef, useState } from "react";
+import ReactResizeDetector from "react-resize-detector";
+import ReactECharts from "../basicChartComp/reactEcharts";
+import {
+ childrenToProps,
+ depsConfig,
+ genRandomKey,
+ NameConfig,
+ UICompBuilder,
+ withDefault,
+ withExposingConfigs,
+ withViewFn,
+ ThemeContext,
+ chartColorPalette,
+ getPromiseAfterDispatch,
+ dropdownControl,
+} from "lowcoder-sdk";
+import { getEchartsLocale, trans } from "i18n/comps";
+import { ItemColorComp } from "comps/basicChartComp/chartConfigs/lineChartConfig";
+import {
+ echartsConfigOmitChildren,
+ getEchartsConfig,
+ getSelectedPoints,
+} from "./lineChartUtils";
+import 'echarts-extension-gmap';
+import log from "loglevel";
+
+let clickEventCallback = () => {};
+
+const chartModeOptions = [
+ {
+ label: "ECharts JSON",
+ value: "json",
+ }
+] as const;
+
+let LineChartTmpComp = (function () {
+ return new UICompBuilder({mode:dropdownControl(chartModeOptions,'ui'),...lineChartChildrenMap}, () => null)
+ .setPropertyViewFn(lineChartPropertyView)
+ .build();
+})();
+
+LineChartTmpComp = withViewFn(LineChartTmpComp, (comp) => {
+ const mode = comp.children.mode.getView();
+ const onUIEvent = comp.children.onUIEvent.getView();
+ const onEvent = comp.children.onEvent.getView();
+ const echartsCompRef = useRef();
+ const [chartSize, setChartSize] = useState();
+ const firstResize = useRef(true);
+ const theme = useContext(ThemeContext);
+ const defaultChartTheme = {
+ color: chartColorPalette,
+ backgroundColor: "#fff",
+ };
+
+ let themeConfig = defaultChartTheme;
+ try {
+ themeConfig = theme?.theme.chart ? JSON.parse(theme?.theme.chart) : defaultChartTheme;
+ } catch (error) {
+ log.error('theme chart error: ', error);
+ }
+
+ const triggerClickEvent = async (dispatch: any, action: CompAction) => {
+ await getPromiseAfterDispatch(
+ dispatch,
+ action,
+ { autoHandleAfterReduce: true }
+ );
+ onEvent('click');
+ }
+
+ useEffect(() => {
+ const echartsCompInstance = echartsCompRef?.current?.getEchartsInstance();
+ if (!echartsCompInstance) {
+ return _.noop;
+ }
+ echartsCompInstance?.on("click", (param: any) => {
+ document.dispatchEvent(new CustomEvent("clickEvent", {
+ bubbles: true,
+ detail: {
+ action: 'click',
+ data: param.data,
+ }
+ }));
+ triggerClickEvent(
+ comp.dispatch,
+ changeChildAction("lastInteractionData", param.data, false)
+ );
+ });
+ return () => {
+ echartsCompInstance?.off("click");
+ document.removeEventListener('clickEvent', clickEventCallback)
+ };
+ }, []);
+
+ useEffect(() => {
+ // bind events
+ const echartsCompInstance = echartsCompRef?.current?.getEchartsInstance();
+ if (!echartsCompInstance) {
+ return _.noop;
+ }
+ echartsCompInstance?.on("selectchanged", (param: any) => {
+ const option: any = echartsCompInstance?.getOption();
+ document.dispatchEvent(new CustomEvent("clickEvent", {
+ bubbles: true,
+ detail: {
+ action: param.fromAction,
+ data: getSelectedPoints(param, option)
+ }
+ }));
+
+ if (param.fromAction === "select") {
+ comp.dispatch(changeChildAction("selectedPoints", getSelectedPoints(param, option), false));
+ onUIEvent("select");
+ } else if (param.fromAction === "unselect") {
+ comp.dispatch(changeChildAction("selectedPoints", getSelectedPoints(param, option), false));
+ onUIEvent("unselect");
+ }
+
+ triggerClickEvent(
+ comp.dispatch,
+ changeChildAction("lastInteractionData", getSelectedPoints(param, option), false)
+ );
+ });
+ // unbind
+ return () => {
+ echartsCompInstance?.off("selectchanged");
+ document.removeEventListener('clickEvent', clickEventCallback)
+ };
+ }, [onUIEvent]);
+
+ const echartsConfigChildren = _.omit(comp.children, echartsConfigOmitChildren);
+ const childrenProps = childrenToProps(echartsConfigChildren);
+ const option = useMemo(() => {
+ return getEchartsConfig(
+ childrenProps as ToViewReturn,
+ chartSize,
+ themeConfig
+ );
+ }, [theme, childrenProps, chartSize, ...Object.values(echartsConfigChildren)]);
+
+ return (
+ {
+ if (w && h) {
+ setChartSize({ w: w, h: h });
+ }
+ if (!firstResize.current) {
+ // ignore the first resize, which will impact the loading animation
+ echartsCompRef.current?.getEchartsInstance().resize();
+ } else {
+ firstResize.current = false;
+ }
+ }}
+ >
+ (echartsCompRef.current = e)}
+ style={{ height: "100%" }}
+ notMerge
+ lazyUpdate
+ opts={{ locale: getEchartsLocale() }}
+ option={option}
+ mode={mode}
+ />
+
+ );
+});
+
+function getYAxisFormatContextValue(
+ data: Array,
+ yAxisType: EchartsAxisType,
+ yAxisName?: string
+) {
+ const dataSample = yAxisName && data.length > 0 && data[0][yAxisName];
+ let contextValue = dataSample;
+ if (yAxisType === "time") {
+ // to timestamp
+ const time =
+ typeof dataSample === "number" || typeof dataSample === "string"
+ ? new Date(dataSample).getTime()
+ : null;
+ if (time) contextValue = time;
+ }
+ return contextValue;
+}
+
+LineChartTmpComp = class extends LineChartTmpComp {
+ private lastYAxisFormatContextVal?: JSONValue;
+ private lastColorContext?: JSONObject;
+
+ updateContext(comp: this) {
+ // the context value of axis format
+ let resultComp = comp;
+ const data = comp.children.data.getView();
+ const sampleSeries = comp.children.series.getView().find((s) => !s.getView().hide);
+ const yAxisContextValue = getYAxisFormatContextValue(
+ data,
+ comp.children.yConfig.children.yAxisType.getView(),
+ sampleSeries?.children.columnName.getView()
+ );
+ if (yAxisContextValue !== comp.lastYAxisFormatContextVal) {
+ comp.lastYAxisFormatContextVal = yAxisContextValue;
+ resultComp = comp.setChild(
+ "yConfig",
+ comp.children.yConfig.reduce(
+ wrapChildAction(
+ "formatter",
+ AxisFormatterComp.changeContextDataAction({ value: yAxisContextValue })
+ )
+ )
+ );
+ }
+ // item color context
+ const colorContextVal = {
+ seriesName: sampleSeries?.children.seriesName.getView(),
+ value: yAxisContextValue,
+ };
+ if (
+ comp.children.chartConfig.children.comp.children.hasOwnProperty("itemColor") &&
+ !_.isEqual(colorContextVal, comp.lastColorContext)
+ ) {
+ comp.lastColorContext = colorContextVal;
+ resultComp = resultComp.setChild(
+ "chartConfig",
+ comp.children.chartConfig.reduce(
+ wrapChildAction(
+ "comp",
+ wrapChildAction("itemColor", ItemColorComp.changeContextDataAction(colorContextVal))
+ )
+ )
+ );
+ }
+ return resultComp;
+ }
+
+ override reduce(action: CompAction): this {
+ const comp = super.reduce(action);
+ if (action.type === CompActionTypes.UPDATE_NODES_V2) {
+ const newData = comp.children.data.getView();
+ // data changes
+ if (comp.children.data !== this.children.data) {
+ setTimeout(() => {
+ // update x-axis value
+ const keys = getDataKeys(newData);
+ if (keys.length > 0 && !keys.includes(comp.children.xAxisKey.getView())) {
+ comp.children.xAxisKey.dispatch(changeValueAction(keys[0] || ""));
+ }
+ // pass to child series comp
+ comp.children.series.dispatchDataChanged(newData);
+ }, 0);
+ }
+ return this.updateContext(comp);
+ }
+ return comp;
+ }
+
+ override autoHeight(): boolean {
+ return false;
+ }
+};
+
+let LineChartComp = withExposingConfigs(LineChartTmpComp, [
+ depsConfig({
+ name: "selectedPoints",
+ desc: trans("chart.selectedPointsDesc"),
+ depKeys: ["selectedPoints"],
+ func: (input) => {
+ return input.selectedPoints;
+ },
+ }),
+ depsConfig({
+ name: "lastInteractionData",
+ desc: trans("chart.lastInteractionDataDesc"),
+ depKeys: ["lastInteractionData"],
+ func: (input) => {
+ return input.lastInteractionData;
+ },
+ }),
+ depsConfig({
+ name: "data",
+ desc: trans("chart.dataDesc"),
+ depKeys: ["data", "mode"],
+ func: (input) =>[] ,
+ }),
+ new NameConfig("title", trans("chart.titleDesc")),
+]);
+
+
+export const LineChartCompWithDefault = withDefault(LineChartComp, {
+ xAxisKey: "date",
+ series: [
+ {
+ dataIndex: genRandomKey(),
+ seriesName: trans("chart.spending"),
+ columnName: "spending",
+ },
+ {
+ dataIndex: genRandomKey(),
+ seriesName: trans("chart.budget"),
+ columnName: "budget",
+ },
+ ],
+});
diff --git a/client/packages/lowcoder-comps/src/comps/lineChartComp/lineChartConstants.tsx b/client/packages/lowcoder-comps/src/comps/lineChartComp/lineChartConstants.tsx
new file mode 100644
index 000000000..2685f1972
--- /dev/null
+++ b/client/packages/lowcoder-comps/src/comps/lineChartComp/lineChartConstants.tsx
@@ -0,0 +1,315 @@
+import {
+ jsonControl,
+ stateComp,
+ toJSONObjectArray,
+ toObject,
+ BoolControl,
+ ColorControl,
+ withDefault,
+ StringControl,
+ NumberControl,
+ dropdownControl,
+ list,
+ eventHandlerControl,
+ valueComp,
+ withType,
+ uiChildren,
+ clickEvent,
+ toArray,
+ styleControl,
+ EchartDefaultTextStyle,
+ EchartDefaultChartStyle,
+ MultiCompBuilder,
+} from "lowcoder-sdk";
+import { RecordConstructorToComp, RecordConstructorToView } from "lowcoder-core";
+import { BarChartConfig } from "../basicChartComp/chartConfigs/barChartConfig";
+import { XAxisConfig, YAxisConfig } from "../basicChartComp/chartConfigs/cartesianAxisConfig";
+import { LegendConfig } from "../basicChartComp/chartConfigs/legendConfig";
+import { EchartsLegendConfig } from "../basicChartComp/chartConfigs/echartsLegendConfig";
+import { EchartsLabelConfig } from "../basicChartComp/chartConfigs/echartsLabelConfig";
+import { LineChartConfig } from "../basicChartComp/chartConfigs/lineChartConfig";
+import { PieChartConfig } from "../basicChartComp/chartConfigs/pieChartConfig";
+import { ScatterChartConfig } from "../basicChartComp/chartConfigs/scatterChartConfig";
+import { SeriesListComp } from "./seriesComp";
+import { EChartsOption } from "echarts";
+import { i18nObjs, trans } from "i18n/comps";
+import { GaugeChartConfig } from "../basicChartComp/chartConfigs/gaugeChartConfig";
+import { FunnelChartConfig } from "../basicChartComp/chartConfigs/funnelChartConfig";
+import {EchartsTitleVerticalConfig} from "../chartComp/chartConfigs/echartsTitleVerticalConfig";
+import {EchartsTitleConfig} from "../basicChartComp/chartConfigs/echartsTitleConfig";
+
+export const ChartTypeOptions = [
+ {
+ label: trans("chart.bar"),
+ value: "bar",
+ },
+ {
+ label: trans("chart.line"),
+ value: "line",
+ },
+ {
+ label: trans("chart.scatter"),
+ value: "scatter",
+ },
+ {
+ label: trans("chart.pie"),
+ value: "pie",
+ },
+] as const;
+
+export const UIEventOptions = [
+ {
+ label: trans("chart.select"),
+ value: "select",
+ description: trans("chart.selectDesc"),
+ },
+ {
+ label: trans("chart.unSelect"),
+ value: "unselect",
+ description: trans("chart.unselectDesc"),
+ },
+] as const;
+
+export const XAxisDirectionOptions = [
+ {
+ label: trans("chart.horizontal"),
+ value: "horizontal",
+ },
+ {
+ label: trans("chart.vertical"),
+ value: "vertical",
+ },
+] as const;
+
+export type XAxisDirectionType = ValueFromOption;
+
+export const noDataAxisConfig = {
+ animation: false,
+ xAxis: {
+ type: "category",
+ name: trans("chart.noData"),
+ nameLocation: "middle",
+ data: [],
+ axisLine: {
+ lineStyle: {
+ color: "#8B8FA3",
+ },
+ },
+ },
+ yAxis: {
+ type: "value",
+ axisLabel: {
+ color: "#8B8FA3",
+ },
+ splitLine: {
+ lineStyle: {
+ color: "#F0F0F0",
+ },
+ },
+ },
+ tooltip: {
+ show: false,
+ },
+ series: [
+ {
+ data: [700],
+ type: "line",
+ itemStyle: {
+ opacity: 0,
+ },
+ },
+ ],
+} as EChartsOption;
+
+export const noDataPieChartConfig = {
+ animation: false,
+ tooltip: {
+ show: false,
+ },
+ legend: {
+ formatter: trans("chart.unknown"),
+ top: "bottom",
+ selectedMode: false,
+ },
+ color: ["#B8BBCC", "#CED0D9", "#DCDEE6", "#E6E6EB"],
+ series: [
+ {
+ type: "pie",
+ radius: "35%",
+ center: ["25%", "50%"],
+ silent: true,
+ label: {
+ show: false,
+ },
+ data: [
+ {
+ name: "1",
+ value: 70,
+ },
+ {
+ name: "2",
+ value: 68,
+ },
+ {
+ name: "3",
+ value: 48,
+ },
+ {
+ name: "4",
+ value: 40,
+ },
+ ],
+ },
+ {
+ type: "pie",
+ radius: "35%",
+ center: ["75%", "50%"],
+ silent: true,
+ label: {
+ show: false,
+ },
+ data: [
+ {
+ name: "1",
+ value: 70,
+ },
+ {
+ name: "2",
+ value: 68,
+ },
+ {
+ name: "3",
+ value: 48,
+ },
+ {
+ name: "4",
+ value: 40,
+ },
+ ],
+ },
+ ],
+} as EChartsOption;
+
+const areaPiecesChildrenMap = {
+ color: ColorControl,
+ from: StringControl,
+ to: StringControl,
+ // unique key, for sort
+ dataIndex: valueComp(""),
+};
+const AreaPiecesTmpComp = new MultiCompBuilder(areaPiecesChildrenMap, (props) => {
+ return props;
+})
+ .setPropertyViewFn((children: any) =>
+ (<>
+ {children.color.propertyView({label: trans("lineChart.color")})}
+ {children.from.propertyView({label: trans("lineChart.from")})}
+ {children.to.propertyView({label: trans("lineChart.to")})}
+ >)
+ )
+ .build();
+
+export type ChartSize = { w: number; h: number };
+
+export const getDataKeys = (data: Array) => {
+ if (!data) {
+ return [];
+ }
+ const dataKeys: Array = [];
+ data.slice(0, 50).forEach((d) => {
+ Object.keys(d).forEach((key) => {
+ if (!dataKeys.includes(key)) {
+ dataKeys.push(key);
+ }
+ });
+ });
+ return dataKeys;
+};
+
+const ChartOptionMap = {
+ bar: BarChartConfig,
+ line: LineChartConfig,
+ pie: PieChartConfig,
+ scatter: ScatterChartConfig,
+};
+
+const EchartsOptionMap = {
+ funnel: FunnelChartConfig,
+ gauge: GaugeChartConfig,
+};
+
+const ChartOptionComp = withType(ChartOptionMap, "line");
+const EchartsOptionComp = withType(EchartsOptionMap, "funnel");
+export type CharOptionCompType = keyof typeof ChartOptionMap;
+
+export const chartUiModeChildren = {
+ title: withDefault(StringControl, trans("echarts.defaultTitle")),
+ data: jsonControl(toJSONObjectArray, i18nObjs.defaultDataSource),
+ xAxisKey: valueComp(""), // x-axis, key from data
+ xAxisDirection: dropdownControl(XAxisDirectionOptions, "horizontal"),
+ xAxisData: jsonControl(toArray, []),
+ series: SeriesListComp,
+ xConfig: XAxisConfig,
+ yConfig: YAxisConfig,
+ legendConfig: LegendConfig,
+ chartConfig: ChartOptionComp,
+ areaPieces: list(AreaPiecesTmpComp),
+ animationDuration: withDefault(NumberControl, 1000),
+ onUIEvent: eventHandlerControl(UIEventOptions),
+};
+
+let chartJsonModeChildren: any = {
+ echartsOption: jsonControl(toObject, i18nObjs.defaultEchartsJsonOption),
+ echartsTitle: withDefault(StringControl, trans("echarts.defaultTitle")),
+ echartsLegendConfig: EchartsLegendConfig,
+ echartsLabelConfig: EchartsLabelConfig,
+ echartsConfig: EchartsOptionComp,
+ echartsTitleVerticalConfig: EchartsTitleVerticalConfig,
+ echartsTitleConfig:EchartsTitleConfig,
+
+ left:withDefault(NumberControl,trans('chart.defaultLeft')),
+ right:withDefault(NumberControl,trans('chart.defaultRight')),
+ top:withDefault(NumberControl,trans('chart.defaultTop')),
+ bottom:withDefault(NumberControl,trans('chart.defaultBottom')),
+
+ tooltip: withDefault(BoolControl, true),
+ legendVisibility: withDefault(BoolControl, true),
+}
+
+if (EchartDefaultChartStyle && EchartDefaultTextStyle) {
+ chartJsonModeChildren = {
+ ...chartJsonModeChildren,
+ chartStyle: styleControl(EchartDefaultChartStyle, 'chartStyle'),
+ titleStyle: styleControl(EchartDefaultTextStyle, 'titleStyle'),
+ xAxisStyle: styleControl(EchartDefaultTextStyle, 'xAxis'),
+ yAxisStyle: styleControl(EchartDefaultTextStyle, 'yAxisStyle'),
+ legendStyle: styleControl(EchartDefaultTextStyle, 'legendStyle'),
+ }
+}
+
+export type UIChartDataType = {
+ seriesName: string;
+ // coordinate chart
+ x?: any;
+ y?: any;
+ // pie or funnel
+ itemName?: any;
+ value?: any;
+};
+
+export type NonUIChartDataType = {
+ name: string;
+ value: any;
+}
+
+export const lineChartChildrenMap = {
+ selectedPoints: stateComp>([]),
+ lastInteractionData: stateComp | NonUIChartDataType>({}),
+ onEvent: eventHandlerControl([clickEvent] as const),
+ ...chartUiModeChildren,
+ ...chartJsonModeChildren,
+};
+
+const chartUiChildrenMap = uiChildren(lineChartChildrenMap);
+export type ChartCompPropsType = RecordConstructorToView;
+export type ChartCompChildrenType = RecordConstructorToComp;
diff --git a/client/packages/lowcoder-comps/src/comps/lineChartComp/lineChartPropertyView.tsx b/client/packages/lowcoder-comps/src/comps/lineChartComp/lineChartPropertyView.tsx
new file mode 100644
index 000000000..5a67d8ecf
--- /dev/null
+++ b/client/packages/lowcoder-comps/src/comps/lineChartComp/lineChartPropertyView.tsx
@@ -0,0 +1,187 @@
+import { changeChildAction, CompAction } from "lowcoder-core";
+import { ChartCompChildrenType, ChartTypeOptions,getDataKeys } from "./lineChartConstants";
+import { newSeries } from "./seriesComp";
+import {
+ CustomModal,
+ Dropdown,
+ hiddenPropertyView,
+ Option,
+ RedButton,
+ Section,
+ sectionNames,
+ controlItem,
+} from "lowcoder-sdk";
+import { trans } from "i18n/comps";
+
+export function lineChartPropertyView(
+ children: ChartCompChildrenType,
+ dispatch: (action: CompAction) => void
+) {
+ const series = children.series.getView();
+ const columnOptions = getDataKeys(children.data.getView()).map((key) => ({
+ label: key,
+ value: key,
+ }));
+
+ const uiModePropertyView = (
+ <>
+
+ {children.chartConfig.getPropertyView()}
+ {children.animationDuration.propertyView({label: trans("lineChart.animationDuration")})}
+ {
+ dispatch(changeChildAction("xAxisKey", value));
+ }}
+ />
+ {children.chartConfig.getView().subtype === "waterfall" && children.xAxisData.propertyView({
+ label: "X-Label-Data"
+ })}
+ s.getView().seriesName}
+ popoverTitle={(s) => s.getView().columnName}
+ content={(s, index) => (
+ <>
+ {s.getPropertyViewWithData(columnOptions)}
+ {
+ {
+ CustomModal.confirm({
+ title: trans("chart.delete"),
+ content: trans("chart.confirmDelete") + `${s.getView().seriesName}?`,
+ onConfirm: () =>
+ children.series.dispatch(children.series.deleteAction(index)),
+ confirmBtnType: "delete",
+ okText: trans("chart.delete"),
+ });
+ }}
+ >
+ {trans("chart.delete")}
+
+ }
+ >
+ )}
+ onAdd={() => {
+ if (columnOptions.length <= 0) {
+ return;
+ }
+ children.series.dispatch(
+ children.series.pushAction(
+ newSeries(trans("chart.customSeries"), columnOptions[0].value)
+ )
+ );
+ }}
+ onMove={(fromIndex, toIndex) => {
+ const action = children.series.arrayMoveAction(fromIndex, toIndex);
+ children.series.dispatch(action);
+ }}
+ hide={(s) => s.getView().hide}
+ onHide={(s, hide) => s.children.hide.dispatchChangeValueAction(hide)}
+ dataIndex={(s) => s.getView().dataIndex}
+ />
+ `[${s.getView().from}-${s.getView().to}] ${s.getView().color}`}
+ popoverTitle={(s) => trans("lineChart.areaPiece")}
+ content={(s, index) => (
+ <>
+ {s.getPropertyView({label: "Type"})}
+ {
+ {
+ children.areaPieces.dispatch(children.areaPieces.deleteAction(index));
+ }}
+ >
+ {trans("chart.delete")}
+
+ }
+ >
+ )}
+ onAdd={() => {
+ children.areaPieces.dispatch(
+ children.areaPieces.pushAction(
+ {}
+ )
+ );
+ }}
+ onMove={(fromIndex, toIndex) => {
+ const action = children.areaPieces.arrayMoveAction(fromIndex, toIndex);
+ children.areaPieces.dispatch(action);
+ }}
+ hide={(s) => true}
+ onHide={(s, hide) => console.log("onHide")}
+ dataIndex={(s) => {
+ return s.getView().dataIndex;
+ }}
+ />
+
+
+
+ {children.onUIEvent.propertyView({title: trans("chart.chartEventHandlers")})}
+
+
+ {children.onEvent.propertyView()}
+
+
+
+ {children.echartsTitleConfig.getPropertyView()}
+ {children.echartsTitleVerticalConfig.getPropertyView()}
+ {children.legendConfig.getPropertyView()}
+ {children.title.propertyView({ label: trans("chart.title") })}
+ {children.left.propertyView({ label: trans("chart.left"), tooltip: trans("echarts.leftTooltip") })}
+ {children.right.propertyView({ label: trans("chart.right"), tooltip: trans("echarts.rightTooltip") })}
+ {children.top.propertyView({ label: trans("chart.top"), tooltip: trans("echarts.topTooltip") })}
+ {children.bottom.propertyView({ label: trans("chart.bottom"), tooltip: trans("echarts.bottomTooltip") })}
+ {children.chartConfig.children.compType.getView() !== "pie" && (
+ <>
+ {children.xAxisDirection.propertyView({
+ label: trans("chart.xAxisDirection"),
+ radioButton: true,
+ })}
+ {children.xConfig.getPropertyView()}
+ {children.yConfig.getPropertyView()}
+ >
+ )}
+ {hiddenPropertyView(children)}
+ {children.tooltip.propertyView({label: trans("echarts.tooltip"), tooltip: trans("echarts.tooltipTooltip")})}
+
+
+ {children.chartStyle?.getPropertyView()}
+
+
+ {children.titleStyle?.getPropertyView()}
+
+
+ {children.xAxisStyle?.getPropertyView()}
+
+
+ {children.yAxisStyle?.getPropertyView()}
+
+
+ {children.legendStyle?.getPropertyView()}
+
+
+ {children.data.propertyView({
+ label: trans("chart.data"),
+ })}
+
+ >
+ );
+
+ const getChatConfigByMode = (mode: string) => {
+ switch(mode) {
+ case "ui":
+ return uiModePropertyView;
+ }
+ }
+ return (
+ <>
+ {getChatConfigByMode(children.mode.getView())}
+ >
+ );
+}
diff --git a/client/packages/lowcoder-comps/src/comps/lineChartComp/lineChartUtils.ts b/client/packages/lowcoder-comps/src/comps/lineChartComp/lineChartUtils.ts
new file mode 100644
index 000000000..3dfb3769e
--- /dev/null
+++ b/client/packages/lowcoder-comps/src/comps/lineChartComp/lineChartUtils.ts
@@ -0,0 +1,398 @@
+import {
+ CharOptionCompType,
+ ChartCompPropsType,
+ ChartSize,
+ noDataAxisConfig,
+ noDataPieChartConfig,
+} from "comps/lineChartComp/lineChartConstants";
+import { getPieRadiusAndCenter } from "comps/basicChartComp/chartConfigs/pieChartConfig";
+import { EChartsOptionWithMap } from "../basicChartComp/reactEcharts/types";
+import _ from "lodash";
+import { chartColorPalette, isNumeric, JSONObject, loadScript } from "lowcoder-sdk";
+import { calcXYConfig } from "comps/basicChartComp/chartConfigs/cartesianAxisConfig";
+import Big from "big.js";
+import { googleMapsApiUrl } from "../basicChartComp/chartConfigs/chartUrls";
+import opacityToHex from "../../util/opacityToHex";
+import parseBackground from "../../util/gradientBackgroundColor";
+import {ba, s} from "@fullcalendar/core/internal-common";
+import {chartStyleWrapper, styleWrapper} from "../../util/styleWrapper";
+
+export function transformData(
+ originData: JSONObject[],
+ xAxis: string,
+ seriesColumnNames: string[]
+) {
+ // aggregate data by x-axis
+ const transformedData: JSONObject[] = [];
+ originData.reduce((prev, cur) => {
+ if (cur === null || cur === undefined) {
+ return prev;
+ }
+ const groupValue = cur[xAxis] as string;
+ if (!prev[groupValue]) {
+ // init as 0
+ const initValue: any = {};
+ seriesColumnNames.forEach((name) => {
+ initValue[name] = 0;
+ });
+ prev[groupValue] = initValue;
+ transformedData.push(prev[groupValue]);
+ }
+ // remain the x-axis data
+ prev[groupValue][xAxis] = groupValue;
+ seriesColumnNames.forEach((key) => {
+ if (key === xAxis) {
+ return;
+ } else if (isNumeric(cur[key])) {
+ const bigNum = Big(cur[key]);
+ prev[groupValue][key] = bigNum.add(prev[groupValue][key]).toNumber();
+ } else {
+ prev[groupValue][key] += 1;
+ }
+ });
+ return prev;
+ }, {} as any);
+ return transformedData;
+}
+
+const notAxisChartSet: Set = new Set(["pie"] as const);
+const notAxisChartSubtypeSet: Set = new Set(["polar"] as const);
+export const echartsConfigOmitChildren = [
+ "hidden",
+ "selectedPoints",
+ "onUIEvent",
+ "mapInstance"
+] as const;
+type EchartsConfigProps = Omit;
+
+
+export function isAxisChart(type: CharOptionCompType, polar: boolean) {
+ return !notAxisChartSet.has(type) && !polar;
+}
+
+export function getSeriesConfig(props: EchartsConfigProps) {
+ let visibleSeries = props.series.filter((s) => !s.getView().hide);
+ if(props.chartConfig.subtype === "waterfall") {
+ const seriesOn = visibleSeries[0];
+ const seriesPlaceholder = visibleSeries[0];
+ visibleSeries = [seriesPlaceholder, seriesOn];
+ }
+ const seriesLength = visibleSeries.length;
+ return visibleSeries.map((s, index) => {
+ if (isAxisChart(props.chartConfig.type, props.chartConfig.polarData.polar)) {
+ let encodeX: string, encodeY: string;
+ const horizontalX = props.xAxisDirection === "horizontal";
+ let itemStyle = props.chartConfig.itemStyle;
+
+ if (horizontalX) {
+ encodeX = props.xAxisKey;
+ encodeY = s.getView().columnName;
+ } else {
+ encodeX = s.getView().columnName;
+ encodeY = props.xAxisKey;
+ }
+ const markLineData = s.getView().markLines.map(line => ({type: line.getView().type}));
+ const markAreaData = s.getView().markAreas.map(area => ([{name: area.getView().name, [horizontalX?"xAxis":"yAxis"]: area.getView().from, label: {
+ position: horizontalX?"top":"right",
+ }}, {[horizontalX?"xAxis":"yAxis"]: area.getView().to}]));
+ return {
+ name: s.getView().seriesName,
+ columnName: s.getView().columnName,
+ selectedMode: "single",
+ select: {
+ itemStyle: {
+ borderColor: "#000",
+ },
+ },
+ step: s.getView().step,
+ encode: {
+ x: encodeX,
+ y: encodeY,
+ },
+ markLine: {
+ data: markLineData,
+ },
+ markArea: {
+ itemStyle: {
+ color: 'rgba(255, 173, 177, 0.4)',
+ },
+ data: markAreaData,
+ },
+ // each type of chart's config
+ ...props.chartConfig,
+ itemStyle: itemStyle,
+ label: {
+ ...props.chartConfig.label,
+ ...(!horizontalX && { position: "outside" }),
+ },
+ };
+ } else {
+ const radiusAndCenter = getPieRadiusAndCenter(seriesLength, index, props.chartConfig);
+ return {
+ ...props.chartConfig,
+ columnName: s.getView().columnName,
+ radius: radiusAndCenter.radius,
+ center: radiusAndCenter.center,
+ name: s.getView().seriesName,
+ selectedMode: "single",
+ encode: {
+ itemName: props.xAxisKey,
+ value: s.getView().columnName,
+ },
+ };
+ }
+ });
+}
+
+// https://echarts.apache.org/en/option.html
+export function getEchartsConfig(
+ props: EchartsConfigProps,
+ chartSize?: ChartSize,
+ theme?: any,
+): EChartsOptionWithMap {
+ // axisChart
+ const axisChart = isAxisChart(props.chartConfig.type, props.chartConfig.polarData.polar);
+ const gridPos = {
+ left: `${props?.left}%`,
+ right: `${props?.right}%`,
+ bottom: `${props?.bottom}%`,
+ top: `${props?.top}%`,
+ };
+
+ let config: any = {
+ title: {
+ text: props.title,
+ top: props.echartsTitleVerticalConfig.top,
+ left:props.echartsTitleConfig.top,
+ textStyle: {
+ ...styleWrapper(props?.titleStyle, theme?.titleStyle)
+ }
+ },
+ backgroundColor: parseBackground( props?.chartStyle?.background || theme?.chartStyle?.backgroundColor || "#FFFFFF"),
+ legend: {
+ ...props.legendConfig,
+ textStyle: {
+ ...styleWrapper(props?.legendStyle, theme?.legendStyle, 15)
+ }
+ },
+ tooltip: props.tooltip && {
+ trigger: "axis",
+ axisPointer: {
+ type: "line",
+ lineStyle: {
+ color: "rgba(0,0,0,0.2)",
+ width: 2,
+ type: "solid"
+ }
+ }
+ },
+ grid: {
+ ...gridPos,
+ containLabel: true,
+ },
+ animationDuration: props.animationDuration,
+ };
+ if (props.areaPieces.length > 0) {
+ config.visualMap = {
+ type: 'piecewise',
+ show: false,
+ dimension: 0,
+ seriesIndex: 0,
+ pieces: props.areaPieces?.filter(p => p.getView().from && p.getView().to && p.getView().color)?.map(p => (
+ {
+ ...(p.getView().from?{min: parseInt(p.getView().from)}:{}),
+ ...(p.getView().to?{max: parseInt(p.getView().to)}:{}),
+ ...(p.getView().color?{color: p.getView().color}:{}),
+ }
+ ))
+ }
+ }
+ if(props.chartConfig.race) {
+ config = {
+ ...config,
+ // Disable init animation.
+ animationDuration: 0,
+ animationDurationUpdate: 2000,
+ animationEasing: 'linear',
+ animationEasingUpdate: 'linear',
+ }
+ }
+ if (props.data.length <= 0) {
+ // no data
+ return {
+ ...config,
+ ...(axisChart ? noDataAxisConfig : noDataPieChartConfig),
+ };
+ }
+ const yAxisConfig = props.yConfig();
+ const seriesColumnNames = props.series
+ .filter((s) => !s.getView().hide)
+ .map((s) => s.getView().columnName);
+ // y-axis is category and time, data doesn't need to aggregate
+ let transformedData =
+ yAxisConfig.type === "category" || yAxisConfig.type === "time" ? props.data : transformData(props.data, props.xAxisKey, seriesColumnNames);
+
+ if(props.chartConfig.polarData.polar) {
+ config = {
+ ...config,
+ polar: {
+ radius: [props.chartConfig.polarData.polarRadiusStart, props.chartConfig.polarData.polarRadiusEnd],
+ },
+ radiusAxis: {
+ type: props.chartConfig.polarData.polarIsTangent?'category':undefined,
+ data: props.chartConfig.polarData.polarIsTangent && props.chartConfig.polarData.labelData.length!==0?props.chartConfig.polarData.labelData:undefined,
+ max: props.chartConfig.polarData.polarIsTangent?undefined:props.chartConfig.polarData.radiusAxisMax || undefined,
+ },
+ angleAxis: {
+ type: props.chartConfig.polarData.polarIsTangent?undefined:'category',
+ data: !props.chartConfig.polarData.polarIsTangent && props.chartConfig.polarData.labelData.length!==0?props.chartConfig.polarData.labelData:undefined,
+ max: props.chartConfig.polarData.polarIsTangent?props.chartConfig.polarData.radiusAxisMax || undefined:undefined,
+ startAngle: props.chartConfig.polarData.polarStartAngle,
+ endAngle: props.chartConfig.polarData.polarEndAngle,
+ },
+ }
+ }
+
+ config = {
+ ...config,
+ dataset: [
+ {
+ source: transformedData,
+ sourceHeader: false,
+ },
+ ],
+ series: getSeriesConfig(props).map(series => ({
+ ...series,
+ encode: {
+ ...series.encode,
+ y: series.columnName,
+ },
+ itemStyle: {
+ ...series.itemStyle,
+ // ...chartStyleWrapper(props?.chartStyle, theme?.chartStyle)
+ },
+ lineStyle: {
+ ...chartStyleWrapper(props?.chartStyle, theme?.chartStyle)
+ },
+ data: transformedData.map((i: any) => i[series.columnName])
+ })),
+ };
+ if (axisChart) {
+ // pure chart's size except the margin around
+ let chartRealSize;
+ if (chartSize) {
+ const rightSize =
+ typeof gridPos.right === "number"
+ ? gridPos.right
+ : (chartSize.w * parseFloat(gridPos.right)) / 100.0;
+ chartRealSize = {
+ // actually it's self-adaptive with the x-axis label on the left, not that accurate but work
+ w: chartSize.w - gridPos.left - rightSize,
+ // also self-adaptive on the bottom
+ h: chartSize.h - gridPos.top - gridPos.bottom,
+ right: rightSize,
+ };
+ }
+ const finalXyConfig = calcXYConfig(
+ props.xConfig,
+ yAxisConfig,
+ props.xAxisDirection,
+ transformedData.map((d) => d[props.xAxisKey]),
+ chartRealSize
+ );
+ config = {
+ ...config,
+ // @ts-ignore
+ xAxis: {
+ ...finalXyConfig.xConfig,
+ axisLabel: {
+ ...styleWrapper(props?.xAxisStyle, theme?.xAxisStyle, 11)
+ },
+ data: finalXyConfig.xConfig.type === "category" && (props.xAxisData as []).length!==0?props?.xAxisData:transformedData.map((i: any) => i[props.xAxisKey]),
+ },
+ // @ts-ignore
+ yAxis: {
+ ...finalXyConfig.yConfig,
+ axisLabel: {
+ ...styleWrapper(props?.yAxisStyle, theme?.yAxisStyle, 11)
+ },
+ data: finalXyConfig.yConfig.type === "category" && (props.xAxisData as []).length!==0?props?.xAxisData:transformedData.map((i: any) => i[props.xAxisKey]),
+ },
+ };
+
+ if(props.chartConfig.race) {
+ config = {
+ ...config,
+ xAxis: {
+ ...config.xAxis,
+ animationDuration: 300,
+ animationDurationUpdate: 300
+ },
+ yAxis: {
+ ...config.yAxis,
+ animationDuration: 300,
+ animationDurationUpdate: 300
+ },
+ }
+ }
+ }
+
+ // console.log("Echarts transformedData and config", transformedData, config);
+ return config;
+}
+
+export function getSelectedPoints(param: any, option: any) {
+ const series = option.series;
+ const dataSource = _.isArray(option.dataset) && option.dataset[0]?.source;
+ if (series && dataSource) {
+ return param.selected.flatMap((selectInfo: any) => {
+ const seriesInfo = series[selectInfo.seriesIndex];
+ if (!seriesInfo || !seriesInfo.encode) {
+ return [];
+ }
+ return selectInfo.dataIndex.map((index: any) => {
+ const commonResult = {
+ seriesName: seriesInfo.name,
+ };
+ if (seriesInfo.encode.itemName && seriesInfo.encode.value) {
+ return {
+ ...commonResult,
+ itemName: dataSource[index][seriesInfo.encode.itemName],
+ value: dataSource[index][seriesInfo.encode.value],
+ };
+ } else {
+ return {
+ ...commonResult,
+ x: dataSource[index][seriesInfo.encode.x],
+ y: dataSource[index][seriesInfo.encode.y],
+ };
+ }
+ });
+ });
+ }
+ return [];
+}
+
+export function loadGoogleMapsScript(apiKey: string) {
+ const mapsUrl = `${googleMapsApiUrl}?key=${apiKey}`;
+ const scripts = document.getElementsByTagName('script');
+ // is script already loaded
+ let scriptIndex = _.findIndex(scripts, (script) => script.src.endsWith(mapsUrl));
+ if(scriptIndex > -1) {
+ return scripts[scriptIndex];
+ }
+ // is script loaded with diff api_key, remove the script and load again
+ scriptIndex = _.findIndex(scripts, (script) => script.src.startsWith(googleMapsApiUrl));
+ if(scriptIndex > -1) {
+ scripts[scriptIndex].remove();
+ }
+
+ const script = document.createElement("script");
+ script.type = "text/javascript";
+ script.src = mapsUrl;
+ script.async = true;
+ script.defer = true;
+ window.document.body.appendChild(script);
+
+ return script;
+}
diff --git a/client/packages/lowcoder-comps/src/comps/lineChartComp/seriesComp.tsx b/client/packages/lowcoder-comps/src/comps/lineChartComp/seriesComp.tsx
new file mode 100644
index 000000000..5a61774f5
--- /dev/null
+++ b/client/packages/lowcoder-comps/src/comps/lineChartComp/seriesComp.tsx
@@ -0,0 +1,280 @@
+import {
+ BoolControl,
+ StringControl,
+ list,
+ isNumeric,
+ genRandomKey,
+ Dropdown,
+ Option,
+ RedButton,
+ CustomModal,
+ MultiCompBuilder,
+ valueComp,
+ dropdownControl,
+} from "lowcoder-sdk";
+import { trans } from "i18n/comps";
+
+import { ConstructorToComp, ConstructorToDataType, ConstructorToView } from "lowcoder-core";
+import { CompAction, CustomAction, customAction, isMyCustomAction } from "lowcoder-core";
+
+export type SeriesCompType = ConstructorToComp;
+export type RawSeriesCompType = ConstructorToView;
+type SeriesDataType = ConstructorToDataType;
+type MarkLineDataType = ConstructorToDataType;
+
+type ActionDataType = {
+ type: "chartDataChanged";
+ chartData: Array;
+};
+
+export function newSeries(name: string, columnName: string): SeriesDataType {
+ return {
+ seriesName: name,
+ columnName: columnName,
+ dataIndex: genRandomKey(),
+ };
+}
+
+export function newMarkLine(type: string): MarkLineDataType {
+ return {
+ type,
+ dataIndex: genRandomKey(),
+ };
+}
+
+export const MarkLineTypeOptions = [
+ {
+ label: trans("lineChart.max"),
+ value: "max",
+ },
+ {
+ label: trans("lineChart.average"),
+ value: "average",
+ },
+ {
+ label: trans("lineChart.min"),
+ value: "min",
+ },
+] as const;
+
+export const StepOptions = [
+ {
+ label: trans("lineChart.none"),
+ value: "",
+ },
+ {
+ label: trans("lineChart.start"),
+ value: "start",
+ },
+ {
+ label: trans("lineChart.middle"),
+ value: "middle",
+ },
+ {
+ label: trans("lineChart.end"),
+ value: "end",
+ },
+] as const;
+
+const valToLabel = (val) => MarkLineTypeOptions.find(o => o.value === val)?.label || "";
+const markLinesChildrenMap = {
+ type: dropdownControl(MarkLineTypeOptions, "max"),
+ // unique key, for sort
+ dataIndex: valueComp(""),
+};
+const MarkLinesTmpComp = new MultiCompBuilder(markLinesChildrenMap, (props) => {
+ return props;
+})
+ .setPropertyViewFn((children: any) => {
+ return <>{children.type.propertyView({label: trans("lineChart.type")})}>;
+ })
+ .build();
+const markAreasChildrenMap = {
+ name: StringControl,
+ from: StringControl,
+ to: StringControl,
+ // unique key, for sort
+ dataIndex: valueComp(""),
+};
+const MarkAreasTmpComp = new MultiCompBuilder(markAreasChildrenMap, (props) => {
+ return props;
+})
+ .setPropertyViewFn((children: any) =>
+ (<>
+ {children.name.propertyView({label: trans("lineChart.name")})}
+ {children.from.propertyView({label: trans("lineChart.from")})}
+ {children.to.propertyView({label: trans("lineChart.to")})}
+ >)
+ )
+ .build();
+
+
+export function newMarkArea(): MarkLineDataType {
+ return {
+ dataIndex: genRandomKey(),
+ };
+}
+
+const seriesChildrenMap = {
+ columnName: StringControl,
+ seriesName: StringControl,
+ markLines: list(MarkLinesTmpComp),
+ markAreas: list(MarkAreasTmpComp),
+ hide: BoolControl,
+ // unique key, for sort
+ dataIndex: valueComp(""),
+ step: dropdownControl(StepOptions, ""),
+};
+
+const SeriesTmpComp = new MultiCompBuilder(seriesChildrenMap, (props) => {
+ return props;
+})
+ .setPropertyViewFn(() => {
+ return <>>;
+ })
+ .build();
+
+class SeriesComp extends SeriesTmpComp {
+ getPropertyViewWithData(columnOptions: OptionsType): React.ReactNode {
+ return (
+ <>
+ {this.children.seriesName.propertyView({
+ label: trans("chart.seriesName"),
+ })}
+ {
+ this.children.columnName.dispatchChangeValueAction(value);
+ }}
+ />
+ {this.children.step.propertyView({
+ label: trans("lineChart.step"),
+ })}
+ valToLabel(s.getView().type)}
+ popoverTitle={(s) => trans("lineChart.markLineType")}
+ content={(s, index) => (
+ <>
+ {s.getPropertyView({label: "Type"})}
+ {
+ {
+ this.children.markLines.dispatch(this.children.markLines.deleteAction(index));
+ }}
+ >
+ {trans("chart.delete")}
+
+ }
+ >
+ )}
+ onAdd={() => {
+ this.children.markLines.dispatch(
+ this.children.markLines.pushAction(
+ newMarkLine("max")
+ )
+ );
+ }}
+ onMove={(fromIndex, toIndex) => {
+ const action = this.children.markLines.arrayMoveAction(fromIndex, toIndex);
+ this.children.markLines.dispatch(action);
+ }}
+ hide={(s) => true}
+ onHide={(s, hide) => console.log("onHide")}
+ dataIndex={(s) => {
+ return s.getView().dataIndex;
+ }}
+ />
+ s.getView().name}
+ popoverTitle={(s) => trans("lineChart.markLineType")}
+ content={(s, index) => (
+ <>
+ {s.getPropertyView({label: "Type"})}
+ {
+ {
+ this.children.markAreas.dispatch(this.children.markAreas.deleteAction(index));
+ }}
+ >
+ {trans("chart.delete")}
+
+ }
+ >
+ )}
+ onAdd={() => {
+ this.children.markAreas.dispatch(
+ this.children.markAreas.pushAction(
+ newMarkArea()
+ )
+ );
+ }}
+ onMove={(fromIndex, toIndex) => {
+ const action = this.children.markAreas.arrayMoveAction(fromIndex, toIndex);
+ this.children.markAreas.dispatch(action);
+ }}
+ hide={(s) => true}
+ onHide={(s, hide) => console.log("onHide")}
+ dataIndex={(s) => {
+ return s.getView().dataIndex;
+ }}
+ />
+ >
+ );
+ }
+}
+
+const SeriesListTmpComp = list(SeriesComp);
+
+export class SeriesListComp extends SeriesListTmpComp {
+ override reduce(action: CompAction): this {
+ if (isMyCustomAction(action, "chartDataChanged")) {
+ // auto generate series
+ const actions = this.genExampleSeriesActions(action.value.chartData);
+ return this.reduce(this.multiAction(actions));
+ }
+ return super.reduce(action);
+ }
+
+ private genExampleSeriesActions(chartData: Array) {
+ const actions: CustomAction[] = [];
+ if (!chartData || chartData.length <= 0 || !chartData[0]) {
+ return actions;
+ }
+ let delCnt = 0;
+ const existColumns = this.getView().map((s) => s.getView().columnName);
+ // delete series not in data
+ existColumns.forEach((columnName) => {
+ if (chartData[0]?.[columnName] === undefined) {
+ actions.push(this.deleteAction(0));
+ delCnt++;
+ }
+ });
+ if (existColumns.length > delCnt) {
+ // don't generate example if exists
+ return actions;
+ }
+ // generate example series
+ const exampleKeys = Object.keys(chartData[0])
+ .filter((key) => {
+ return !existColumns.includes(key) && isNumeric(chartData[0][key]);
+ })
+ .slice(0, 3);
+ exampleKeys.forEach((key) => actions.push(this.pushAction(newSeries(key, key))));
+ return actions;
+ }
+
+ dispatchDataChanged(chartData: Array): void {
+ this.dispatch(
+ customAction({
+ type: "chartDataChanged",
+ chartData: chartData,
+ })
+ );
+ }
+}
diff --git a/client/packages/lowcoder-comps/src/comps/parallelChartComp/parallelChartComp.tsx b/client/packages/lowcoder-comps/src/comps/parallelChartComp/parallelChartComp.tsx
new file mode 100644
index 000000000..84bcf3280
--- /dev/null
+++ b/client/packages/lowcoder-comps/src/comps/parallelChartComp/parallelChartComp.tsx
@@ -0,0 +1,282 @@
+import {
+ changeChildAction,
+ changeValueAction,
+ CompAction,
+ CompActionTypes,
+ wrapChildAction,
+} from "lowcoder-core";
+import { AxisFormatterComp, EchartsAxisType } from "../basicChartComp/chartConfigs/cartesianAxisConfig";
+import { parallelChartChildrenMap, ChartSize, getDataKeys } from "./parallelChartConstants";
+import { parallelChartPropertyView } from "./parallelChartPropertyView";
+import _ from "lodash";
+import { useContext, useEffect, useMemo, useRef, useState } from "react";
+import ReactResizeDetector from "react-resize-detector";
+import ReactECharts from "../basicChartComp/reactEcharts";
+import * as echarts from "echarts";
+import {
+ childrenToProps,
+ depsConfig,
+ genRandomKey,
+ NameConfig,
+ UICompBuilder,
+ withDefault,
+ withExposingConfigs,
+ withViewFn,
+ ThemeContext,
+ chartColorPalette,
+ getPromiseAfterDispatch,
+ dropdownControl,
+} from "lowcoder-sdk";
+import { getEchartsLocale, i18nObjs, trans } from "i18n/comps";
+import {
+ echartsConfigOmitChildren,
+ getEchartsConfig,
+ getSelectedPoints,
+} from "./parallelChartUtils";
+import 'echarts-extension-gmap';
+import log from "loglevel";
+
+let clickEventCallback = () => {};
+
+const chartModeOptions = [
+ {
+ label: "UI",
+ value: "ui",
+ }
+] as const;
+
+let ParallelChartTmpComp = (function () {
+ return new UICompBuilder({mode:dropdownControl(chartModeOptions,'ui'),...parallelChartChildrenMap}, () => null)
+ .setPropertyViewFn(parallelChartPropertyView)
+ .build();
+})();
+
+ParallelChartTmpComp = withViewFn(ParallelChartTmpComp, (comp) => {
+ const mode = comp.children.mode.getView();
+ const onUIEvent = comp.children.onUIEvent.getView();
+ const onEvent = comp.children.onEvent.getView();
+ const echartsCompRef = useRef();
+ const [chartSize, setChartSize] = useState();
+ const firstResize = useRef(true);
+ const theme = useContext(ThemeContext);
+ const defaultChartTheme = {
+ color: chartColorPalette,
+ backgroundColor: "#fff",
+ };
+
+ let themeConfig = defaultChartTheme;
+ try {
+ themeConfig = theme?.theme.chart ? JSON.parse(theme?.theme.chart) : defaultChartTheme;
+ } catch (error) {
+ log.error('theme chart error: ', error);
+ }
+
+ const triggerClickEvent = async (dispatch: any, action: CompAction) => {
+ await getPromiseAfterDispatch(
+ dispatch,
+ action,
+ { autoHandleAfterReduce: true }
+ );
+ onEvent('click');
+ }
+
+ useEffect(() => {
+ const echartsCompInstance = echartsCompRef?.current?.getEchartsInstance();
+ if (!echartsCompInstance) {
+ return _.noop;
+ }
+ echartsCompInstance?.on("click", (param: any) => {
+ document.dispatchEvent(new CustomEvent("clickEvent", {
+ bubbles: true,
+ detail: {
+ action: 'click',
+ data: param.data,
+ }
+ }));
+ triggerClickEvent(
+ comp.dispatch,
+ changeChildAction("lastInteractionData", param.data, false)
+ );
+ });
+ return () => {
+ echartsCompInstance?.off("click");
+ document.removeEventListener('clickEvent', clickEventCallback)
+ };
+ }, []);
+
+ useEffect(() => {
+ // bind events
+ const echartsCompInstance = echartsCompRef?.current?.getEchartsInstance();
+ if (!echartsCompInstance) {
+ return _.noop;
+ }
+ echartsCompInstance?.on("selectchanged", (param: any) => {
+ const option: any = echartsCompInstance?.getOption();
+ document.dispatchEvent(new CustomEvent("clickEvent", {
+ bubbles: true,
+ detail: {
+ action: param.fromAction,
+ data: getSelectedPoints(param, option)
+ }
+ }));
+
+ if (param.fromAction === "select") {
+ comp.dispatch(changeChildAction("selectedPoints", getSelectedPoints(param, option), false));
+ onUIEvent("select");
+ } else if (param.fromAction === "unselect") {
+ comp.dispatch(changeChildAction("selectedPoints", getSelectedPoints(param, option), false));
+ onUIEvent("unselect");
+ }
+
+ triggerClickEvent(
+ comp.dispatch,
+ changeChildAction("lastInteractionData", getSelectedPoints(param, option), false)
+ );
+ });
+ // unbind
+ return () => {
+ echartsCompInstance?.off("selectchanged");
+ document.removeEventListener('clickEvent', clickEventCallback)
+ };
+ }, [onUIEvent]);
+
+ const echartsConfigChildren = _.omit(comp.children, echartsConfigOmitChildren);
+ const childrenProps = childrenToProps(echartsConfigChildren);
+
+ const option = useMemo(() => {
+ return getEchartsConfig(
+ childrenProps as ToViewReturn,
+ chartSize,
+ themeConfig
+ );
+ }, [theme, childrenProps, chartSize, ...Object.values(echartsConfigChildren)]);
+
+ return (
+ {
+ if (w && h) {
+ setChartSize({ w: w, h: h });
+ }
+ if (!firstResize.current) {
+ // ignore the first resize, which will impact the loading animation
+ echartsCompRef.current?.getEchartsInstance().resize();
+ } else {
+ firstResize.current = false;
+ }
+ }}
+ >
+ (echartsCompRef.current = e)}
+ style={{ height: "100%" }}
+ notMerge
+ lazyUpdate
+ opts={{ locale: getEchartsLocale() }}
+ option={option}
+ mode={mode}
+ />
+
+ );
+});
+
+function getYAxisFormatContextValue(
+ data: Array,
+ yAxisType: EchartsAxisType,
+ yAxisName?: string
+) {
+ const dataSample = yAxisName && data.length > 0 && data[0][yAxisName];
+ let contextValue = dataSample;
+ if (yAxisType === "time") {
+ // to timestamp
+ const time =
+ typeof dataSample === "number" || typeof dataSample === "string"
+ ? new Date(dataSample).getTime()
+ : null;
+ if (time) contextValue = time;
+ }
+ return contextValue;
+}
+
+ParallelChartTmpComp = class extends ParallelChartTmpComp {
+ private lastYAxisFormatContextVal?: JSONValue;
+ private lastColorContext?: JSONObject;
+
+ updateContext(comp: this) {
+ // the context value of axis format
+ let resultComp = comp;
+ const data = comp.children.data.getView();
+ const yAxisContextValue = getYAxisFormatContextValue(
+ data,
+ comp.children.yConfig.children.yAxisType.getView(),
+ );
+ if (yAxisContextValue !== comp.lastYAxisFormatContextVal) {
+ comp.lastYAxisFormatContextVal = yAxisContextValue;
+ resultComp = comp.setChild(
+ "yConfig",
+ comp.children.yConfig.reduce(
+ wrapChildAction(
+ "formatter",
+ AxisFormatterComp.changeContextDataAction({ value: yAxisContextValue })
+ )
+ )
+ );
+ }
+ return resultComp;
+ }
+
+ override reduce(action: CompAction): this {
+ const comp = super.reduce(action);
+ if (action.type === CompActionTypes.UPDATE_NODES_V2) {
+ const newData = comp.children.data.getView();
+ // data changes
+ if (comp.children.data !== this.children.data) {
+ setTimeout(() => {
+ // update x-axis value
+ const keys = getDataKeys(newData);
+ if (keys.length > 0 && !keys.includes(comp.children.xAxisKey.getView())) {
+ comp.children.xAxisKey.dispatch(changeValueAction(keys[0] || ""));
+ }
+ if (keys.length > 0 && !keys.includes(comp.children.yAxisKey.getView())) {
+ comp.children.yAxisKey.dispatch(changeValueAction(keys[1] || ""));
+ }
+ }, 0);
+ }
+ return this.updateContext(comp);
+ }
+ return comp;
+ }
+
+ override autoHeight(): boolean {
+ return false;
+ }
+};
+
+let ParallelChartComp = withExposingConfigs(ParallelChartTmpComp, [
+ depsConfig({
+ name: "selectedPoints",
+ desc: trans("chart.selectedPointsDesc"),
+ depKeys: ["selectedPoints"],
+ func: (input) => {
+ return input.selectedPoints;
+ },
+ }),
+ depsConfig({
+ name: "lastInteractionData",
+ desc: trans("chart.lastInteractionDataDesc"),
+ depKeys: ["lastInteractionData"],
+ func: (input) => {
+ return input.lastInteractionData;
+ },
+ }),
+ depsConfig({
+ name: "data",
+ desc: trans("chart.dataDesc"),
+ depKeys: ["data", "mode"],
+ func: (input) =>[] ,
+ }),
+ new NameConfig("title", trans("chart.titleDesc")),
+]);
+
+
+export const ParallelChartCompWithDefault = withDefault(ParallelChartComp, {
+ xAxisKey: "date",
+});
diff --git a/client/packages/lowcoder-comps/src/comps/parallelChartComp/parallelChartConstants.tsx b/client/packages/lowcoder-comps/src/comps/parallelChartComp/parallelChartConstants.tsx
new file mode 100644
index 000000000..4b383d645
--- /dev/null
+++ b/client/packages/lowcoder-comps/src/comps/parallelChartComp/parallelChartConstants.tsx
@@ -0,0 +1,193 @@
+import {
+ jsonControl,
+ stateComp,
+ toJSONObjectArray,
+ toObject,
+ BoolControl,
+ ColorControl,
+ withDefault,
+ StringControl,
+ NumberControl,
+ dropdownControl,
+ list,
+ eventHandlerControl,
+ valueComp,
+ withType,
+ uiChildren,
+ clickEvent,
+ toArray,
+ styleControl,
+ EchartDefaultTextStyle,
+ EchartDefaultChartStyle,
+ MultiCompBuilder,
+} from "lowcoder-sdk";
+import { RecordConstructorToComp, RecordConstructorToView } from "lowcoder-core";
+import { XAxisConfig, YAxisConfig } from "../basicChartComp/chartConfigs/cartesianAxisConfig";
+import { LegendConfig } from "../basicChartComp/chartConfigs/legendConfig";
+import { EchartsLegendConfig } from "../basicChartComp/chartConfigs/echartsLegendConfig";
+import { EchartsLabelConfig } from "../basicChartComp/chartConfigs/echartsLabelConfig";
+import { EChartsOption } from "echarts";
+import { i18nObjs, trans } from "i18n/comps";
+import {EchartsTitleVerticalConfig} from "../chartComp/chartConfigs/echartsTitleVerticalConfig";
+import {EchartsTitleConfig} from "../basicChartComp/chartConfigs/echartsTitleConfig";
+
+export const UIEventOptions = [
+ {
+ label: trans("chart.select"),
+ value: "select",
+ description: trans("chart.selectDesc"),
+ },
+ {
+ label: trans("chart.unSelect"),
+ value: "unselect",
+ description: trans("chart.unselectDesc"),
+ },
+] as const;
+
+export const XAxisDirectionOptions = [
+ {
+ label: trans("chart.horizontal"),
+ value: "horizontal",
+ },
+ {
+ label: trans("chart.vertical"),
+ value: "vertical",
+ },
+] as const;
+
+export type XAxisDirectionType = ValueFromOption;
+
+export const noDataAxisConfig = {
+ animation: false,
+ xAxis: {
+ type: "category",
+ name: trans("chart.noData"),
+ nameLocation: "middle",
+ data: [],
+ axisLine: {
+ lineStyle: {
+ color: "#8B8FA3",
+ },
+ },
+ },
+ yAxis: {
+ type: "value",
+ axisLabel: {
+ color: "#8B8FA3",
+ },
+ splitLine: {
+ lineStyle: {
+ color: "#F0F0F0",
+ },
+ },
+ },
+ tooltip: {
+ show: false,
+ },
+ series: [
+ {
+ data: [700],
+ type: "line",
+ itemStyle: {
+ opacity: 0,
+ },
+ },
+ ],
+} as EChartsOption;
+
+export const noDataParallelChartConfig = {
+ animation: false,
+ tooltip: {
+ show: false,
+ },
+ legend: {
+ formatter: trans("chart.unknown"),
+ top: "bottom",
+ selectedMode: false,
+ },
+ color: ["#B8BBCC", "#CED0D9", "#DCDEE6", "#E6E6EB"],
+ series: [],
+} as EChartsOption;
+
+export type ChartSize = { w: number; h: number };
+
+export const getDataKeys = (data: Array) => {
+ if (!data) {
+ return [];
+ }
+ const dataKeys: Array = [];
+ data[0].forEach((key) => {
+ if (!dataKeys.includes(key)) {
+ dataKeys.push(key);
+ }
+ });
+ return dataKeys;
+};
+
+export const chartUiModeChildren = {
+ title: withDefault(StringControl, trans("echarts.defaultTitle")),
+ data: jsonControl(toArray, i18nObjs.defaultDatasourceParallel),
+ xAxisKey: valueComp(""), // x-axis, key from data
+ xAxisDirection: dropdownControl(XAxisDirectionOptions, "horizontal"),
+ xAxisData: jsonControl(toArray, []),
+ yAxisKey: valueComp(""), // x-axis, key from data
+ xConfig: XAxisConfig,
+ yConfig: YAxisConfig,
+ legendConfig: LegendConfig,
+ onUIEvent: eventHandlerControl(UIEventOptions),
+};
+
+let chartJsonModeChildren: any = {
+ echartsOption: jsonControl(toObject, i18nObjs.defaultEchartsJsonOption),
+ echartsTitle: withDefault(StringControl, trans("echarts.defaultTitle")),
+ echartsLegendConfig: EchartsLegendConfig,
+ echartsLabelConfig: EchartsLabelConfig,
+ echartsTitleVerticalConfig: EchartsTitleVerticalConfig,
+ echartsTitleConfig:EchartsTitleConfig,
+
+ left:withDefault(NumberControl,trans('chart.defaultLeft')),
+ right:withDefault(NumberControl,trans('chart.defaultRight')),
+ top:withDefault(NumberControl,trans('chart.defaultTop')),
+ bottom:withDefault(NumberControl,trans('chart.defaultBottom')),
+
+ tooltip: withDefault(BoolControl, true),
+ legendVisibility: withDefault(BoolControl, true),
+}
+
+if (EchartDefaultChartStyle && EchartDefaultTextStyle) {
+ chartJsonModeChildren = {
+ ...chartJsonModeChildren,
+ chartStyle: styleControl(EchartDefaultChartStyle, 'chartStyle'),
+ titleStyle: styleControl(EchartDefaultTextStyle, 'titleStyle'),
+ xAxisStyle: styleControl(EchartDefaultTextStyle, 'xAxis'),
+ yAxisStyle: styleControl(EchartDefaultTextStyle, 'yAxisStyle'),
+ legendStyle: styleControl(EchartDefaultTextStyle, 'legendStyle'),
+ }
+}
+
+export type UIChartDataType = {
+ seriesName: string;
+ // coordinate chart
+ x?: any;
+ y?: any;
+ // parallel or funnel
+ itemName?: any;
+ value?: any;
+};
+
+export type NonUIChartDataType = {
+ name: string;
+ value: any;
+}
+
+export const parallelChartChildrenMap = {
+ selectedPoints: stateComp>([]),
+ lastInteractionData: stateComp | NonUIChartDataType>({}),
+ onEvent: eventHandlerControl([clickEvent] as const),
+ ...chartUiModeChildren,
+ ...chartJsonModeChildren,
+};
+
+const chartUiChildrenMap = uiChildren(parallelChartChildrenMap);
+export type ChartCompPropsType = RecordConstructorToView;
+export type ChartCompChildrenType = RecordConstructorToComp;
diff --git a/client/packages/lowcoder-comps/src/comps/parallelChartComp/parallelChartPropertyView.tsx b/client/packages/lowcoder-comps/src/comps/parallelChartComp/parallelChartPropertyView.tsx
new file mode 100644
index 000000000..3106c44d7
--- /dev/null
+++ b/client/packages/lowcoder-comps/src/comps/parallelChartComp/parallelChartPropertyView.tsx
@@ -0,0 +1,70 @@
+import { changeChildAction, CompAction } from "lowcoder-core";
+import { ChartCompChildrenType, getDataKeys } from "./parallelChartConstants";
+import {
+ CustomModal,
+ Dropdown,
+ hiddenPropertyView,
+ Option,
+ RedButton,
+ Section,
+ sectionNames,
+ controlItem,
+} from "lowcoder-sdk";
+import { trans } from "i18n/comps";
+
+export function parallelChartPropertyView(
+ children: ChartCompChildrenType,
+ dispatch: (action: CompAction) => void
+) {
+ const columnOptions = getDataKeys(children.data.getView()).map((key) => ({
+ label: key,
+ value: key,
+ }));
+
+ const uiModePropertyView = (
+ <>
+
+
+ {children.onUIEvent.propertyView({title: trans("chart.chartEventHandlers")})}
+
+
+ {children.onEvent.propertyView()}
+
+
+
+ {children.echartsTitleConfig.getPropertyView()}
+ {children.echartsTitleVerticalConfig.getPropertyView()}
+ {children.title.propertyView({ label: trans("chart.title") })}
+ {children.left.propertyView({ label: trans("chart.left"), tooltip: trans("echarts.leftTooltip") })}
+ {children.right.propertyView({ label: trans("chart.right"), tooltip: trans("echarts.rightTooltip") })}
+ {children.top.propertyView({ label: trans("chart.top"), tooltip: trans("echarts.topTooltip") })}
+ {children.bottom.propertyView({ label: trans("chart.bottom"), tooltip: trans("echarts.bottomTooltip") })}
+ {hiddenPropertyView(children)}
+ {children.tooltip.propertyView({label: trans("echarts.tooltip"), tooltip: trans("echarts.tooltipTooltip")})}
+
+
+ {children.chartStyle?.getPropertyView()}
+
+
+ {children.titleStyle?.getPropertyView()}
+
+
+ {children.data.propertyView({
+ label: trans("chart.data"),
+ })}
+
+ >
+ );
+
+ const getChatConfigByMode = (mode: string) => {
+ switch(mode) {
+ case "ui":
+ return uiModePropertyView;
+ }
+ }
+ return (
+ <>
+ {getChatConfigByMode(children.mode.getView())}
+ >
+ );
+}
diff --git a/client/packages/lowcoder-comps/src/comps/parallelChartComp/parallelChartUtils.ts b/client/packages/lowcoder-comps/src/comps/parallelChartComp/parallelChartUtils.ts
new file mode 100644
index 000000000..407a2df69
--- /dev/null
+++ b/client/packages/lowcoder-comps/src/comps/parallelChartComp/parallelChartUtils.ts
@@ -0,0 +1,241 @@
+import {
+ ChartCompPropsType,
+ ChartSize,
+ noDataParallelChartConfig,
+} from "comps/parallelChartComp/parallelChartConstants";
+import { EChartsOptionWithMap } from "../basicChartComp/reactEcharts/types";
+import _ from "lodash";
+import { googleMapsApiUrl } from "../basicChartComp/chartConfigs/chartUrls";
+import parseBackground from "../../util/gradientBackgroundColor";
+import {chartStyleWrapper, styleWrapper} from "../../util/styleWrapper";
+// Define the configuration interface to match the original transform
+
+interface AggregateConfig {
+ resultDimensions: Array<{
+ name: string;
+ from: string;
+ method?: string; // e.g., 'min', 'Q1', 'median', 'Q3', 'max'
+ }>;
+ groupBy: string;
+}
+
+// Custom transform function
+function customAggregateTransform(params: {
+ upstream: { source: any[] };
+ config: AggregateConfig;
+}): any[] {
+ const { upstream, config } = params;
+ const data = upstream.source;
+
+ // Assume data is an array of arrays, with the first row as headers
+ const headers = data[0];
+ const rows = data.slice(1);
+
+ // Find the index of the groupBy column
+ const groupByIndex = headers.indexOf(config.groupBy);
+ if (groupByIndex === -1) {
+ return [];
+ }
+
+ // Group rows by the groupBy column
+ const groups: { [key: string]: any[][] } = {};
+ rows.forEach(row => {
+ const key = row[groupByIndex];
+ if (!groups[key]) {
+ groups[key] = [];
+ }
+ groups[key].push(row);
+ });
+
+ // Define aggregation functions
+ const aggregators: {
+ [method: string]: (values: number[]) => number;
+ } = {
+ min: values => Math.min(...values),
+ max: values => Math.max(...values),
+ Q1: values => percentile(values, 25),
+ median: values => percentile(values, 50),
+ Q3: values => percentile(values, 75),
+ };
+
+ // Helper function to calculate percentiles (Q1, median, Q3)
+ function percentile(arr: number[], p: number): number {
+ const sorted = arr.slice().sort((a, b) => a - b);
+ const index = (p / 100) * (sorted.length - 1);
+ const i = Math.floor(index);
+ const f = index - i;
+ if (i === sorted.length - 1) {
+ return sorted[i];
+ }
+ return sorted[i] + f * (sorted[i + 1] - sorted[i]);
+ }
+
+ // Prepare output headers from resultDimensions
+ const outputHeaders = config.resultDimensions.map(dim => dim.name);
+
+ // Compute aggregated data for each group
+ const aggregatedData: any[][] = [];
+ for (const key in groups) {
+ const groupRows = groups[key];
+ const row: any[] = [];
+
+ config.resultDimensions.forEach(dim => {
+ if (dim.from === config.groupBy) {
+ // Include the group key directly
+ row.push(key);
+ } else {
+ // Find the index of the 'from' column
+ const fromIndex = headers.indexOf(dim.from);
+ if (fromIndex === -1) {
+ return;
+ }
+ // Extract values for the 'from' column in this group
+ const values = groupRows
+ .map(r => parseFloat(r[fromIndex]))
+ .filter(v => !isNaN(v));
+ if (dim.method && aggregators[dim.method]) {
+ // Apply the aggregation method
+ row.push(aggregators[dim.method](values));
+ } else {
+ return;
+ }
+ }
+ });
+
+ aggregatedData.push(row);
+ }
+
+ // Return the transformed data with headers
+ return [outputHeaders, ...aggregatedData];
+}
+
+export const echartsConfigOmitChildren = [
+ "hidden",
+ "selectedPoints",
+ "onUIEvent",
+ "mapInstance"
+] as const;
+type EchartsConfigProps = Omit;
+
+// https://echarts.apache.org/en/option.html
+export function getEchartsConfig(
+ props: EchartsConfigProps,
+ chartSize?: ChartSize,
+ theme?: any,
+): EChartsOptionWithMap {
+ const gridPos = {
+ left: `${props?.left}%`,
+ right: `${props?.right}%`,
+ bottom: `${props?.bottom}%`,
+ top: `${props?.top}%`,
+ };
+
+ let config: any = {
+ title: {
+ text: props.title,
+ top: props.echartsTitleVerticalConfig.top,
+ left:props.echartsTitleConfig.top,
+ textStyle: {
+ ...styleWrapper(props?.titleStyle, theme?.titleStyle)
+ }
+ },
+ backgroundColor: parseBackground( props?.chartStyle?.background || theme?.chartStyle?.backgroundColor || "#FFFFFF"),
+ tooltip: props.tooltip && {
+ trigger: "axis",
+ axisPointer: {
+ type: "line",
+ lineStyle: {
+ color: "rgba(0,0,0,0.2)",
+ width: 2,
+ type: "solid"
+ }
+ }
+ },
+ grid: {
+ ...gridPos,
+ containLabel: true,
+ },
+ };
+
+ if (props.data.length <= 0) {
+ // no data
+ return {
+ ...config,
+ ...noDataParallelChartConfig,
+ };
+ }
+ // y-axis is category and time, data doesn't need to aggregate
+ let transformedData = props.data;
+
+ config = {
+ ...config,
+ series: [{
+ name: 'parallel',
+ type: 'parallel',
+ lineStyle: {
+ width: 4
+ },
+ data: props.data.slice(1)
+ }],
+ parallelAxis: props.data[0].map((c, i) => ({ dim: i, name: c, type: typeof props.data[1][i] === 'string'?'category':'value'}))
+ };
+
+ console.log("Echarts transformedData and config", transformedData, config);
+ return config;
+}
+
+export function getSelectedPoints(param: any, option: any) {
+ const series = option.series;
+ const dataSource = _.isArray(option.dataset) && option.dataset[0]?.source;
+ if (series && dataSource) {
+ return param.selected.flatMap((selectInfo: any) => {
+ const seriesInfo = series[selectInfo.seriesIndex];
+ if (!seriesInfo || !seriesInfo.encode) {
+ return [];
+ }
+ return selectInfo.dataIndex.map((index: any) => {
+ const commonResult = {
+ seriesName: seriesInfo.name,
+ };
+ if (seriesInfo.encode.itemName && seriesInfo.encode.value) {
+ return {
+ ...commonResult,
+ itemName: dataSource[index][seriesInfo.encode.itemName],
+ value: dataSource[index][seriesInfo.encode.value],
+ };
+ } else {
+ return {
+ ...commonResult,
+ x: dataSource[index][seriesInfo.encode.x],
+ y: dataSource[index][seriesInfo.encode.y],
+ };
+ }
+ });
+ });
+ }
+ return [];
+}
+
+export function loadGoogleMapsScript(apiKey: string) {
+ const mapsUrl = `${googleMapsApiUrl}?key=${apiKey}`;
+ const scripts = document.getElementsByTagName('script');
+ // is script already loaded
+ let scriptIndex = _.findIndex(scripts, (script) => script.src.endsWith(mapsUrl));
+ if(scriptIndex > -1) {
+ return scripts[scriptIndex];
+ }
+ // is script loaded with diff api_key, remove the script and load again
+ scriptIndex = _.findIndex(scripts, (script) => script.src.startsWith(googleMapsApiUrl));
+ if(scriptIndex > -1) {
+ scripts[scriptIndex].remove();
+ }
+
+ const script = document.createElement("script");
+ script.type = "text/javascript";
+ script.src = mapsUrl;
+ script.async = true;
+ script.defer = true;
+ window.document.body.appendChild(script);
+
+ return script;
+}
diff --git a/client/packages/lowcoder-comps/src/comps/pieChartComp/pieChartComp.tsx b/client/packages/lowcoder-comps/src/comps/pieChartComp/pieChartComp.tsx
new file mode 100644
index 000000000..d502a8090
--- /dev/null
+++ b/client/packages/lowcoder-comps/src/comps/pieChartComp/pieChartComp.tsx
@@ -0,0 +1,314 @@
+import {
+ changeChildAction,
+ changeValueAction,
+ CompAction,
+ CompActionTypes,
+ wrapChildAction,
+} from "lowcoder-core";
+import { AxisFormatterComp, EchartsAxisType } from "../basicChartComp/chartConfigs/cartesianAxisConfig";
+import { pieChartChildrenMap, ChartSize, getDataKeys } from "./pieChartConstants";
+import { pieChartPropertyView } from "./pieChartPropertyView";
+import _ from "lodash";
+import { useContext, useEffect, useMemo, useRef, useState } from "react";
+import ReactResizeDetector from "react-resize-detector";
+import ReactECharts from "../basicChartComp/reactEcharts";
+import * as echarts from "echarts";
+import {
+ childrenToProps,
+ depsConfig,
+ genRandomKey,
+ NameConfig,
+ UICompBuilder,
+ withDefault,
+ withExposingConfigs,
+ withViewFn,
+ ThemeContext,
+ chartColorPalette,
+ getPromiseAfterDispatch,
+ dropdownControl,
+} from "lowcoder-sdk";
+import { getEchartsLocale, i18nObjs, trans } from "i18n/comps";
+import {
+ echartsConfigOmitChildren,
+ getEchartsConfig,
+ getSelectedPoints,
+} from "./pieChartUtils";
+import 'echarts-extension-gmap';
+import log from "loglevel";
+
+let clickEventCallback = () => {};
+
+const chartModeOptions = [
+ {
+ label: "UI",
+ value: "ui",
+ }
+] as const;
+
+let PieChartTmpComp = (function () {
+ return new UICompBuilder({mode:dropdownControl(chartModeOptions,'ui'),...pieChartChildrenMap}, () => null)
+ .setPropertyViewFn(pieChartPropertyView)
+ .build();
+})();
+
+PieChartTmpComp = withViewFn(PieChartTmpComp, (comp) => {
+ const mode = comp.children.mode.getView();
+ const onUIEvent = comp.children.onUIEvent.getView();
+ const onEvent = comp.children.onEvent.getView();
+ const echartsCompRef = useRef();
+ const [chartSize, setChartSize] = useState();
+ const firstResize = useRef(true);
+ const theme = useContext(ThemeContext);
+ const defaultChartTheme = {
+ color: chartColorPalette,
+ backgroundColor: "#fff",
+ };
+
+ let themeConfig = defaultChartTheme;
+ try {
+ themeConfig = theme?.theme.chart ? JSON.parse(theme?.theme.chart) : defaultChartTheme;
+ } catch (error) {
+ log.error('theme chart error: ', error);
+ }
+
+ const triggerClickEvent = async (dispatch: any, action: CompAction) => {
+ await getPromiseAfterDispatch(
+ dispatch,
+ action,
+ { autoHandleAfterReduce: true }
+ );
+ onEvent('click');
+ }
+
+ useEffect(() => {
+ const echartsCompInstance = echartsCompRef?.current?.getEchartsInstance();
+ if (!echartsCompInstance) {
+ return _.noop;
+ }
+ echartsCompInstance?.on("click", (param: any) => {
+ document.dispatchEvent(new CustomEvent("clickEvent", {
+ bubbles: true,
+ detail: {
+ action: 'click',
+ data: param.data,
+ }
+ }));
+ triggerClickEvent(
+ comp.dispatch,
+ changeChildAction("lastInteractionData", param.data, false)
+ );
+ });
+ return () => {
+ echartsCompInstance?.off("click");
+ document.removeEventListener('clickEvent', clickEventCallback)
+ };
+ }, []);
+
+ useEffect(() => {
+ // bind events
+ const echartsCompInstance = echartsCompRef?.current?.getEchartsInstance();
+ if (!echartsCompInstance) {
+ return _.noop;
+ }
+ echartsCompInstance?.on("selectchanged", (param: any) => {
+ const option: any = echartsCompInstance?.getOption();
+ document.dispatchEvent(new CustomEvent("clickEvent", {
+ bubbles: true,
+ detail: {
+ action: param.fromAction,
+ data: getSelectedPoints(param, option)
+ }
+ }));
+
+ if (param.fromAction === "select") {
+ comp.dispatch(changeChildAction("selectedPoints", getSelectedPoints(param, option), false));
+ onUIEvent("select");
+ } else if (param.fromAction === "unselect") {
+ comp.dispatch(changeChildAction("selectedPoints", getSelectedPoints(param, option), false));
+ onUIEvent("unselect");
+ }
+
+ triggerClickEvent(
+ comp.dispatch,
+ changeChildAction("lastInteractionData", getSelectedPoints(param, option), false)
+ );
+ });
+ // unbind
+ return () => {
+ echartsCompInstance?.off("selectchanged");
+ document.removeEventListener('clickEvent', clickEventCallback)
+ };
+ }, [onUIEvent]);
+
+ const echartsConfigChildren = _.omit(comp.children, echartsConfigOmitChildren);
+ const childrenProps = childrenToProps(echartsConfigChildren);
+ const [mapJson, setMapJson] = useState(null);
+ useEffect(() => {
+ const fetchMapData = async () => {
+ if (childrenProps.chartConfig.subtype === 'geoPie') {
+ let fetchedMapJson = i18nObjs.usaMap;
+ try {
+ const response = await fetch(childrenProps.chartConfig.mapUrl, childrenProps.chartConfig.mapSpecial);
+ fetchedMapJson = await response.json();
+ } catch {}
+ echarts.registerMap('jsonmap', fetchedMapJson);
+ setMapJson(fetchedMapJson);
+ }
+ };
+
+ fetchMapData();
+ }, [childrenProps.chartConfig.subtype, childrenProps.chartConfig.mapUrl, childrenProps.chartConfig.mapSpecial]);
+
+ const option = useMemo(() => {
+ if (!mapJson && childrenProps.chartConfig.subtype === 'geoPie') {
+ return {}; // Return an empty object or some default value until the map is loaded
+ }
+ return getEchartsConfig(
+ childrenProps as ToViewReturn,
+ chartSize,
+ themeConfig
+ );
+ }, [mapJson, theme, childrenProps, chartSize, ...Object.values(echartsConfigChildren)]);
+
+ return (
+ {
+ if (w && h) {
+ setChartSize({ w: w, h: h });
+ }
+ if (!firstResize.current) {
+ // ignore the first resize, which will impact the loading animation
+ echartsCompRef.current?.getEchartsInstance().resize();
+ } else {
+ firstResize.current = false;
+ }
+ }}
+ >
+ (echartsCompRef.current = e)}
+ style={{ height: "100%" }}
+ notMerge
+ lazyUpdate
+ opts={{ locale: getEchartsLocale() }}
+ option={option}
+ mode={mode}
+ />
+
+ );
+});
+
+function getYAxisFormatContextValue(
+ data: Array,
+ yAxisType: EchartsAxisType,
+ yAxisName?: string
+) {
+ const dataSample = yAxisName && data.length > 0 && data[0][yAxisName];
+ let contextValue = dataSample;
+ if (yAxisType === "time") {
+ // to timestamp
+ const time =
+ typeof dataSample === "number" || typeof dataSample === "string"
+ ? new Date(dataSample).getTime()
+ : null;
+ if (time) contextValue = time;
+ }
+ return contextValue;
+}
+
+PieChartTmpComp = class extends PieChartTmpComp {
+ private lastYAxisFormatContextVal?: JSONValue;
+ private lastColorContext?: JSONObject;
+
+ updateContext(comp: this) {
+ // the context value of axis format
+ let resultComp = comp;
+ const data = comp.children.data.getView();
+ const sampleSeries = comp.children.series.getView().find((s) => !s.getView().hide);
+ const yAxisContextValue = getYAxisFormatContextValue(
+ data,
+ comp.children.yConfig.children.yAxisType.getView(),
+ sampleSeries?.children.columnName.getView()
+ );
+ if (yAxisContextValue !== comp.lastYAxisFormatContextVal) {
+ comp.lastYAxisFormatContextVal = yAxisContextValue;
+ resultComp = comp.setChild(
+ "yConfig",
+ comp.children.yConfig.reduce(
+ wrapChildAction(
+ "formatter",
+ AxisFormatterComp.changeContextDataAction({ value: yAxisContextValue })
+ )
+ )
+ );
+ }
+ return resultComp;
+ }
+
+ override reduce(action: CompAction): this {
+ const comp = super.reduce(action);
+ if (action.type === CompActionTypes.UPDATE_NODES_V2) {
+ const newData = comp.children.data.getView();
+ // data changes
+ if (comp.children.data !== this.children.data) {
+ setTimeout(() => {
+ // update x-axis value
+ const keys = getDataKeys(newData);
+ if (keys.length > 0 && !keys.includes(comp.children.xAxisKey.getView())) {
+ comp.children.xAxisKey.dispatch(changeValueAction(keys[0] || ""));
+ }
+ // pass to child series comp
+ comp.children.series.dispatchDataChanged(newData);
+ }, 0);
+ }
+ return this.updateContext(comp);
+ }
+ return comp;
+ }
+
+ override autoHeight(): boolean {
+ return false;
+ }
+};
+
+let PieChartComp = withExposingConfigs(PieChartTmpComp, [
+ depsConfig({
+ name: "selectedPoints",
+ desc: trans("chart.selectedPointsDesc"),
+ depKeys: ["selectedPoints"],
+ func: (input) => {
+ return input.selectedPoints;
+ },
+ }),
+ depsConfig({
+ name: "lastInteractionData",
+ desc: trans("chart.lastInteractionDataDesc"),
+ depKeys: ["lastInteractionData"],
+ func: (input) => {
+ return input.lastInteractionData;
+ },
+ }),
+ depsConfig({
+ name: "data",
+ desc: trans("chart.dataDesc"),
+ depKeys: ["data", "mode"],
+ func: (input) =>[] ,
+ }),
+ new NameConfig("title", trans("chart.titleDesc")),
+]);
+
+
+export const PieChartCompWithDefault = withDefault(PieChartComp, {
+ xAxisKey: "date",
+ series: [
+ {
+ dataIndex: genRandomKey(),
+ seriesName: trans("chart.spending"),
+ columnName: "spending",
+ },
+ {
+ dataIndex: genRandomKey(),
+ seriesName: trans("chart.budget"),
+ columnName: "budget",
+ },
+ ],
+});
diff --git a/client/packages/lowcoder-comps/src/comps/pieChartComp/pieChartConstants.tsx b/client/packages/lowcoder-comps/src/comps/pieChartComp/pieChartConstants.tsx
new file mode 100644
index 000000000..62e5be971
--- /dev/null
+++ b/client/packages/lowcoder-comps/src/comps/pieChartComp/pieChartConstants.tsx
@@ -0,0 +1,311 @@
+import {
+ jsonControl,
+ stateComp,
+ toJSONObjectArray,
+ toObject,
+ BoolControl,
+ ColorControl,
+ withDefault,
+ StringControl,
+ NumberControl,
+ dropdownControl,
+ list,
+ eventHandlerControl,
+ valueComp,
+ withType,
+ uiChildren,
+ clickEvent,
+ toArray,
+ styleControl,
+ EchartDefaultTextStyle,
+ EchartDefaultChartStyle,
+ MultiCompBuilder,
+} from "lowcoder-sdk";
+import { RecordConstructorToComp, RecordConstructorToView } from "lowcoder-core";
+import { BarChartConfig } from "../basicChartComp/chartConfigs/barChartConfig";
+import { XAxisConfig, YAxisConfig } from "../basicChartComp/chartConfigs/cartesianAxisConfig";
+import { LegendConfig } from "../basicChartComp/chartConfigs/legendConfig";
+import { EchartsLegendConfig } from "../basicChartComp/chartConfigs/echartsLegendConfig";
+import { EchartsLabelConfig } from "../basicChartComp/chartConfigs/echartsLabelConfig";
+import { PieChartConfig } from "../basicChartComp/chartConfigs/pieChartConfig";
+import { ScatterChartConfig } from "../basicChartComp/chartConfigs/scatterChartConfig";
+import { SeriesListComp } from "./seriesComp";
+import { EChartsOption } from "echarts";
+import { i18nObjs, trans } from "i18n/comps";
+import { GaugeChartConfig } from "../basicChartComp/chartConfigs/gaugeChartConfig";
+import { FunnelChartConfig } from "../basicChartComp/chartConfigs/funnelChartConfig";
+import {EchartsTitleVerticalConfig} from "../chartComp/chartConfigs/echartsTitleVerticalConfig";
+import {EchartsTitleConfig} from "../basicChartComp/chartConfigs/echartsTitleConfig";
+
+export const ChartTypeOptions = [
+ {
+ label: trans("chart.bar"),
+ value: "bar",
+ },
+ {
+ label: trans("chart.line"),
+ value: "line",
+ },
+ {
+ label: trans("chart.scatter"),
+ value: "scatter",
+ },
+ {
+ label: trans("chart.pie"),
+ value: "pie",
+ },
+] as const;
+
+export const UIEventOptions = [
+ {
+ label: trans("chart.select"),
+ value: "select",
+ description: trans("chart.selectDesc"),
+ },
+ {
+ label: trans("chart.unSelect"),
+ value: "unselect",
+ description: trans("chart.unselectDesc"),
+ },
+] as const;
+
+export const XAxisDirectionOptions = [
+ {
+ label: trans("chart.horizontal"),
+ value: "horizontal",
+ },
+ {
+ label: trans("chart.vertical"),
+ value: "vertical",
+ },
+] as const;
+
+export type XAxisDirectionType = ValueFromOption;
+
+export const noDataAxisConfig = {
+ animation: false,
+ xAxis: {
+ type: "category",
+ name: trans("chart.noData"),
+ nameLocation: "middle",
+ data: [],
+ axisLine: {
+ lineStyle: {
+ color: "#8B8FA3",
+ },
+ },
+ },
+ yAxis: {
+ type: "value",
+ axisLabel: {
+ color: "#8B8FA3",
+ },
+ splitLine: {
+ lineStyle: {
+ color: "#F0F0F0",
+ },
+ },
+ },
+ tooltip: {
+ show: false,
+ },
+ series: [
+ {
+ data: [700],
+ type: "line",
+ itemStyle: {
+ opacity: 0,
+ },
+ },
+ ],
+} as EChartsOption;
+
+export const noDataPieChartConfig = {
+ animation: false,
+ tooltip: {
+ show: false,
+ },
+ legend: {
+ formatter: trans("chart.unknown"),
+ top: "bottom",
+ selectedMode: false,
+ },
+ color: ["#B8BBCC", "#CED0D9", "#DCDEE6", "#E6E6EB"],
+ series: [
+ {
+ type: "pie",
+ radius: "35%",
+ center: ["25%", "50%"],
+ silent: true,
+ label: {
+ show: false,
+ },
+ data: [
+ {
+ name: "1",
+ value: 70,
+ },
+ {
+ name: "2",
+ value: 68,
+ },
+ {
+ name: "3",
+ value: 48,
+ },
+ {
+ name: "4",
+ value: 40,
+ },
+ ],
+ },
+ {
+ type: "pie",
+ radius: "35%",
+ center: ["75%", "50%"],
+ silent: true,
+ label: {
+ show: false,
+ },
+ data: [
+ {
+ name: "1",
+ value: 70,
+ },
+ {
+ name: "2",
+ value: 68,
+ },
+ {
+ name: "3",
+ value: 48,
+ },
+ {
+ name: "4",
+ value: 40,
+ },
+ ],
+ },
+ ],
+} as EChartsOption;
+
+const areaPiecesChildrenMap = {
+ color: ColorControl,
+ from: StringControl,
+ to: StringControl,
+ // unique key, for sort
+ dataIndex: valueComp(""),
+};
+const AreaPiecesTmpComp = new MultiCompBuilder(areaPiecesChildrenMap, (props) => {
+ return props;
+})
+ .setPropertyViewFn((children: any) =>
+ (<>
+ {children.color.propertyView({label: trans("pieChart.color")})}
+ {children.from.propertyView({label: trans("pieChart.from")})}
+ {children.to.propertyView({label: trans("pieChart.to")})}
+ >)
+ )
+ .build();
+
+export type ChartSize = { w: number; h: number };
+
+export const getDataKeys = (data: Array) => {
+ if (!data) {
+ return [];
+ }
+ const dataKeys: Array = [];
+ data.slice(0, 50).forEach((d) => {
+ Object.keys(d).forEach((key) => {
+ if (!dataKeys.includes(key)) {
+ dataKeys.push(key);
+ }
+ });
+ });
+ return dataKeys;
+};
+
+const ChartOptionMap = {
+ pie: PieChartConfig,
+ scatter: ScatterChartConfig,
+};
+
+const EchartsOptionMap = {
+ funnel: FunnelChartConfig,
+ gauge: GaugeChartConfig,
+};
+
+const ChartOptionComp = withType(ChartOptionMap, "pie");
+const EchartsOptionComp = withType(EchartsOptionMap, "funnel");
+export type CharOptionCompType = keyof typeof ChartOptionMap;
+
+export const chartUiModeChildren = {
+ title: withDefault(StringControl, trans("echarts.defaultTitle")),
+ data: jsonControl(toJSONObjectArray, i18nObjs.defaultDataSource),
+ xAxisKey: valueComp(""), // x-axis, key from data
+ xAxisDirection: dropdownControl(XAxisDirectionOptions, "horizontal"),
+ xAxisData: jsonControl(toArray, []),
+ series: SeriesListComp,
+ xConfig: XAxisConfig,
+ yConfig: YAxisConfig,
+ legendConfig: LegendConfig,
+ chartConfig: ChartOptionComp,
+ areaPieces: list(AreaPiecesTmpComp),
+ onUIEvent: eventHandlerControl(UIEventOptions),
+};
+
+let chartJsonModeChildren: any = {
+ echartsOption: jsonControl(toObject, i18nObjs.defaultEchartsJsonOption),
+ echartsTitle: withDefault(StringControl, trans("echarts.defaultTitle")),
+ echartsLegendConfig: EchartsLegendConfig,
+ echartsLabelConfig: EchartsLabelConfig,
+ echartsConfig: EchartsOptionComp,
+ echartsTitleVerticalConfig: EchartsTitleVerticalConfig,
+ echartsTitleConfig:EchartsTitleConfig,
+
+ left:withDefault(NumberControl,trans('chart.defaultLeft')),
+ right:withDefault(NumberControl,trans('chart.defaultRight')),
+ top:withDefault(NumberControl,trans('chart.defaultTop')),
+ bottom:withDefault(NumberControl,trans('chart.defaultBottom')),
+
+ tooltip: withDefault(BoolControl, true),
+ legendVisibility: withDefault(BoolControl, true),
+}
+
+if (EchartDefaultChartStyle && EchartDefaultTextStyle) {
+ chartJsonModeChildren = {
+ ...chartJsonModeChildren,
+ chartStyle: styleControl(EchartDefaultChartStyle, 'chartStyle'),
+ titleStyle: styleControl(EchartDefaultTextStyle, 'titleStyle'),
+ xAxisStyle: styleControl(EchartDefaultTextStyle, 'xAxis'),
+ yAxisStyle: styleControl(EchartDefaultTextStyle, 'yAxisStyle'),
+ legendStyle: styleControl(EchartDefaultTextStyle, 'legendStyle'),
+ }
+}
+
+export type UIChartDataType = {
+ seriesName: string;
+ // coordinate chart
+ x?: any;
+ y?: any;
+ // pie or funnel
+ itemName?: any;
+ value?: any;
+};
+
+export type NonUIChartDataType = {
+ name: string;
+ value: any;
+}
+
+export const pieChartChildrenMap = {
+ selectedPoints: stateComp>([]),
+ lastInteractionData: stateComp | NonUIChartDataType>({}),
+ onEvent: eventHandlerControl([clickEvent] as const),
+ ...chartUiModeChildren,
+ ...chartJsonModeChildren,
+};
+
+const chartUiChildrenMap = uiChildren(pieChartChildrenMap);
+export type ChartCompPropsType = RecordConstructorToView;
+export type ChartCompChildrenType = RecordConstructorToComp;
diff --git a/client/packages/lowcoder-comps/src/comps/pieChartComp/pieChartPropertyView.tsx b/client/packages/lowcoder-comps/src/comps/pieChartComp/pieChartPropertyView.tsx
new file mode 100644
index 000000000..626a491c0
--- /dev/null
+++ b/client/packages/lowcoder-comps/src/comps/pieChartComp/pieChartPropertyView.tsx
@@ -0,0 +1,144 @@
+import { changeChildAction, CompAction } from "lowcoder-core";
+import { ChartCompChildrenType, ChartTypeOptions,getDataKeys } from "./pieChartConstants";
+import { newSeries } from "./seriesComp";
+import {
+ CustomModal,
+ Dropdown,
+ hiddenPropertyView,
+ Option,
+ RedButton,
+ Section,
+ sectionNames,
+ controlItem,
+} from "lowcoder-sdk";
+import { trans } from "i18n/comps";
+
+export function pieChartPropertyView(
+ children: ChartCompChildrenType,
+ dispatch: (action: CompAction) => void
+) {
+ const series = children.series.getView();
+ const columnOptions = getDataKeys(children.data.getView()).map((key) => ({
+ label: key,
+ value: key,
+ }));
+
+ const uiModePropertyView = (
+ <>
+
+ {children.chartConfig.getPropertyView()}
+ {
+ dispatch(changeChildAction("xAxisKey", value));
+ }}
+ />
+ {children.chartConfig.getView().subtype === "waterfall" && children.xAxisData.propertyView({
+ label: "X-Label-Data"
+ })}
+ s.getView().seriesName}
+ popoverTitle={(s) => s.getView().columnName}
+ content={(s, index) => (
+ <>
+ {s.getPropertyViewWithData(columnOptions)}
+ {
+ {
+ CustomModal.confirm({
+ title: trans("chart.delete"),
+ content: trans("chart.confirmDelete") + `${s.getView().seriesName}?`,
+ onConfirm: () =>
+ children.series.dispatch(children.series.deleteAction(index)),
+ confirmBtnType: "delete",
+ okText: trans("chart.delete"),
+ });
+ }}
+ >
+ {trans("chart.delete")}
+
+ }
+ >
+ )}
+ onAdd={() => {
+ if (columnOptions.length <= 0) {
+ return;
+ }
+ children.series.dispatch(
+ children.series.pushAction(
+ newSeries(trans("chart.customSeries"), columnOptions[0].value)
+ )
+ );
+ }}
+ onMove={(fromIndex, toIndex) => {
+ const action = children.series.arrayMoveAction(fromIndex, toIndex);
+ children.series.dispatch(action);
+ }}
+ hide={(s) => s.getView().hide}
+ onHide={(s, hide) => s.children.hide.dispatchChangeValueAction(hide)}
+ dataIndex={(s) => s.getView().dataIndex}
+ />
+
+
+
+ {children.onUIEvent.propertyView({title: trans("chart.chartEventHandlers")})}
+
+
+ {children.onEvent.propertyView()}
+
+
+
+ {children.echartsTitleConfig.getPropertyView()}
+ {children.echartsTitleVerticalConfig.getPropertyView()}
+ {children.legendConfig.getPropertyView()}
+ {children.title.propertyView({ label: trans("chart.title") })}
+ {children.left.propertyView({ label: trans("chart.left"), tooltip: trans("echarts.leftTooltip") })}
+ {children.right.propertyView({ label: trans("chart.right"), tooltip: trans("echarts.rightTooltip") })}
+ {children.top.propertyView({ label: trans("chart.top"), tooltip: trans("echarts.topTooltip") })}
+ {children.bottom.propertyView({ label: trans("chart.bottom"), tooltip: trans("echarts.bottomTooltip") })}
+ {children.chartConfig.children.compType.getView() !== "pie" && (
+ <>
+ {children.xAxisDirection.propertyView({
+ label: trans("chart.xAxisDirection"),
+ radioButton: true,
+ })}
+ {children.xConfig.getPropertyView()}
+ {children.yConfig.getPropertyView()}
+ >
+ )}
+ {hiddenPropertyView(children)}
+ {children.tooltip.propertyView({label: trans("echarts.tooltip"), tooltip: trans("echarts.tooltipTooltip")})}
+
+
+ {children.chartStyle?.getPropertyView()}
+
+
+ {children.titleStyle?.getPropertyView()}
+
+
+ {children.legendStyle?.getPropertyView()}
+
+
+ {children.data.propertyView({
+ label: trans("chart.data"),
+ })}
+
+ >
+ );
+
+ const getChatConfigByMode = (mode: string) => {
+ switch(mode) {
+ case "ui":
+ return uiModePropertyView;
+ }
+ }
+ return (
+ <>
+ {getChatConfigByMode(children.mode.getView())}
+ >
+ );
+}
diff --git a/client/packages/lowcoder-comps/src/comps/pieChartComp/pieChartUtils.ts b/client/packages/lowcoder-comps/src/comps/pieChartComp/pieChartUtils.ts
new file mode 100644
index 000000000..cf3b6a664
--- /dev/null
+++ b/client/packages/lowcoder-comps/src/comps/pieChartComp/pieChartUtils.ts
@@ -0,0 +1,341 @@
+import {
+ CharOptionCompType,
+ ChartCompPropsType,
+ ChartSize,
+ noDataAxisConfig,
+ noDataPieChartConfig,
+} from "comps/pieChartComp/pieChartConstants";
+import { getPieRadiusAndCenter } from "comps/basicChartComp/chartConfigs/pieChartConfig";
+import { EChartsOptionWithMap } from "../basicChartComp/reactEcharts/types";
+import _ from "lodash";
+import { chartColorPalette, isNumeric, JSONObject, loadScript } from "lowcoder-sdk";
+import { calcXYConfig } from "comps/basicChartComp/chartConfigs/cartesianAxisConfig";
+import Big from "big.js";
+import { googleMapsApiUrl } from "../basicChartComp/chartConfigs/chartUrls";
+import opacityToHex from "../../util/opacityToHex";
+import parseBackground from "../../util/gradientBackgroundColor";
+import {ba, s} from "@fullcalendar/core/internal-common";
+import {chartStyleWrapper, styleWrapper} from "../../util/styleWrapper";
+
+export function transformData(
+ originData: JSONObject[],
+ xAxis: string,
+ seriesColumnNames: string[]
+) {
+ // aggregate data by x-axis
+ const transformedData: JSONObject[] = [];
+ originData.reduce((prev, cur) => {
+ if (cur === null || cur === undefined) {
+ return prev;
+ }
+ const groupValue = cur[xAxis] as string;
+ if (!prev[groupValue]) {
+ // init as 0
+ const initValue: any = {};
+ seriesColumnNames.forEach((name) => {
+ initValue[name] = 0;
+ });
+ prev[groupValue] = initValue;
+ transformedData.push(prev[groupValue]);
+ }
+ // remain the x-axis data
+ prev[groupValue][xAxis] = groupValue;
+ seriesColumnNames.forEach((key) => {
+ if (key === xAxis) {
+ return;
+ } else if (isNumeric(cur[key])) {
+ const bigNum = Big(cur[key]);
+ prev[groupValue][key] = bigNum.add(prev[groupValue][key]).toNumber();
+ } else {
+ prev[groupValue][key] += 1;
+ }
+ });
+ return prev;
+ }, {} as any);
+ return transformedData;
+}
+
+export const echartsConfigOmitChildren = [
+ "hidden",
+ "selectedPoints",
+ "onUIEvent",
+ "mapInstance"
+] as const;
+type EchartsConfigProps = Omit;
+
+export function getSeriesConfig(props: EchartsConfigProps) {
+ let visibleSeries = props.series.filter((s) => !s.getView().hide).map(s => s.toJsonValue());
+ let newVisibleSeries;
+ if(props.chartConfig.subtype === "calendarPie") {
+ const dataInRange = props.data.filter(item => item[props.xAxisKey].substr(0, 7) === props.chartConfig.range);
+ newVisibleSeries = dataInRange.map(data => {
+ return {
+ data: visibleSeries.map(s => ({name: s.seriesName, value: data[s.columnName]})),
+ date: data[props.xAxisKey],
+ }
+ });
+ visibleSeries = newVisibleSeries;
+ }
+ const seriesLength = visibleSeries.length;
+ return visibleSeries.map((s, index) => {
+ // pie
+ const radiusAndCenter = getPieRadiusAndCenter(seriesLength, index, props.chartConfig);
+ let config = {
+ ...props.chartConfig,
+ radius: radiusAndCenter.radius,
+ center: radiusAndCenter.center,
+ selectedMode: "single",
+ };
+ if(props.chartConfig.subtype !== "calendarPie") {
+ config = {
+ ...config,
+ startAngle: s.startAngle,
+ endAngle: s.endAngle,
+ padAngle: s.padAngle,
+ name: s.seriesName,
+ label: {
+ show: s.showLabel,
+ position: s.labelPosition,
+ alignTo: s.labelAlignTo,
+ bleedMargin: s.labelBleedMargin,
+ },
+ labelLine: {
+ length: s.labelLineLength,
+ length2: s.labelLineLength2,
+ },
+ encode: {
+ itemName: props.xAxisKey,
+ value: s.columnName,
+ },
+ itemStyle: {
+ borderRadius: s.borderRadius,
+ color: s.itemColor,
+ shadowColor: s.itemShadowColor,
+ shadowBlur: s.itemShadowBlur,
+ },
+ }
+ if(s.labelAlignTo === 'edge') {
+ config.label.edgeDistance = s.labelEdgeDistance;
+ }
+ if(s.roseType !== "none") {
+ config.roseType = s.roseType;
+ }
+ if(s.itemBg) {
+ config.itemStyle = {
+ color: {
+ image: s.itemBg,
+ repeat: 'repeat',
+ }
+ }
+ }
+ if(props.chartConfig.subtype !== 'doughnutPie') config.radius = s.radius;
+ if(s.left!="" && s.top!="") {
+ config.center = [s.left, s.top];
+ }
+ if(props.chartConfig.subtype === 'geoPie') config.coordinateSystem = 'geo';
+ } else {
+ config.data = s.data;
+ config.center = s.date;
+ config.radius = props.chartConfig.cellSize[0]*0.4;
+ }
+ return config;
+ });
+}
+
+// https://echarts.apache.org/en/option.html
+export function getEchartsConfig(
+ props: EchartsConfigProps,
+ chartSize?: ChartSize,
+ theme?: any,
+): EChartsOptionWithMap {
+ const gridPos = {
+ left: `${props?.left}%`,
+ right: `${props?.right}%`,
+ bottom: `${props?.bottom}%`,
+ top: `${props?.top}%`,
+ };
+
+ let config: any = {
+ title: {
+ text: props.title,
+ top: props.echartsTitleVerticalConfig.top,
+ left:props.echartsTitleConfig.top,
+ textStyle: {
+ ...styleWrapper(props?.titleStyle, theme?.titleStyle)
+ }
+ },
+ backgroundColor: parseBackground( props?.chartStyle?.background || theme?.chartStyle?.backgroundColor || "#FFFFFF"),
+ legend: {
+ ...props.legendConfig,
+ textStyle: {
+ ...styleWrapper(props?.legendStyle, theme?.legendStyle, 15)
+ }
+ },
+ tooltip: props.tooltip && {
+ trigger: "axis",
+ axisPointer: {
+ type: "line",
+ lineStyle: {
+ color: "rgba(0,0,0,0.2)",
+ width: 2,
+ type: "solid"
+ }
+ }
+ },
+ grid: {
+ ...gridPos,
+ containLabel: true,
+ },
+ };
+ if(props.chartConfig.subtype === "geoPie") {
+ config.geo = {
+ map: 'jsonmap',
+ roam: true,
+ itemStyle: {
+ areaColor: '#e7e8ea'
+ }
+ };
+ }
+
+ //calendar pie
+ if(props.chartConfig.subtype === "calendarPie") {
+ config.calendar = {
+ top: 'middle',
+ left: 'center',
+ orient: 'vertical',
+ cellSize: props.chartConfig.cellSize,
+ yearLabel: {
+ show: false,
+ fontSize: 30
+ },
+ dayLabel: {
+ margin: 20,
+ firstDay: 1,
+ nameMap: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
+ },
+ monthLabel: {
+ show: false
+ },
+ range: [props.chartConfig.range]
+ }
+ }
+ //
+
+ if (props.data.length <= 0) {
+ // no data
+ return {
+ ...config,
+ ...noDataPieChartConfig,
+ };
+ }
+ const yAxisConfig = props.yConfig();
+ const seriesColumnNames = props.series
+ .filter((s) => !s.getView().hide)
+ .map((s) => s.getView().columnName);
+ // y-axis is category and time, data doesn't need to aggregate
+ let transformedData =
+ yAxisConfig.type === "category" || yAxisConfig.type === "time" ? props.data : transformData(props.data, props.xAxisKey, seriesColumnNames);
+
+ config = {
+ ...config,
+ dataset: [
+ {
+ source: transformedData,
+ sourceHeader: false,
+ },
+ ],
+ series: getSeriesConfig(props).map(series => ({
+ ...series,
+ encode: {
+ ...series.encode,
+ y: series.name,
+ },
+ itemStyle: {
+ ...series.itemStyle,
+ ...chartStyleWrapper(props?.chartStyle, theme?.chartStyle)
+ },
+ lineStyle: {
+ ...chartStyleWrapper(props?.chartStyle, theme?.chartStyle)
+ },
+ })),
+ };
+ if(props.chartConfig.subtype === "calendarPie") {
+ config.series = [
+ {
+ id: 'label',
+ type: 'scatter',
+ coordinateSystem: 'calendar',
+ symbolSize: 0,
+ label: {
+ show: true,
+ formatter: function (params) {
+ return params.value[1];
+ },
+ offset: [-props.chartConfig.cellSize[0] / 2 + 10, -props.chartConfig.cellSize[1] / 2 + 10],
+ fontSize: 14
+ },
+ data: Array.from({ length: 31 }, (_, index) => index + 1).map(d => ([props.chartConfig.range + "-" + (d<10?`0${d}`:d), d]))
+ },
+ ...config.series,
+ ]
+ }
+
+ console.log("Echarts transformedData and config", transformedData, config);
+ return config;
+}
+
+export function getSelectedPoints(param: any, option: any) {
+ const series = option.series;
+ const dataSource = _.isArray(option.dataset) && option.dataset[0]?.source;
+ if (series && dataSource) {
+ return param.selected.flatMap((selectInfo: any) => {
+ const seriesInfo = series[selectInfo.seriesIndex];
+ if (!seriesInfo || !seriesInfo.encode) {
+ return [];
+ }
+ return selectInfo.dataIndex.map((index: any) => {
+ const commonResult = {
+ seriesName: seriesInfo.name,
+ };
+ if (seriesInfo.encode.itemName && seriesInfo.encode.value) {
+ return {
+ ...commonResult,
+ itemName: dataSource[index][seriesInfo.encode.itemName],
+ value: dataSource[index][seriesInfo.encode.value],
+ };
+ } else {
+ return {
+ ...commonResult,
+ x: dataSource[index][seriesInfo.encode.x],
+ y: dataSource[index][seriesInfo.encode.y],
+ };
+ }
+ });
+ });
+ }
+ return [];
+}
+
+export function loadGoogleMapsScript(apiKey: string) {
+ const mapsUrl = `${googleMapsApiUrl}?key=${apiKey}`;
+ const scripts = document.getElementsByTagName('script');
+ // is script already loaded
+ let scriptIndex = _.findIndex(scripts, (script) => script.src.endsWith(mapsUrl));
+ if(scriptIndex > -1) {
+ return scripts[scriptIndex];
+ }
+ // is script loaded with diff api_key, remove the script and load again
+ scriptIndex = _.findIndex(scripts, (script) => script.src.startsWith(googleMapsApiUrl));
+ if(scriptIndex > -1) {
+ scripts[scriptIndex].remove();
+ }
+
+ const script = document.createElement("script");
+ script.type = "text/javascript";
+ script.src = mapsUrl;
+ script.async = true;
+ script.defer = true;
+ window.document.body.appendChild(script);
+
+ return script;
+}
diff --git a/client/packages/lowcoder-comps/src/comps/pieChartComp/seriesComp.tsx b/client/packages/lowcoder-comps/src/comps/pieChartComp/seriesComp.tsx
new file mode 100644
index 000000000..bf71aa6b1
--- /dev/null
+++ b/client/packages/lowcoder-comps/src/comps/pieChartComp/seriesComp.tsx
@@ -0,0 +1,244 @@
+import {
+ BoolControl,
+ StringControl,
+ ColorControl,
+ list,
+ dropdownControl,
+ withDefault,
+ NumberControl,
+ isNumeric,
+ genRandomKey,
+ Dropdown,
+ MultiCompBuilder,
+ valueComp,
+} from "lowcoder-sdk";
+import { i18nObjs, trans } from "i18n/comps";
+
+import { ConstructorToComp, ConstructorToDataType, ConstructorToView } from "lowcoder-core";
+import { CompAction, CustomAction, customAction, isMyCustomAction } from "lowcoder-core";
+import { x } from "@fullcalendar/resource/internal-common";
+
+export type SeriesCompType = ConstructorToComp;
+export type RawSeriesCompType = ConstructorToView;
+type SeriesDataType = ConstructorToDataType;
+
+type ActionDataType = {
+ type: "chartDataChanged";
+ chartData: Array;
+};
+
+export function newSeries(name: string, columnName: string): SeriesDataType {
+ return {
+ seriesName: name,
+ columnName: columnName,
+ dataIndex: genRandomKey(),
+ };
+}
+
+export const RoseTypeOptions = [
+ {
+ label: trans("pieChart.radius"),
+ value: "radius",
+ },
+ {
+ label: trans("pieChart.area"),
+ value: "area",
+ },
+ {
+ label: trans("pieChart.none"),
+ value: "none",
+ },
+] as const;
+
+export const LabelAlignToOptions = [
+ {
+ label: trans("pieChart.none"),
+ value: "none",
+ },
+ {
+ label: trans("pieChart.labelLine"),
+ value: "labelLine",
+ },
+ {
+ label: trans("pieChart.edge"),
+ value: "edge",
+ },
+] as const;
+
+export const LabelPositionOptions = [
+ {
+ label: trans("pieChart.outer"),
+ value: "outer",
+ },
+ {
+ label: trans("pieChart.inner"),
+ value: "inner",
+ },
+ {
+ label: trans("pieChart.center"),
+ value: "center",
+ },
+] as const;
+
+const seriesChildrenMap = {
+ columnName: StringControl,
+ seriesName: StringControl,
+ showLabel: withDefault(BoolControl, true),
+ radius: withDefault(StringControl, 30),
+ left: withDefault(StringControl, ""),
+ top: withDefault(StringControl, ""),
+ startAngle: withDefault(NumberControl, 0),
+ endAngle: withDefault(NumberControl, 360),
+ roseType: dropdownControl(RoseTypeOptions, "none"),
+ labelAlignTo: dropdownControl(LabelAlignToOptions, "none"),
+ labelPosition: dropdownControl(LabelPositionOptions, "outer"),
+ labelBleedMargin: withDefault(NumberControl, 5),
+ labelEdgeDistance: withDefault(StringControl, '25%'),
+ labelLineLength: withDefault(NumberControl, 10),
+ labelLineLength2: withDefault(NumberControl, 10),
+ padAngle: withDefault(NumberControl, 0),
+ borderRadius: withDefault(NumberControl, 0),
+ itemColor: ColorControl,
+ itemBg: StringControl,
+ itemShadowBlur: NumberControl,
+ itemShadowColor: ColorControl,
+ hide: BoolControl,
+ // unique key, for sort
+ dataIndex: valueComp(""),
+};
+
+const SeriesTmpComp = new MultiCompBuilder(seriesChildrenMap, (props) => {
+ return props;
+})
+ .setPropertyViewFn(() => {
+ return <>>;
+ })
+ .build();
+
+class SeriesComp extends SeriesTmpComp {
+ getPropertyViewWithData(columnOptions: OptionsType): React.ReactNode {
+ return (
+ <>
+ {this.children.seriesName.propertyView({
+ label: trans("chart.seriesName"),
+ })}
+ {
+ this.children.columnName.dispatchChangeValueAction(value);
+ }}
+ />
+ {this.children.radius.propertyView({
+ label: trans("pieChart.radius"),
+ })}
+ {this.children.left.propertyView({
+ label: trans("pieChart.left"),
+ })}
+ {this.children.top.propertyView({
+ label: trans("pieChart.top"),
+ })}
+ {this.children.startAngle.propertyView({
+ label: trans("pieChart.startAngle"),
+ })}
+ {this.children.endAngle.propertyView({
+ label: trans("pieChart.endAngle"),
+ })}
+ {this.children.roseType.propertyView({
+ label: trans("pieChart.roseType"),
+ })}
+ {this.children.showLabel.propertyView({
+ label: trans("pieChart.showLabel"),
+ })}
+ {this.children.showLabel.getView() && this.children.labelPosition.propertyView({
+ label: trans("pieChart.labelPosition"),
+ })}
+ {this.children.showLabel.getView() && this.children.labelAlignTo.propertyView({
+ label: trans("pieChart.labelAlignTo"),
+ })}
+ {this.children.showLabel.getView() && this.children.labelBleedMargin.propertyView({
+ label: trans("pieChart.labelBleedMargin"),
+ })}
+ {this.children.showLabel.getView() && this.children.labelAlignTo.getView() === "edge" && this.children.labelEdgeDistance.propertyView({
+ label: trans("pieChart.labelEdgeDistance"),
+ })}
+ {this.children.showLabel.getView() && this.children.labelLineLength.propertyView({
+ label: trans("pieChart.labelLineLength"),
+ })}
+ {this.children.showLabel.getView() && this.children.labelAlignTo.getView() === "labelLine" && this.children.labelLineLength2.propertyView({
+ label: trans("pieChart.labelLineLength2"),
+ })}
+ {this.children.padAngle.propertyView({
+ label: trans("pieChart.padAngle"),
+ })}
+ {this.children.borderRadius.propertyView({
+ label: trans("pieChart.borderRadius"),
+ })}
+ {this.children.itemColor.propertyView({
+ label: trans("pieChart.itemColor"),
+ })}
+ {this.children.itemShadowBlur.propertyView({
+ label: trans("pieChart.itemShadowBlur"),
+ })}
+ {this.children.itemShadowColor.propertyView({
+ label: trans("pieChart.itemShadowColor"),
+ })}
+ {this.children.itemBg.propertyView({
+ label: trans("pieChart.itemBg"),
+ placeholder: i18nObjs.defaultPieBg,
+ })}
+ >
+ );
+ }
+}
+
+const SeriesListTmpComp = list(SeriesComp);
+
+export class SeriesListComp extends SeriesListTmpComp {
+ override reduce(action: CompAction): this {
+ if (isMyCustomAction(action, "chartDataChanged")) {
+ // auto generate series
+ const actions = this.genExampleSeriesActions(action.value.chartData);
+ return this.reduce(this.multiAction(actions));
+ }
+ return super.reduce(action);
+ }
+
+ private genExampleSeriesActions(chartData: Array) {
+ const actions: CustomAction[] = [];
+ if (!chartData || chartData.length <= 0 || !chartData[0]) {
+ return actions;
+ }
+ let delCnt = 0;
+ const existColumns = this.getView().map((s) => s.getView().columnName);
+ // delete series not in data
+ existColumns.forEach((columnName) => {
+ if (chartData[0]?.[columnName] === undefined) {
+ actions.push(this.deleteAction(0));
+ delCnt++;
+ }
+ });
+ if (existColumns.length > delCnt) {
+ // don't generate example if exists
+ return actions;
+ }
+ // generate example series
+ const exampleKeys = Object.keys(chartData[0])
+ .filter((key) => {
+ return !existColumns.includes(key) && isNumeric(chartData[0][key]);
+ })
+ .slice(0, 3);
+ exampleKeys.forEach((key) => actions.push(this.pushAction(newSeries(key, key))));
+ return actions;
+ }
+
+ dispatchDataChanged(chartData: Array): void {
+ this.dispatch(
+ customAction({
+ type: "chartDataChanged",
+ chartData: chartData,
+ })
+ );
+ }
+}
diff --git a/client/packages/lowcoder-comps/src/comps/scatterChartComp/scatterChartComp.tsx b/client/packages/lowcoder-comps/src/comps/scatterChartComp/scatterChartComp.tsx
new file mode 100644
index 000000000..003fadf1d
--- /dev/null
+++ b/client/packages/lowcoder-comps/src/comps/scatterChartComp/scatterChartComp.tsx
@@ -0,0 +1,295 @@
+import {
+ changeChildAction,
+ changeValueAction,
+ CompAction,
+ CompActionTypes,
+ wrapChildAction,
+} from "lowcoder-core";
+import { AxisFormatterComp, EchartsAxisType } from "../basicChartComp/chartConfigs/cartesianAxisConfig";
+import { scatterChartChildrenMap, ChartSize, getDataKeys } from "./scatterChartConstants";
+import { scatterChartPropertyView } from "./scatterChartPropertyView";
+import _ from "lodash";
+import { useContext, useEffect, useMemo, useRef, useState } from "react";
+import ReactResizeDetector from "react-resize-detector";
+import ReactECharts from "../basicChartComp/reactEcharts";
+import * as echarts from "echarts";
+import {
+ childrenToProps,
+ depsConfig,
+ genRandomKey,
+ NameConfig,
+ UICompBuilder,
+ withDefault,
+ withExposingConfigs,
+ withViewFn,
+ ThemeContext,
+ chartColorPalette,
+ getPromiseAfterDispatch,
+ dropdownControl,
+} from "lowcoder-sdk";
+import { getEchartsLocale, i18nObjs, trans } from "i18n/comps";
+import {
+ echartsConfigOmitChildren,
+ getEchartsConfig,
+ getSelectedPoints,
+} from "./scatterChartUtils";
+import 'echarts-extension-gmap';
+import log from "loglevel";
+
+let clickEventCallback = () => {};
+
+const chartModeOptions = [
+ {
+ label: "UI",
+ value: "ui",
+ }
+] as const;
+
+let ScatterChartTmpComp = (function () {
+ return new UICompBuilder({mode:dropdownControl(chartModeOptions,'ui'),...scatterChartChildrenMap}, () => null)
+ .setPropertyViewFn(scatterChartPropertyView)
+ .build();
+})();
+
+ScatterChartTmpComp = withViewFn(ScatterChartTmpComp, (comp) => {
+ const mode = comp.children.mode.getView();
+ const onUIEvent = comp.children.onUIEvent.getView();
+ const onEvent = comp.children.onEvent.getView();
+ const echartsCompRef = useRef();
+ const [chartSize, setChartSize] = useState();
+ const firstResize = useRef(true);
+ const theme = useContext(ThemeContext);
+ const defaultChartTheme = {
+ color: chartColorPalette,
+ backgroundColor: "#fff",
+ };
+
+ let themeConfig = defaultChartTheme;
+ try {
+ themeConfig = theme?.theme.chart ? JSON.parse(theme?.theme.chart) : defaultChartTheme;
+ } catch (error) {
+ log.error('theme chart error: ', error);
+ }
+
+ const triggerClickEvent = async (dispatch: any, action: CompAction) => {
+ await getPromiseAfterDispatch(
+ dispatch,
+ action,
+ { autoHandleAfterReduce: true }
+ );
+ onEvent('click');
+ }
+
+ useEffect(() => {
+ const echartsCompInstance = echartsCompRef?.current?.getEchartsInstance();
+ if (!echartsCompInstance) {
+ return _.noop;
+ }
+ echartsCompInstance?.on("click", (param: any) => {
+ document.dispatchEvent(new CustomEvent("clickEvent", {
+ bubbles: true,
+ detail: {
+ action: 'click',
+ data: param.data,
+ }
+ }));
+ triggerClickEvent(
+ comp.dispatch,
+ changeChildAction("lastInteractionData", param.data, false)
+ );
+ });
+ return () => {
+ echartsCompInstance?.off("click");
+ document.removeEventListener('clickEvent', clickEventCallback)
+ };
+ }, []);
+
+ useEffect(() => {
+ // bind events
+ const echartsCompInstance = echartsCompRef?.current?.getEchartsInstance();
+ if (!echartsCompInstance) {
+ return _.noop;
+ }
+ echartsCompInstance?.on("selectchanged", (param: any) => {
+ const option: any = echartsCompInstance?.getOption();
+ document.dispatchEvent(new CustomEvent("clickEvent", {
+ bubbles: true,
+ detail: {
+ action: param.fromAction,
+ data: getSelectedPoints(param, option)
+ }
+ }));
+
+ if (param.fromAction === "select") {
+ comp.dispatch(changeChildAction("selectedPoints", getSelectedPoints(param, option), false));
+ onUIEvent("select");
+ } else if (param.fromAction === "unselect") {
+ comp.dispatch(changeChildAction("selectedPoints", getSelectedPoints(param, option), false));
+ onUIEvent("unselect");
+ }
+
+ triggerClickEvent(
+ comp.dispatch,
+ changeChildAction("lastInteractionData", getSelectedPoints(param, option), false)
+ );
+ });
+ // unbind
+ return () => {
+ echartsCompInstance?.off("selectchanged");
+ document.removeEventListener('clickEvent', clickEventCallback)
+ };
+ }, [onUIEvent]);
+
+ const echartsConfigChildren = _.omit(comp.children, echartsConfigOmitChildren);
+ const childrenProps = childrenToProps(echartsConfigChildren);
+
+ const option = useMemo(() => {
+ return getEchartsConfig(
+ childrenProps as ToViewReturn,
+ chartSize,
+ themeConfig
+ );
+ }, [theme, childrenProps, chartSize, ...Object.values(echartsConfigChildren)]);
+
+ return (
+ {
+ if (w && h) {
+ setChartSize({ w: w, h: h });
+ }
+ if (!firstResize.current) {
+ // ignore the first resize, which will impact the loading animation
+ echartsCompRef.current?.getEchartsInstance().resize();
+ } else {
+ firstResize.current = false;
+ }
+ }}
+ >
+ (echartsCompRef.current = e)}
+ style={{ height: "100%" }}
+ notMerge
+ lazyUpdate
+ opts={{ locale: getEchartsLocale() }}
+ option={option}
+ mode={mode}
+ />
+
+ );
+});
+
+function getYAxisFormatContextValue(
+ data: Array,
+ yAxisType: EchartsAxisType,
+ yAxisName?: string
+) {
+ const dataSample = yAxisName && data.length > 0 && data[0][yAxisName];
+ let contextValue = dataSample;
+ if (yAxisType === "time") {
+ // to timestamp
+ const time =
+ typeof dataSample === "number" || typeof dataSample === "string"
+ ? new Date(dataSample).getTime()
+ : null;
+ if (time) contextValue = time;
+ }
+ return contextValue;
+}
+
+ScatterChartTmpComp = class extends ScatterChartTmpComp {
+ private lastYAxisFormatContextVal?: JSONValue;
+ private lastColorContext?: JSONObject;
+
+ updateContext(comp: this) {
+ // the context value of axis format
+ let resultComp = comp;
+ const data = comp.children.data.getView();
+ const sampleSeries = comp.children.series.getView().find((s) => !s.getView().hide);
+ const yAxisContextValue = getYAxisFormatContextValue(
+ data,
+ comp.children.yConfig.children.yAxisType.getView(),
+ sampleSeries?.children.columnName.getView()
+ );
+ if (yAxisContextValue !== comp.lastYAxisFormatContextVal) {
+ comp.lastYAxisFormatContextVal = yAxisContextValue;
+ resultComp = comp.setChild(
+ "yConfig",
+ comp.children.yConfig.reduce(
+ wrapChildAction(
+ "formatter",
+ AxisFormatterComp.changeContextDataAction({ value: yAxisContextValue })
+ )
+ )
+ );
+ }
+ return resultComp;
+ }
+
+ override reduce(action: CompAction): this {
+ const comp = super.reduce(action);
+ if (action.type === CompActionTypes.UPDATE_NODES_V2) {
+ const newData = comp.children.data.getView();
+ // data changes
+ if (comp.children.data !== this.children.data) {
+ setTimeout(() => {
+ // update x-axis value
+ const keys = getDataKeys(newData);
+ if (keys.length > 0 && !keys.includes(comp.children.xAxisKey.getView())) {
+ comp.children.xAxisKey.dispatch(changeValueAction(keys[0] || ""));
+ }
+ // pass to child series comp
+ comp.children.series.dispatchDataChanged(newData);
+ }, 0);
+ }
+ return this.updateContext(comp);
+ }
+ return comp;
+ }
+
+ override autoHeight(): boolean {
+ return false;
+ }
+};
+
+let ScatterChartComp = withExposingConfigs(ScatterChartTmpComp, [
+ depsConfig({
+ name: "selectedPoints",
+ desc: trans("chart.selectedPointsDesc"),
+ depKeys: ["selectedPoints"],
+ func: (input) => {
+ return input.selectedPoints;
+ },
+ }),
+ depsConfig({
+ name: "lastInteractionData",
+ desc: trans("chart.lastInteractionDataDesc"),
+ depKeys: ["lastInteractionData"],
+ func: (input) => {
+ return input.lastInteractionData;
+ },
+ }),
+ depsConfig({
+ name: "data",
+ desc: trans("chart.dataDesc"),
+ depKeys: ["data", "mode"],
+ func: (input) =>[] ,
+ }),
+ new NameConfig("title", trans("chart.titleDesc")),
+]);
+
+
+export const ScatterChartCompWithDefault = withDefault(ScatterChartComp, {
+ xAxisKey: "date",
+ series: [
+ {
+ dataIndex: genRandomKey(),
+ seriesName: trans("chart.spending"),
+ columnName: "spending",
+ },
+ {
+ dataIndex: genRandomKey(),
+ seriesName: trans("chart.budget"),
+ columnName: "budget",
+ },
+ ],
+});
diff --git a/client/packages/lowcoder-comps/src/comps/scatterChartComp/scatterChartConstants.tsx b/client/packages/lowcoder-comps/src/comps/scatterChartComp/scatterChartConstants.tsx
new file mode 100644
index 000000000..02c8f803f
--- /dev/null
+++ b/client/packages/lowcoder-comps/src/comps/scatterChartComp/scatterChartConstants.tsx
@@ -0,0 +1,288 @@
+import {
+ jsonControl,
+ stateComp,
+ toJSONObjectArray,
+ toObject,
+ BoolControl,
+ ColorControl,
+ withDefault,
+ StringControl,
+ NumberControl,
+ dropdownControl,
+ list,
+ eventHandlerControl,
+ valueComp,
+ withType,
+ uiChildren,
+ clickEvent,
+ toArray,
+ styleControl,
+ EchartDefaultTextStyle,
+ EchartDefaultChartStyle,
+ MultiCompBuilder,
+} from "lowcoder-sdk";
+import { RecordConstructorToComp, RecordConstructorToView } from "lowcoder-core";
+import { XAxisConfig, YAxisConfig } from "../basicChartComp/chartConfigs/cartesianAxisConfig";
+import { LegendConfig } from "../basicChartComp/chartConfigs/legendConfig";
+import { EchartsLegendConfig } from "../basicChartComp/chartConfigs/echartsLegendConfig";
+import { EchartsLabelConfig } from "../basicChartComp/chartConfigs/echartsLabelConfig";
+import { ScatterChartConfig } from "../basicChartComp/chartConfigs/scatterChartConfig";
+import { SeriesListComp } from "./seriesComp";
+import { EChartsOption } from "echarts";
+import { i18nObjs, trans } from "i18n/comps";
+import { GaugeChartConfig } from "../basicChartComp/chartConfigs/gaugeChartConfig";
+import { FunnelChartConfig } from "../basicChartComp/chartConfigs/funnelChartConfig";
+import {EchartsTitleVerticalConfig} from "../chartComp/chartConfigs/echartsTitleVerticalConfig";
+import {EchartsTitleConfig} from "../basicChartComp/chartConfigs/echartsTitleConfig";
+
+export const ChartTypeOptions = [
+ {
+ label: trans("chart.bar"),
+ value: "bar",
+ },
+ {
+ label: trans("chart.line"),
+ value: "line",
+ },
+ {
+ label: trans("chart.scatter"),
+ value: "scatter",
+ },
+ {
+ label: trans("chart.scatter"),
+ value: "scatter",
+ },
+] as const;
+
+export const UIEventOptions = [
+ {
+ label: trans("chart.select"),
+ value: "select",
+ description: trans("chart.selectDesc"),
+ },
+ {
+ label: trans("chart.unSelect"),
+ value: "unselect",
+ description: trans("chart.unselectDesc"),
+ },
+] as const;
+
+export const XAxisDirectionOptions = [
+ {
+ label: trans("chart.horizontal"),
+ value: "horizontal",
+ },
+ {
+ label: trans("chart.vertical"),
+ value: "vertical",
+ },
+] as const;
+
+export type XAxisDirectionType = ValueFromOption;
+
+export const noDataAxisConfig = {
+ animation: false,
+ xAxis: {
+ type: "category",
+ name: trans("chart.noData"),
+ nameLocation: "middle",
+ data: [],
+ axisLine: {
+ lineStyle: {
+ color: "#8B8FA3",
+ },
+ },
+ },
+ yAxis: {
+ type: "value",
+ axisLabel: {
+ color: "#8B8FA3",
+ },
+ splitLine: {
+ lineStyle: {
+ color: "#F0F0F0",
+ },
+ },
+ },
+ tooltip: {
+ show: false,
+ },
+ series: [
+ {
+ data: [700],
+ type: "line",
+ itemStyle: {
+ opacity: 0,
+ },
+ },
+ ],
+} as EChartsOption;
+
+export const noDataScatterChartConfig = {
+ animation: false,
+ tooltip: {
+ show: false,
+ },
+ legend: {
+ formatter: trans("chart.unknown"),
+ top: "bottom",
+ selectedMode: false,
+ },
+ color: ["#B8BBCC", "#CED0D9", "#DCDEE6", "#E6E6EB"],
+ series: [
+ {
+ type: "scatter",
+ radius: "35%",
+ center: ["25%", "50%"],
+ silent: true,
+ label: {
+ show: false,
+ },
+ data: [
+ {
+ name: "1",
+ value: 70,
+ },
+ {
+ name: "2",
+ value: 68,
+ },
+ {
+ name: "3",
+ value: 48,
+ },
+ {
+ name: "4",
+ value: 40,
+ },
+ ],
+ },
+ {
+ type: "scatter",
+ radius: "35%",
+ center: ["75%", "50%"],
+ silent: true,
+ label: {
+ show: false,
+ },
+ data: [
+ {
+ name: "1",
+ value: 70,
+ },
+ {
+ name: "2",
+ value: 68,
+ },
+ {
+ name: "3",
+ value: 48,
+ },
+ {
+ name: "4",
+ value: 40,
+ },
+ ],
+ },
+ ],
+} as EChartsOption;
+
+export type ChartSize = { w: number; h: number };
+
+export const getDataKeys = (data: Array) => {
+ if (!data) {
+ return [];
+ }
+ const dataKeys: Array = [];
+ data.slice(0, 50).forEach((d) => {
+ Object.keys(d).forEach((key) => {
+ if (!dataKeys.includes(key)) {
+ dataKeys.push(key);
+ }
+ });
+ });
+ return dataKeys;
+};
+
+const ChartOptionMap = {
+ scatter: ScatterChartConfig,
+};
+
+const EchartsOptionMap = {
+ funnel: FunnelChartConfig,
+ gauge: GaugeChartConfig,
+};
+
+const ChartOptionComp = withType(ChartOptionMap, "scatter");
+const EchartsOptionComp = withType(EchartsOptionMap, "funnel");
+export type CharOptionCompType = keyof typeof ChartOptionMap;
+
+export const chartUiModeChildren = {
+ title: withDefault(StringControl, trans("echarts.defaultTitle")),
+ data: jsonControl(toJSONObjectArray, i18nObjs.defaultDataSource),
+ xAxisKey: valueComp(""), // x-axis, key from data
+ xAxisDirection: dropdownControl(XAxisDirectionOptions, "horizontal"),
+ xAxisData: jsonControl(toArray, []),
+ series: SeriesListComp,
+ xConfig: XAxisConfig,
+ yConfig: YAxisConfig,
+ legendConfig: LegendConfig,
+ chartConfig: ChartOptionComp,
+ onUIEvent: eventHandlerControl(UIEventOptions),
+};
+
+let chartJsonModeChildren: any = {
+ echartsOption: jsonControl(toObject, i18nObjs.defaultEchartsJsonOption),
+ echartsTitle: withDefault(StringControl, trans("echarts.defaultTitle")),
+ echartsLegendConfig: EchartsLegendConfig,
+ echartsLabelConfig: EchartsLabelConfig,
+ echartsConfig: EchartsOptionComp,
+ echartsTitleVerticalConfig: EchartsTitleVerticalConfig,
+ echartsTitleConfig:EchartsTitleConfig,
+
+ left:withDefault(NumberControl,trans('chart.defaultLeft')),
+ right:withDefault(NumberControl,trans('chart.defaultRight')),
+ top:withDefault(NumberControl,trans('chart.defaultTop')),
+ bottom:withDefault(NumberControl,trans('chart.defaultBottom')),
+
+ tooltip: withDefault(BoolControl, true),
+ legendVisibility: withDefault(BoolControl, true),
+}
+
+if (EchartDefaultChartStyle && EchartDefaultTextStyle) {
+ chartJsonModeChildren = {
+ ...chartJsonModeChildren,
+ chartStyle: styleControl(EchartDefaultChartStyle, 'chartStyle'),
+ titleStyle: styleControl(EchartDefaultTextStyle, 'titleStyle'),
+ xAxisStyle: styleControl(EchartDefaultTextStyle, 'xAxis'),
+ yAxisStyle: styleControl(EchartDefaultTextStyle, 'yAxisStyle'),
+ legendStyle: styleControl(EchartDefaultTextStyle, 'legendStyle'),
+ }
+}
+
+export type UIChartDataType = {
+ seriesName: string;
+ // coordinate chart
+ x?: any;
+ y?: any;
+ // scatter or funnel
+ itemName?: any;
+ value?: any;
+};
+
+export type NonUIChartDataType = {
+ name: string;
+ value: any;
+}
+
+export const scatterChartChildrenMap = {
+ selectedPoints: stateComp>([]),
+ lastInteractionData: stateComp | NonUIChartDataType>({}),
+ onEvent: eventHandlerControl([clickEvent] as const),
+ ...chartUiModeChildren,
+ ...chartJsonModeChildren,
+};
+
+const chartUiChildrenMap = uiChildren(scatterChartChildrenMap);
+export type ChartCompPropsType = RecordConstructorToView;
+export type ChartCompChildrenType = RecordConstructorToComp;
diff --git a/client/packages/lowcoder-comps/src/comps/scatterChartComp/scatterChartPropertyView.tsx b/client/packages/lowcoder-comps/src/comps/scatterChartComp/scatterChartPropertyView.tsx
new file mode 100644
index 000000000..77ac49eb0
--- /dev/null
+++ b/client/packages/lowcoder-comps/src/comps/scatterChartComp/scatterChartPropertyView.tsx
@@ -0,0 +1,140 @@
+import { changeChildAction, CompAction } from "lowcoder-core";
+import { ChartCompChildrenType, ChartTypeOptions,getDataKeys } from "./scatterChartConstants";
+import { newSeries } from "./seriesComp";
+import {
+ CustomModal,
+ Dropdown,
+ hiddenPropertyView,
+ Option,
+ RedButton,
+ Section,
+ sectionNames,
+ controlItem,
+} from "lowcoder-sdk";
+import { trans } from "i18n/comps";
+
+export function scatterChartPropertyView(
+ children: ChartCompChildrenType,
+ dispatch: (action: CompAction) => void
+) {
+ const series = children.series.getView();
+ const columnOptions = getDataKeys(children.data.getView()).map((key) => ({
+ label: key,
+ value: key,
+ }));
+
+ const uiModePropertyView = (
+ <>
+
+ {children.chartConfig.getPropertyView()}
+ {
+ dispatch(changeChildAction("xAxisKey", value));
+ }}
+ />
+ {children.chartConfig.getView().subtype === "waterfall" && children.xAxisData.propertyView({
+ label: "X-Label-Data"
+ })}
+ s.getView().seriesName}
+ popoverTitle={(s) => s.getView().columnName}
+ content={(s, index) => (
+ <>
+ {s.getPropertyViewWithData(columnOptions)}
+ {
+ {
+ CustomModal.confirm({
+ title: trans("chart.delete"),
+ content: trans("chart.confirmDelete") + `${s.getView().seriesName}?`,
+ onConfirm: () =>
+ children.series.dispatch(children.series.deleteAction(index)),
+ confirmBtnType: "delete",
+ okText: trans("chart.delete"),
+ });
+ }}
+ >
+ {trans("chart.delete")}
+
+ }
+ >
+ )}
+ onAdd={() => {
+ if (columnOptions.length <= 0) {
+ return;
+ }
+ children.series.dispatch(
+ children.series.pushAction(
+ newSeries(trans("chart.customSeries"), columnOptions[0].value)
+ )
+ );
+ }}
+ onMove={(fromIndex, toIndex) => {
+ const action = children.series.arrayMoveAction(fromIndex, toIndex);
+ children.series.dispatch(action);
+ }}
+ hide={(s) => s.getView().hide}
+ onHide={(s, hide) => s.children.hide.dispatchChangeValueAction(hide)}
+ dataIndex={(s) => s.getView().dataIndex}
+ />
+
+
+
+ {children.onUIEvent.propertyView({title: trans("chart.chartEventHandlers")})}
+
+
+ {children.onEvent.propertyView()}
+
+
+
+ {children.echartsTitleConfig.getPropertyView()}
+ {children.echartsTitleVerticalConfig.getPropertyView()}
+ {children.legendConfig.getPropertyView()}
+ {children.title.propertyView({ label: trans("chart.title") })}
+ {children.left.propertyView({ label: trans("chart.left"), tooltip: trans("echarts.leftTooltip") })}
+ {children.right.propertyView({ label: trans("chart.right"), tooltip: trans("echarts.rightTooltip") })}
+ {children.top.propertyView({ label: trans("chart.top"), tooltip: trans("echarts.topTooltip") })}
+ {children.bottom.propertyView({ label: trans("chart.bottom"), tooltip: trans("echarts.bottomTooltip") })}
+ {hiddenPropertyView(children)}
+ {children.tooltip.propertyView({label: trans("echarts.tooltip"), tooltip: trans("echarts.tooltipTooltip")})}
+
+
+ {children.chartStyle?.getPropertyView()}
+
+
+ {children.titleStyle?.getPropertyView()}
+
+
+ {children.xAxisStyle?.getPropertyView()}
+
+
+ {children.yAxisStyle?.getPropertyView()}
+
+
+ {children.legendStyle?.getPropertyView()}
+
+
+ {children.data.propertyView({
+ label: trans("chart.data"),
+ })}
+
+ >
+ );
+
+ const getChatConfigByMode = (mode: string) => {
+ switch(mode) {
+ case "ui":
+ return uiModePropertyView;
+ }
+ }
+ return (
+ <>
+ {getChatConfigByMode(children.mode.getView())}
+ >
+ );
+}
diff --git a/client/packages/lowcoder-comps/src/comps/scatterChartComp/scatterChartUtils.ts b/client/packages/lowcoder-comps/src/comps/scatterChartComp/scatterChartUtils.ts
new file mode 100644
index 000000000..67b2a4a53
--- /dev/null
+++ b/client/packages/lowcoder-comps/src/comps/scatterChartComp/scatterChartUtils.ts
@@ -0,0 +1,354 @@
+import {
+ CharOptionCompType,
+ ChartCompPropsType,
+ ChartSize,
+ noDataAxisConfig,
+ noDataScatterChartConfig,
+} from "comps/scatterChartComp/scatterChartConstants";
+import { EChartsOptionWithMap } from "../basicChartComp/reactEcharts/types";
+import _ from "lodash";
+import { chartColorPalette, isNumeric, JSONObject, loadScript } from "lowcoder-sdk";
+import { calcXYConfig } from "comps/basicChartComp/chartConfigs/cartesianAxisConfig";
+import Big from "big.js";
+import { googleMapsApiUrl } from "../basicChartComp/chartConfigs/chartUrls";
+import opacityToHex from "../../util/opacityToHex";
+import parseBackground from "../../util/gradientBackgroundColor";
+import {ba, s} from "@fullcalendar/core/internal-common";
+import {chartStyleWrapper, styleWrapper} from "../../util/styleWrapper";
+
+export function transformData(
+ originData: JSONObject[],
+ xAxis: string,
+ seriesColumnNames: string[]
+) {
+ // aggregate data by x-axis
+ const transformedData: JSONObject[] = [];
+ originData.reduce((prev, cur) => {
+ if (cur === null || cur === undefined) {
+ return prev;
+ }
+ const groupValue = cur[xAxis] as string;
+ if (!prev[groupValue]) {
+ // init as 0
+ const initValue: any = {};
+ seriesColumnNames.forEach((name) => {
+ initValue[name] = 0;
+ });
+ prev[groupValue] = initValue;
+ transformedData.push(prev[groupValue]);
+ }
+ // remain the x-axis data
+ prev[groupValue][xAxis] = groupValue;
+ seriesColumnNames.forEach((key) => {
+ if (key === xAxis) {
+ return;
+ } else if (isNumeric(cur[key])) {
+ const bigNum = Big(cur[key]);
+ prev[groupValue][key] = bigNum.add(prev[groupValue][key]).toNumber();
+ } else {
+ prev[groupValue][key] += 1;
+ }
+ });
+ return prev;
+ }, {} as any);
+ return transformedData;
+}
+
+export const echartsConfigOmitChildren = [
+ "hidden",
+ "selectedPoints",
+ "onUIEvent",
+ "mapInstance"
+] as const;
+type EchartsConfigProps = Omit;
+
+export function getSeriesConfig(props: EchartsConfigProps) {
+ let visibleSeries = props.series.filter((s) => !s.getView().hide).map(s => s.toJsonValue());
+ return visibleSeries.map((s, index) => {
+ let config = {
+ ...props.chartConfig,
+ name: s.seriesName,
+ encode: {
+ itemName: props.xAxisKey,
+ value: s.columnName,
+ },
+ itemStyle: {
+ borderRadius: s.borderRadius,
+ color: s.itemColor,
+ shadowColor: s.itemShadowColor,
+ shadowBlur: s.itemShadowBlur,
+ },
+ }
+ let fromArr = [0,0];
+ let toArr = [0,0];
+ try {
+ fromArr = JSON.parse(s.markLineFrom);
+ } catch {}
+ try {
+ toArr = JSON.parse(s.markLineTo);
+ } catch {}
+ if(s.showMarkLine) {
+ config.markLine = {
+ animation: false,
+ label: {
+ formatter: s.markLineDesc,
+ align: 'right'
+ },
+ lineStyle: {
+ type: 'solid'
+ },
+ tooltip: {
+ formatter: s.markLineDesc
+ },
+ data: [
+ [
+ {
+ coord: fromArr,
+ symbol: 'none'
+ },
+ {
+ coord: toArr,
+ symbol: 'none'
+ }
+ ]
+ ]
+ };
+ }
+ if(props.chartConfig.singleAxis) {
+ config.coordinateSystem = 'singleAxis';
+ config.singleAxisIndex = index;
+ config.data = [];
+ }
+ if(props.chartConfig.polar) {
+ config.coordinateSystem = 'polar';
+ }
+ if(props.chartConfig.heatmap) {
+ config.coordinateSystem = 'calendar';
+ config.type = 'heatmap';
+ }
+ if(s.effect) config.type = "effectScatter";
+ if(s.symbolSize) config.symbolSize = s.symbolSize;
+ if(s.dynamicSize) config.symbolSize = function(dataItem) {
+ return dataItem[s.dynamicIndex] / s.divider;
+ }
+ return config;
+ });
+}
+
+// https://echarts.apache.org/en/option.html
+export function getEchartsConfig(
+ props: EchartsConfigProps,
+ chartSize?: ChartSize,
+ theme?: any,
+): EChartsOptionWithMap {
+ const gridPos = {
+ left: `${props?.left}%`,
+ right: `${props?.right}%`,
+ bottom: `${props?.bottom}%`,
+ top: `${props?.top}%`,
+ };
+
+ let config: any = {
+ title: {
+ text: props.title,
+ top: props.echartsTitleVerticalConfig.top,
+ left:props.echartsTitleConfig.top,
+ textStyle: {
+ ...styleWrapper(props?.titleStyle, theme?.titleStyle)
+ }
+ },
+ backgroundColor: parseBackground( props?.chartStyle?.background || theme?.chartStyle?.backgroundColor || "#FFFFFF"),
+ legend: {
+ ...props.legendConfig,
+ textStyle: {
+ ...styleWrapper(props?.legendStyle, theme?.legendStyle, 15)
+ }
+ },
+ tooltip: props.tooltip && {
+ trigger: "axis",
+ axisPointer: {
+ type: "line",
+ lineStyle: {
+ color: "rgba(0,0,0,0.2)",
+ width: 2,
+ type: "solid"
+ }
+ }
+ },
+ grid: {
+ ...gridPos,
+ containLabel: true,
+ },
+ xAxis: {
+ type: "category",
+ boundaryGap: props.chartConfig.boundaryGap,
+ splitLine: {
+ show: !props.chartConfig.boundaryGap,
+ },
+ axisLine: {
+ show: props.chartConfig.boundaryGap,
+ },
+ axisLabel: {
+ ...styleWrapper(props?.xAxisStyle, theme?.xAxisStyle, 11)
+ }
+ },
+ yAxis: {
+ type: "category",
+ axisLabel: {
+ ...styleWrapper(props?.yAxisStyle, theme?.yAxisStyle, 11)
+ }
+ },
+ };
+
+ if (props.data.length <= 0) {
+ // no data
+ return {
+ ...config,
+ ...noDataScatterChartConfig,
+ };
+ }
+ const yAxisConfig = props.yConfig();
+ const seriesColumnNames = props.series
+ .filter((s) => !s.getView().hide)
+ .map((s) => s.getView().columnName);
+ // y-axis is category and time, data doesn't need to aggregate
+ let transformedData = props.data;
+ const seriesConfig = getSeriesConfig(props);
+ const singleAxis = seriesConfig.map((series, idx) => ({
+ left: 100,
+ type: 'category',
+ boundaryGap: false,
+ top: (idx * 100) / seriesConfig.length + (100/seriesConfig.length/2) + '%',
+ height: - 100 / seriesConfig.length / 4 + '%',
+ }));
+
+ config = {
+ ...config,
+ series: seriesConfig.map(series => ({
+ ...series,
+ itemStyle: {
+ ...series.itemStyle,
+ ...chartStyleWrapper(props?.chartStyle, theme?.chartStyle)
+ },
+ lineStyle: {
+ ...chartStyleWrapper(props?.chartStyle, theme?.chartStyle)
+ },
+ data: transformedData.map(d => [d[props.xAxisKey], d[series.encode.value], ...Object.values(d)]),
+ })),
+ };
+
+ if(props.chartConfig.singleAxis) {
+ config.singleAxis = singleAxis;
+ delete config.xAxis;
+ delete config.yAxis;
+
+ config.title = seriesConfig.map((series, idx) => ({
+ textBaseline: 'middle',
+ top: ((idx + 0.5) * 100) / seriesConfig.length + '%',
+ text: series.name,
+ }));
+ }
+
+ if(props.chartConfig.visualMapData.visualMap) {
+ config.visualMap = {
+ min: props.chartConfig.visualMapData.visualMapMin,
+ max: props.chartConfig.visualMapData.visualMapMax,
+ dimension: props.chartConfig.visualMapData.visualMapDimension,
+ orient: 'vertical',
+ right: 10,
+ top: 'center',
+ text: ['HIGH', 'LOW'],
+ calculable: true,
+ inRange: {
+ color: [props.chartConfig.visualMapData.visualMapColorMin, props.chartConfig.visualMapData.visualMapColorMax]
+ }
+ }
+ }
+ if(props.chartConfig.polar) {
+ config.angleAxis = config.xAxis;
+ config.radiusAxis = config.yAxis;
+ config.polar = {};
+ delete config.xAxis;
+ delete config.yAxis;
+ }
+
+ if(props.chartConfig.heatmap) {
+ config.calendar = {
+ orient: 'vertical',
+ yearLabel: {
+ margin: 40
+ },
+ monthLabel: {
+ nameMap: 'cn',
+ margin: 20
+ },
+ dayLabel: {
+ firstDay: 1,
+ nameMap: 'cn'
+ },
+ cellSize: 40,
+ range: props.chartConfig.heatmapMonth,
+ }
+ delete config.xAxis;
+ delete config.yAxis;
+ }
+
+ console.log("Echarts transformedData and config", transformedData, config);
+ return config;
+}
+
+export function getSelectedPoints(param: any, option: any) {
+ const series = option.series;
+ const dataSource = _.isArray(option.dataset) && option.dataset[0]?.source;
+ if (series && dataSource) {
+ return param.selected.flatMap((selectInfo: any) => {
+ const seriesInfo = series[selectInfo.seriesIndex];
+ if (!seriesInfo || !seriesInfo.encode) {
+ return [];
+ }
+ return selectInfo.dataIndex.map((index: any) => {
+ const commonResult = {
+ seriesName: seriesInfo.name,
+ };
+ if (seriesInfo.encode.itemName && seriesInfo.encode.value) {
+ return {
+ ...commonResult,
+ itemName: dataSource[index][seriesInfo.encode.itemName],
+ value: dataSource[index][seriesInfo.encode.value],
+ };
+ } else {
+ return {
+ ...commonResult,
+ x: dataSource[index][seriesInfo.encode.x],
+ y: dataSource[index][seriesInfo.encode.y],
+ };
+ }
+ });
+ });
+ }
+ return [];
+}
+
+export function loadGoogleMapsScript(apiKey: string) {
+ const mapsUrl = `${googleMapsApiUrl}?key=${apiKey}`;
+ const scripts = document.getElementsByTagName('script');
+ // is script already loaded
+ let scriptIndex = _.findIndex(scripts, (script) => script.src.endsWith(mapsUrl));
+ if(scriptIndex > -1) {
+ return scripts[scriptIndex];
+ }
+ // is script loaded with diff api_key, remove the script and load again
+ scriptIndex = _.findIndex(scripts, (script) => script.src.startsWith(googleMapsApiUrl));
+ if(scriptIndex > -1) {
+ scripts[scriptIndex].remove();
+ }
+
+ const script = document.createElement("script");
+ script.type = "text/javascript";
+ script.src = mapsUrl;
+ script.async = true;
+ script.defer = true;
+ window.document.body.appendChild(script);
+
+ return script;
+}
diff --git a/client/packages/lowcoder-comps/src/comps/scatterChartComp/seriesComp.tsx b/client/packages/lowcoder-comps/src/comps/scatterChartComp/seriesComp.tsx
new file mode 100644
index 000000000..0f423da20
--- /dev/null
+++ b/client/packages/lowcoder-comps/src/comps/scatterChartComp/seriesComp.tsx
@@ -0,0 +1,159 @@
+import {
+ BoolControl,
+ StringControl,
+ ColorControl,
+ list,
+ dropdownControl,
+ withDefault,
+ jsonControl,
+ toArray,
+ NumberControl,
+ isNumeric,
+ genRandomKey,
+ Dropdown,
+ MultiCompBuilder,
+ valueComp,
+} from "lowcoder-sdk";
+import { i18nObjs, trans } from "i18n/comps";
+
+import { ConstructorToComp, ConstructorToDataType, ConstructorToView } from "lowcoder-core";
+import { CompAction, CustomAction, customAction, isMyCustomAction } from "lowcoder-core";
+
+export type SeriesCompType = ConstructorToComp;
+export type RawSeriesCompType = ConstructorToView;
+type SeriesDataType = ConstructorToDataType;
+
+type ActionDataType = {
+ type: "chartDataChanged";
+ chartData: Array;
+};
+
+export function newSeries(name: string, columnName: string): SeriesDataType {
+ return {
+ seriesName: name,
+ columnName: columnName,
+ dataIndex: genRandomKey(),
+ };
+}
+
+const seriesChildrenMap = {
+ columnName: StringControl,
+ seriesName: StringControl,
+ dynamicSize: BoolControl,
+ symbolSize: NumberControl,
+ dynamicIndex: withDefault(NumberControl, "1"),
+ divider: withDefault(NumberControl, 1000),
+ effect: BoolControl,
+ showMarkLine: BoolControl,
+ markLineFrom: withDefault(StringControl, "[0,0]"),
+ markLineTo: withDefault(StringControl, "[1000,1000]"),
+ markLineDesc: StringControl,
+ hide: BoolControl,
+ // unique key, for sort
+ dataIndex: valueComp(""),
+};
+
+const SeriesTmpComp = new MultiCompBuilder(seriesChildrenMap, (props) => {
+ return props;
+})
+ .setPropertyViewFn(() => {
+ return <>>;
+ })
+ .build();
+
+class SeriesComp extends SeriesTmpComp {
+ getPropertyViewWithData(columnOptions: OptionsType): React.ReactNode {
+ return (
+ <>
+ {this.children.seriesName.propertyView({
+ label: trans("chart.seriesName"),
+ })}
+ {
+ this.children.columnName.dispatchChangeValueAction(value);
+ }}
+ />
+ {this.children.effect.propertyView({
+ label: trans("scatterChart.effect"),
+ })}
+ {this.children.dynamicSize.propertyView({
+ label: trans("scatterChart.dynamicSize"),
+ })}
+ {this.children.dynamicSize.getView() && this.children.dynamicIndex.propertyView({
+ label: trans("scatterChart.dynamicIndex"),
+ })}
+ {this.children.dynamicSize.getView() && this.children.divider.propertyView({
+ label: trans("scatterChart.divider"),
+ })}
+ {!this.children.dynamicSize.getView() && this.children.symbolSize.propertyView({
+ label: trans("scatterChart.symbolSize"),
+ })}
+ {this.children.showMarkLine.propertyView({
+ label: trans("scatterChart.showMarkLine"),
+ })}
+ {this.children.showMarkLine.getView() && this.children.markLineFrom.propertyView({
+ label: trans("scatterChart.from"),
+ })}
+ {this.children.showMarkLine.getView() && this.children.markLineTo.propertyView({
+ label: trans("scatterChart.to"),
+ })}
+ {this.children.showMarkLine.getView() && this.children.markLineDesc.propertyView({
+ label: trans("scatterChart.desc"),
+ })}
+ >
+ );
+ }
+}
+
+const SeriesListTmpComp = list(SeriesComp);
+
+export class SeriesListComp extends SeriesListTmpComp {
+ override reduce(action: CompAction): this {
+ if (isMyCustomAction(action, "chartDataChanged")) {
+ // auto generate series
+ const actions = this.genExampleSeriesActions(action.value.chartData);
+ return this.reduce(this.multiAction(actions));
+ }
+ return super.reduce(action);
+ }
+
+ private genExampleSeriesActions(chartData: Array) {
+ const actions: CustomAction[] = [];
+ if (!chartData || chartData.length <= 0 || !chartData[0]) {
+ return actions;
+ }
+ let delCnt = 0;
+ const existColumns = this.getView().map((s) => s.getView().columnName);
+ // delete series not in data
+ existColumns.forEach((columnName) => {
+ if (chartData[0]?.[columnName] === undefined) {
+ actions.push(this.deleteAction(0));
+ delCnt++;
+ }
+ });
+ if (existColumns.length > delCnt) {
+ // don't generate example if exists
+ return actions;
+ }
+ // generate example series
+ const exampleKeys = Object.keys(chartData[0])
+ .filter((key) => {
+ return !existColumns.includes(key) && isNumeric(chartData[0][key]);
+ })
+ .slice(0, 3);
+ exampleKeys.forEach((key) => actions.push(this.pushAction(newSeries(key, key))));
+ return actions;
+ }
+
+ dispatchDataChanged(chartData: Array): void {
+ this.dispatch(
+ customAction({
+ type: "chartDataChanged",
+ chartData: chartData,
+ })
+ );
+ }
+}
diff --git a/client/packages/lowcoder-comps/src/i18n/comps/locales/en.ts b/client/packages/lowcoder-comps/src/i18n/comps/locales/en.ts
index c2861b8ca..73c3d7d21 100644
--- a/client/packages/lowcoder-comps/src/i18n/comps/locales/en.ts
+++ b/client/packages/lowcoder-comps/src/i18n/comps/locales/en.ts
@@ -1,3 +1,7 @@
+import {default as defaultBaseTexture} from '../../../comps/line3dChartComp/images/default_base_texture.jpg';
+import {default as defaultHeightTexture} from '../../../comps/line3dChartComp/images/default_height_texture.jpg';
+import {default as defaultEnvironment} from '../../../comps/line3dChartComp/images/default_environment.jpg';
+
export const en = {
calendarChart: {
calendarType: 'Calendar Chart Type',
@@ -311,6 +315,183 @@ export const en = {
defaultBarometerPointerLength: "125",
defaultBarometerPointer_Y: "-10"
+ },
+ lineChart: {
+ cellSize: "Cell Size",
+ range: "Range",
+ markLines: "Mark Lines",
+ markAreas: "Mark Areas",
+ stacked: "Stacked Chart",
+ area: "Area Chart",
+ max: "Max",
+ min: "Min",
+ average: "Average",
+ markLineType: "Marker Type",
+ type: "Type",
+ name: "Name",
+ from: "From",
+ to: "To",
+ color: "Color",
+ areaPieces: "Area Pieces",
+ areaPiece: "Area Piece",
+ showEndLabel: "End Label",
+ symbol: "Symbol",
+ symbolSize: "Symbol Size",
+ animationDuration: "Animation Duration",
+ none: "None",
+ start: "Start",
+ middle: "Middle",
+ end: "End",
+ step: "Step",
+ polar: "Polar Chart",
+ solid: "Solid",
+ dashed: "Dashed",
+ dotted: "Dotted",
+ borderColor: "Border Color",
+ borderWidth: "Border Width",
+ borderType: "Border Type",
+ },
+ pieChart: {
+ showLabel: "Show Label",
+ mapUrl: "Map URL",
+ left: "Left",
+ top: "Top",
+ itemBg: "Background Image",
+ itemColor: "Color",
+ itemShadowColor: "Shadow Color",
+ itemShadowBlur: "Shadow Blur",
+ padAngle: "Pad Angle",
+ borderRadius: "Border Radius",
+ startAngle: "Start Angle",
+ endAngle: "End Angle",
+ roseType: "Rose Type",
+ area: "Area",
+ radius: "Radius",
+ none: "None",
+ labelPosition: "Position",
+ labelAlignTo: "AlignTo",
+ labelBleedMargin: "Bleed Margin",
+ labelEdgeDistance: "Edge Distance",
+ labelLine: "Label Line",
+ edge: "Edge",
+ outside: "Outside",
+ outer: "Outer",
+ inside: "Inside",
+ inner: "Inner",
+ center: "Center",
+ labelLineLength: "Label Line Length",
+ labelLineLength2: "Label Line Length2",
+ },
+ scatterChart: {
+ heatmap: "Heat Map",
+ heatmapMonth: "Heat Map Month",
+ polar: "Polar Chart",
+ visualMap: "Visual Map",
+ visualMapMin: "Visual Map Min",
+ visualMapMax: "Visual Map Max",
+ visualMapDimension: "Visual Map Dimension",
+ visualMapColorMin: "Visual Map Color Min",
+ visualMapColorMax: "Visual Map Color Max",
+ boundaryGap: "Boundary Gap",
+ labelIndex: "Label Column Index",
+ dynamicSize: "Dynamic Size",
+ dynamicIndex: "Size Column Index",
+ divider: "Divider",
+ singleAxis: "Single Axis",
+ effect: "Effect",
+ symbolSize: "Symbol Size",
+ from: "From",
+ to: "To",
+ showMarkLine: "Show Mark Line",
+ desc: "Description",
+ },
+ barChart: {
+ title: 'Title',
+ barWidth: 'Bar Width(%)',
+ race: 'Race',
+ stack: 'Stacked',
+ showBg: 'Show Bar Background',
+ bgColor: 'Background Color',
+ polarIsTangent: 'Tangential Chart',
+ radiusAxisMax: 'Max',
+ polarRadiusStart: 'Start Radius',
+ polarRadiusEnd: 'End Radius',
+ polarLabelData: 'Label Data',
+ polarStartAngle: 'Start Angle',
+ polarEndAngle: 'End Angle',
+ defaultTitle: 'Bar Chart',
+ barType: 'Bar Chart Type',
+ tooltip: 'Tooltip',
+ left: 'Left',
+ defaultLeft:'35',
+ top: 'Top',
+ defaultTop:'60',
+ bottom: 'Bottom',
+ defaultBottom:'60',
+ width: 'Width',
+ defaultWidth:'80',
+ min: 'Min',
+ defaultMin:'0',
+ max: 'Max',
+ defaultMax:'100',
+ gap: 'Gap',
+ defaultGap: '2',
+ defaultStartAngle: '210',
+ startAngle: 'Start Angle',
+ defaultEndAngle: '-30',
+ endAngle: 'End Angle',
+ defaultSplitNumber: '10',
+ splitNumber: 'Split Number',
+ radius: 'Radius',
+ defaultRadius: '80',
+ defaultTemperatureRadius: '60',
+ defaultPointerLength: '50',
+ pointerLength: 'Pointer Length',
+ pointerWidth: 'Pointer Width',
+ defaultPointerWidth: '5',
+ label:'Label',
+ position_x: 'Position-X',
+ defaultPosition_X: '50',
+ position_y: 'Position-Y',
+ defaultPosition_Y: '60',
+ progressBarWidth: 'Progress Bar Width',
+ defaultProgressBarWidth: '10',
+ defaultStageProgressBarWidth: '15',
+ defaultTemperatureProgressBarWidth: '35',
+ defaultRingProgressBarWidth: '20',
+ progressBar: 'Progress Bar',
+ roundCap: "Round Cap",
+ chartType: "Chart Type",
+ chartTypeTooltip: "Select the types of Charts.",
+ defaultPointer_Y: "0",
+ gradeDefaultPointerIcon: "path://M12.8,0.7l12,40.1H0.7L12.8,0.7z",
+ clockDefaultPointerIcon: "path://M2.9,0.7L2.9,0.7c1.4,0,2.6,1.2,2.6,2.6v115c0,1.4-1.2,2.6-2.6,2.6l0,0c-1.4,0-2.6-1.2-2.6-2.6V3.3C0.3,1.9,1.4,0.7,2.9,0.7z",
+ defaultBarometerPointerIcon: 'path://M2090.36389,615.30999 L2090.36389,615.30999 C2091.48372,615.30999 2092.40383,616.194028 2092.44859,617.312956 L2096.90698,728.755929 C2097.05155,732.369577 2094.2393,735.416212 2090.62566,735.56078 C2090.53845,735.564269 2090.45117,735.566014 2090.36389,735.566014 L2090.36389,735.566014 C2086.74736,735.566014 2083.81557,732.63423 2083.81557,729.017692 C2083.81557,728.930412 2083.81732,728.84314 2083.82081,728.755929 L2088.2792,617.312956 C2088.32396,616.194028 2089.24407,615.30999 2090.36389,615.30999 Z',
+ defaultMultiTitlePointerIcon: 'path://M2.9,0.7L2.9,0.7c1.4,0,2.6,1.2,2.6,2.6v115c0,1.4-1.2,2.6-2.6,2.6l0,0c-1.4,0-2.6-1.2-2.6-2.6V3.3C0.3,1.9,1.4,0.7,2.9,0.7z',
+ pointer_Y: "Pointer-Y",
+ pointer_Y_Tooltip: "Select the Y-value of the pointer.",
+ pointerIcon: "Pointer Icon",
+ pointerIconTooltip: "Select the Pointer Icon",
+ defaultGradeBarPointerLength: "25",
+ defaultGradeBarPointerWidth: "10",
+ defaultGradeBarPointer_Y: "45",
+ defaultAxisLabelDistance: "10",
+ defaultTemperatureAxisLabelDistance: "30",
+ axisLabelDistance: "Axis Label Distance",
+ progressBarColor: "Progress Bar Color",
+ gradeProgressBarString: "Progress Bar String",
+ defaultAxisTickLength: "7",
+ defaultAxisTickWidth: "2",
+ defaultAxisTickColor: "#444444",
+ defaultStageAxisTickColor: "#ffffff",
+ axisTickLength: "axisTick Length",
+ axisTickWidth: "axisTick Width",
+ axisTickWidthStage: "axisTick Width",
+ axisTickColor: "AxisTick Color",
+ defaultBarometerPointerWidth: "3",
+ defaultBarometerPointerLength: "125",
+ defaultBarometerPointer_Y: "-10"
+
},
echarts: {
legendVisibility: 'Legend',
@@ -367,6 +548,24 @@ export const en = {
tooltipTooltip: "Show or hide the Tooltip of the Chart.",
labelVisibility: "Label",
},
+ line3dchart: {
+ background: "Background",
+ lineStyleWidth: "Line Style Width",
+ lineStyleColor: "Line Style Color",
+ lineStyleOpacity: "Line Style Opacity",
+ effectShow: "Show Effects",
+ effectTrailWidth: "Trail Width",
+ effectTrailLength: "Trail Length",
+ effectTrailOpacity: "Trail Opacity",
+ effectTrailColor: "Trail Color",
+ environment: "Environment",
+ baseTexture: "Base Texture",
+ heightTexture: "Height Texture",
+ ambientCubemapTexture: "Ambient Cubemap Texture",
+ defaultBaseTexture: defaultBaseTexture,
+ defaultEnvironment: defaultEnvironment,
+ defaultHeightTexture: defaultHeightTexture,
+ },
chart: {
delete: "Delete",
data: "Data",
@@ -376,6 +575,7 @@ export const en = {
UIMode: "UI Mode",
chartType: "Chart Type",
xAxis: "X-axis",
+ yAxis: "Y-axis",
chartSeries: "Chart Series",
customSeries: "Custom Series",
add: "Add",
@@ -399,6 +599,8 @@ export const en = {
"Indicates the value of each coordinate. Example: '{{value * 100 + \"%\"}}'",
basicBar: "Basic Bar",
stackedBar: "Stacked Bar",
+ waterfallBar: "Waterfall Chart",
+ polar: "Polar",
barType: "Bar Chart Type",
categoryAxis: "Category Axis",
valueAxis: "Value Axis",
@@ -409,11 +611,14 @@ export const en = {
basicLine: "Basic Line",
stackedLine: "Stacked Line",
areaLine: "Area Line",
+ stackedAreaLine: "Stacked Area Line",
smooth: "Smooth Curve",
lineType: "Line Chart Type",
basicPie: "Basic Pie",
doughnutPie: "Doughnut Pie",
rosePie: "Rose Pie",
+ calendarPie: "Calendar Pie",
+ geoPie: "Geo Map Pie",
pieType: "Pie Chart Type",
spending: "Spending",
budget: "Budget",
@@ -446,6 +651,9 @@ export const en = {
diamond: "Diamond",
pin: "Pin",
arrow: "Arrow",
+ emptyCircle: "Empty Circle",
+ none: "None",
+ roundRect: "Round Rectangle",
pointColorLabel: "Point Color",
pointColorTooltip:
'Set point color based on series name and value. Variables: seriesName, value. Example: \'{{value < 25000 ? "red" : "green"}}\'',
diff --git a/client/packages/lowcoder-comps/src/i18n/comps/locales/enObj.tsx b/client/packages/lowcoder-comps/src/i18n/comps/locales/enObj.tsx
index 408e50bf5..b9d17e3c2 100644
--- a/client/packages/lowcoder-comps/src/i18n/comps/locales/enObj.tsx
+++ b/client/packages/lowcoder-comps/src/i18n/comps/locales/enObj.tsx
@@ -80,78 +80,95 @@ const defaultMapData = {
export const enObj: I18nObjects = {
defaultDataSource: [
{
- date: "2021-09",
+ date: "2021-09-01",
department: "Administration",
spending: 9003,
- budget: 8000,
+ budget: 8000
},
{
- date: "2021-09",
+ date: "2021-09-02",
department: "Finance",
spending: 3033,
- budget: 4000,
+ budget: 4000
},
{
- date: "2021-09",
+ date: "2021-09-03",
department: "Sales",
spending: 9230,
- budget: 8000,
+ budget: 8000
},
{
- date: "2021-10",
+ date: "2021-09-04",
department: "Administration",
spending: 13032,
- budget: 15000,
+ budget: 15000
},
{
- date: "2021-10",
+ date: "2021-09-05",
department: "Finance",
spending: 2300,
- budget: 5000,
+ budget: 5000
},
{
- date: "2021-10",
+ date: "2021-09-05",
department: "Sales",
spending: 7323.5,
- budget: 8000,
+ budget: 8000
},
{
- date: "2021-11",
+ date: "2021-09-06",
department: "Administration",
spending: 13000,
- budget: 16023,
+ budget: 16023
},
{
- date: "2021-11",
+ date: "2021-09-06",
department: "Finance",
spending: 3569.5,
- budget: 3000,
+ budget: 3000
},
{
- date: "2021-11",
+ date: "2021-09-07",
department: "Sales",
spending: 10000,
- budget: 9932,
+ budget: 9932
},
{
- date: "2021-12",
+ date: "2021-09-07",
department: "Administration",
spending: 18033,
- budget: 20000,
+ budget: 20000
},
{
- date: "2021-12",
+ date: "2021-09-08",
department: "Finance",
spending: 4890,
- budget: 4500,
+ budget: 4500
},
{
- date: "2021-12",
+ date: "2021-09-09",
department: "Sales",
spending: 9322,
- budget: 8000,
- },
+ budget: 8000
+ }
],
+ defaultBarChartOption: {
+ xAxis: {
+ type: 'category',
+ data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
+ },
+ yAxis: {
+ type: 'value'
+ },
+ series: [
+ {
+ data: [120, 200, 150, 80, 70, 110, 130],
+ type: 'bar'
+ }
+ ],
+ barWidth: 30,
+ barBg: "#aaaaaa"
+ },
defaultEchartsJsonOption: {
data: [
@@ -544,4 +561,1446 @@ export const enObj: I18nObjects = {
},
defaultMapJsonOption: defaultMapData,
+ defaultPieBg: 'data:image/jpeg;base64,/9j/4AAQS...',
+ usaMap: {"type":"FeatureCollection","features":[
+ {"type":"Feature","id":"01","properties":{"name":"Alabama"},"geometry":{"type":"Polygon","coordinates":[[[-87.359296,35.00118],[-85.606675,34.984749],[-85.431413,34.124869],[-85.184951,32.859696],[-85.069935,32.580372],[-84.960397,32.421541],[-85.004212,32.322956],[-84.889196,32.262709],[-85.058981,32.13674],[-85.053504,32.01077],[-85.141136,31.840985],[-85.042551,31.539753],[-85.113751,31.27686],[-85.004212,31.003013],[-85.497137,30.997536],[-87.600282,30.997536],[-87.633143,30.86609],[-87.408589,30.674397],[-87.446927,30.510088],[-87.37025,30.427934],[-87.518128,30.280057],[-87.655051,30.247195],[-87.90699,30.411504],[-87.934375,30.657966],[-88.011052,30.685351],[-88.10416,30.499135],[-88.137022,30.318396],[-88.394438,30.367688],[-88.471115,31.895754],[-88.241084,33.796253],[-88.098683,34.891641],[-88.202745,34.995703],[-87.359296,35.00118]]]}},
+ {"type":"Feature","id":"02","properties":{"name":"Alaska"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-131.602021,55.117982],[-131.569159,55.28229],[-131.355558,55.183705],[-131.38842,55.01392],[-131.645836,55.035827],[-131.602021,55.117982]]],[[[-131.832052,55.42469],[-131.645836,55.304197],[-131.749898,55.128935],[-131.832052,55.189182],[-131.832052,55.42469]]],[[[-132.976733,56.437924],[-132.735747,56.459832],[-132.631685,56.421493],[-132.664547,56.273616],[-132.878148,56.240754],[-133.069841,56.333862],[-132.976733,56.437924]]],[[[-133.595627,56.350293],[-133.162949,56.317431],[-133.05341,56.125739],[-132.620732,55.912138],[-132.472854,55.780691],[-132.4619,55.671152],[-132.357838,55.649245],[-132.341408,55.506844],[-132.166146,55.364444],[-132.144238,55.238474],[-132.029222,55.276813],[-131.97993,55.178228],[-131.958022,54.789365],[-132.029222,54.701734],[-132.308546,54.718165],[-132.385223,54.915335],[-132.483808,54.898904],[-132.686455,55.046781],[-132.746701,54.997489],[-132.916486,55.046781],[-132.889102,54.898904],[-132.73027,54.937242],[-132.626209,54.882473],[-132.675501,54.679826],[-132.867194,54.701734],[-133.157472,54.95915],[-133.239626,55.090597],[-133.223195,55.22752],[-133.453227,55.216566],[-133.453227,55.320628],[-133.277964,55.331582],[-133.102702,55.42469],[-133.17938,55.588998],[-133.387503,55.62186],[-133.420365,55.884753],[-133.497042,56.0162],[-133.639442,55.923092],[-133.694212,56.070969],[-133.546335,56.142169],[-133.666827,56.311955],[-133.595627,56.350293]]],[[[-133.738027,55.556137],[-133.546335,55.490413],[-133.414888,55.572568],[-133.283441,55.534229],[-133.420365,55.386352],[-133.633966,55.430167],[-133.738027,55.556137]]],[[[-133.907813,56.930849],[-134.050213,57.029434],[-133.885905,57.095157],[-133.343688,57.002049],[-133.102702,57.007526],[-132.932917,56.82131],[-132.620732,56.667956],[-132.653593,56.55294],[-132.817901,56.492694],[-133.042456,56.520078],[-133.201287,56.448878],[-133.420365,56.492694],[-133.66135,56.448878],[-133.710643,56.684386],[-133.688735,56.837741],[-133.869474,56.843218],[-133.907813,56.930849]]],[[[-134.115936,56.48174],[-134.25286,56.558417],[-134.400737,56.722725],[-134.417168,56.848695],[-134.296675,56.908941],[-134.170706,56.848695],[-134.143321,56.952757],[-133.748981,56.772017],[-133.710643,56.596755],[-133.847566,56.574848],[-133.935197,56.377678],[-133.836612,56.322908],[-133.957105,56.092877],[-134.110459,56.142169],[-134.132367,55.999769],[-134.230952,56.070969],[-134.291198,56.350293],[-134.115936,56.48174]]],[[[-134.636246,56.28457],[-134.669107,56.169554],[-134.806031,56.235277],[-135.178463,56.67891],[-135.413971,56.810356],[-135.331817,56.914418],[-135.424925,57.166357],[-135.687818,57.369004],[-135.419448,57.566174],[-135.298955,57.48402],[-135.063447,57.418296],[-134.849846,57.407343],[-134.844369,57.248511],[-134.636246,56.728202],[-134.636246,56.28457]]],[[[-134.712923,58.223407],[-134.373353,58.14673],[-134.176183,58.157683],[-134.187137,58.081006],[-133.902336,57.807159],[-134.099505,57.850975],[-134.148798,57.757867],[-133.935197,57.615466],[-133.869474,57.363527],[-134.083075,57.297804],[-134.154275,57.210173],[-134.499322,57.029434],[-134.603384,57.034911],[-134.6472,57.226604],[-134.575999,57.341619],[-134.608861,57.511404],[-134.729354,57.719528],[-134.707446,57.829067],[-134.784123,58.097437],[-134.91557,58.212453],[-134.953908,58.409623],[-134.712923,58.223407]]],[[[-135.857603,57.330665],[-135.715203,57.330665],[-135.567326,57.149926],[-135.633049,57.023957],[-135.857603,56.996572],[-135.824742,57.193742],[-135.857603,57.330665]]],[[[-136.279328,58.206976],[-135.978096,58.201499],[-135.780926,58.28913],[-135.496125,58.168637],[-135.64948,58.037191],[-135.59471,57.987898],[-135.45231,58.135776],[-135.107263,58.086483],[-134.91557,57.976944],[-135.025108,57.779775],[-134.937477,57.763344],[-134.822462,57.500451],[-135.085355,57.462112],[-135.572802,57.675713],[-135.556372,57.456635],[-135.709726,57.369004],[-135.890465,57.407343],[-136.000004,57.544266],[-136.208128,57.637374],[-136.366959,57.829067],[-136.569606,57.916698],[-136.558652,58.075529],[-136.421728,58.130299],[-136.377913,58.267222],[-136.279328,58.206976]]],[[[-147.079854,60.200582],[-147.501579,59.948643],[-147.53444,59.850058],[-147.874011,59.784335],[-147.80281,59.937689],[-147.435855,60.09652],[-147.205824,60.271782],[-147.079854,60.200582]]],[[[-147.561825,60.578491],[-147.616594,60.370367],[-147.758995,60.156767],[-147.956165,60.227967],[-147.791856,60.474429],[-147.561825,60.578491]]],[[[-147.786379,70.245291],[-147.682318,70.201475],[-147.162008,70.15766],[-146.888161,70.185044],[-146.510252,70.185044],[-146.099482,70.146706],[-145.858496,70.168614],[-145.622988,70.08646],[-145.195787,69.993352],[-144.620708,69.971444],[-144.461877,70.026213],[-144.078491,70.059075],[-143.914183,70.130275],[-143.497935,70.141229],[-143.503412,70.091936],[-143.25695,70.119321],[-142.747594,70.042644],[-142.402547,69.916674],[-142.079408,69.856428],[-142.008207,69.801659],[-141.712453,69.790705],[-141.433129,69.697597],[-141.378359,69.63735],[-141.208574,69.686643],[-141.00045,69.648304],[-141.00045,60.304644],[-140.53491,60.22249],[-140.474664,60.310121],[-139.987216,60.184151],[-139.696939,60.342983],[-139.088998,60.359413],[-139.198537,60.091043],[-139.045183,59.997935],[-138.700135,59.910304],[-138.623458,59.767904],[-137.604747,59.242118],[-137.445916,58.908024],[-137.265177,59.001132],[-136.827022,59.159963],[-136.580559,59.16544],[-136.465544,59.285933],[-136.476498,59.466672],[-136.301236,59.466672],[-136.25742,59.625503],[-135.945234,59.663842],[-135.479694,59.800766],[-135.025108,59.565257],[-135.068924,59.422857],[-134.959385,59.280456],[-134.701969,59.247595],[-134.378829,59.033994],[-134.400737,58.973748],[-134.25286,58.858732],[-133.842089,58.727285],[-133.173903,58.152206],[-133.075318,57.998852],[-132.867194,57.845498],[-132.560485,57.505928],[-132.253777,57.21565],[-132.368792,57.095157],[-132.05113,57.051341],[-132.127807,56.876079],[-131.870391,56.804879],[-131.837529,56.602232],[-131.580113,56.613186],[-131.087188,56.405062],[-130.78048,56.366724],[-130.621648,56.268139],[-130.468294,56.240754],[-130.424478,56.142169],[-130.101339,56.114785],[-130.002754,55.994292],[-130.150631,55.769737],[-130.128724,55.583521],[-129.986323,55.276813],[-130.095862,55.200136],[-130.336847,54.920812],[-130.687372,54.718165],[-130.785957,54.822227],[-130.917403,54.789365],[-131.010511,54.997489],[-130.983126,55.08512],[-131.092665,55.189182],[-130.862634,55.298721],[-130.928357,55.337059],[-131.158389,55.200136],[-131.284358,55.287767],[-131.426759,55.238474],[-131.843006,55.457552],[-131.700606,55.698537],[-131.963499,55.616383],[-131.974453,55.49589],[-132.182576,55.588998],[-132.226392,55.704014],[-132.083991,55.829984],[-132.127807,55.955953],[-132.324977,55.851892],[-132.522147,56.076446],[-132.642639,56.032631],[-132.719317,56.218847],[-132.527624,56.339339],[-132.341408,56.339339],[-132.396177,56.487217],[-132.297592,56.67891],[-132.450946,56.673433],[-132.768609,56.837741],[-132.993164,57.034911],[-133.51895,57.177311],[-133.507996,57.577128],[-133.677781,57.62642],[-133.639442,57.790728],[-133.814705,57.834544],[-134.072121,58.053622],[-134.143321,58.168637],[-134.586953,58.206976],[-135.074401,58.502731],[-135.282525,59.192825],[-135.38111,59.033994],[-135.337294,58.891593],[-135.140124,58.617746],[-135.189417,58.573931],[-135.05797,58.349376],[-135.085355,58.201499],[-135.277048,58.234361],[-135.430402,58.398669],[-135.633049,58.426053],[-135.91785,58.382238],[-135.912373,58.617746],[-136.087635,58.814916],[-136.246466,58.75467],[-136.876314,58.962794],[-136.931084,58.902547],[-136.586036,58.836824],[-136.317666,58.672516],[-136.213604,58.667039],[-136.180743,58.535592],[-136.043819,58.382238],[-136.388867,58.294607],[-136.591513,58.349376],[-136.59699,58.212453],[-136.859883,58.316515],[-136.947514,58.393192],[-137.111823,58.393192],[-137.566409,58.590362],[-137.900502,58.765624],[-137.933364,58.869686],[-138.11958,59.02304],[-138.634412,59.132579],[-138.919213,59.247595],[-139.417615,59.379041],[-139.746231,59.505011],[-139.718846,59.641934],[-139.625738,59.598119],[-139.5162,59.68575],[-139.625738,59.88292],[-139.488815,59.992458],[-139.554538,60.041751],[-139.801,59.833627],[-140.315833,59.696704],[-140.92925,59.745996],[-141.444083,59.871966],[-141.46599,59.970551],[-141.706976,59.948643],[-141.964392,60.019843],[-142.539471,60.085566],[-142.873564,60.091043],[-143.623905,60.036274],[-143.892275,59.997935],[-144.231845,60.140336],[-144.65357,60.206059],[-144.785016,60.29369],[-144.834309,60.441568],[-145.124586,60.430614],[-145.223171,60.299167],[-145.738004,60.474429],[-145.820158,60.551106],[-146.351421,60.408706],[-146.608837,60.238921],[-146.718376,60.397752],[-146.608837,60.485383],[-146.455483,60.463475],[-145.951604,60.578491],[-146.017328,60.666122],[-146.252836,60.622307],[-146.345944,60.737322],[-146.565022,60.753753],[-146.784099,61.044031],[-146.866253,60.972831],[-147.172962,60.934492],[-147.271547,60.972831],[-147.375609,60.879723],[-147.758995,60.912584],[-147.775426,60.808523],[-148.032842,60.781138],[-148.153334,60.819476],[-148.065703,61.005692],[-148.175242,61.000215],[-148.350504,60.803046],[-148.109519,60.737322],[-148.087611,60.594922],[-147.939734,60.441568],[-148.027365,60.277259],[-148.219058,60.332029],[-148.273827,60.249875],[-148.087611,60.217013],[-147.983549,59.997935],[-148.251919,59.95412],[-148.399797,59.997935],[-148.635305,59.937689],[-148.755798,59.986981],[-149.067984,59.981505],[-149.05703,60.063659],[-149.204907,60.008889],[-149.287061,59.904827],[-149.418508,59.997935],[-149.582816,59.866489],[-149.511616,59.806242],[-149.741647,59.729565],[-149.949771,59.718611],[-150.031925,59.61455],[-150.25648,59.521442],[-150.409834,59.554303],[-150.579619,59.444764],[-150.716543,59.450241],[-151.001343,59.225687],[-151.308052,59.209256],[-151.406637,59.280456],[-151.592853,59.159963],[-151.976239,59.253071],[-151.888608,59.422857],[-151.636669,59.483103],[-151.47236,59.472149],[-151.423068,59.537872],[-151.127313,59.669319],[-151.116359,59.778858],[-151.505222,59.63098],[-151.828361,59.718611],[-151.8667,59.778858],[-151.702392,60.030797],[-151.423068,60.211536],[-151.379252,60.359413],[-151.297098,60.386798],[-151.264237,60.545629],[-151.406637,60.720892],[-151.06159,60.786615],[-150.404357,61.038554],[-150.245526,60.939969],[-150.042879,60.912584],[-149.741647,61.016646],[-150.075741,61.15357],[-150.207187,61.257632],[-150.47008,61.246678],[-150.656296,61.29597],[-150.711066,61.252155],[-151.023251,61.180954],[-151.165652,61.044031],[-151.477837,61.011169],[-151.800977,60.852338],[-151.833838,60.748276],[-152.080301,60.693507],[-152.13507,60.578491],[-152.310332,60.507291],[-152.392486,60.304644],[-152.732057,60.173197],[-152.567748,60.069136],[-152.704672,59.915781],[-153.022334,59.888397],[-153.049719,59.691227],[-153.345474,59.620026],[-153.438582,59.702181],[-153.586459,59.548826],[-153.761721,59.543349],[-153.72886,59.433811],[-154.117723,59.368087],[-154.1944,59.066856],[-153.750768,59.050425],[-153.400243,58.968271],[-153.301658,58.869686],[-153.444059,58.710854],[-153.679567,58.612269],[-153.898645,58.606793],[-153.920553,58.519161],[-154.062953,58.4863],[-153.99723,58.376761],[-154.145107,58.212453],[-154.46277,58.059098],[-154.643509,58.059098],[-154.818771,58.004329],[-154.988556,58.015283],[-155.120003,57.955037],[-155.081664,57.872883],[-155.328126,57.829067],[-155.377419,57.708574],[-155.547204,57.785251],[-155.73342,57.549743],[-156.045606,57.566174],[-156.023698,57.440204],[-156.209914,57.473066],[-156.34136,57.418296],[-156.34136,57.248511],[-156.549484,56.985618],[-156.883577,56.952757],[-157.157424,56.832264],[-157.20124,56.766541],[-157.376502,56.859649],[-157.672257,56.607709],[-157.754411,56.67891],[-157.918719,56.657002],[-157.957058,56.514601],[-158.126843,56.459832],[-158.32949,56.48174],[-158.488321,56.339339],[-158.208997,56.295524],[-158.510229,55.977861],[-159.375585,55.873799],[-159.616571,55.594475],[-159.676817,55.654722],[-159.643955,55.829984],[-159.813741,55.857368],[-160.027341,55.791645],[-160.060203,55.720445],[-160.394296,55.605429],[-160.536697,55.473983],[-160.580512,55.567091],[-160.668143,55.457552],[-160.865313,55.528752],[-161.232268,55.358967],[-161.506115,55.364444],[-161.467776,55.49589],[-161.588269,55.62186],[-161.697808,55.517798],[-161.686854,55.408259],[-162.053809,55.074166],[-162.179779,55.15632],[-162.218117,55.03035],[-162.470057,55.052258],[-162.508395,55.249428],[-162.661749,55.293244],[-162.716519,55.222043],[-162.579595,55.134412],[-162.645319,54.997489],[-162.847965,54.926289],[-163.00132,55.079643],[-163.187536,55.090597],[-163.220397,55.03035],[-163.034181,54.942719],[-163.373752,54.800319],[-163.14372,54.76198],[-163.138243,54.696257],[-163.329936,54.74555],[-163.587352,54.614103],[-164.085754,54.61958],[-164.332216,54.531949],[-164.354124,54.466226],[-164.638925,54.389548],[-164.847049,54.416933],[-164.918249,54.603149],[-164.710125,54.663395],[-164.551294,54.88795],[-164.34317,54.893427],[-163.894061,55.041304],[-163.532583,55.046781],[-163.39566,54.904381],[-163.291598,55.008443],[-163.313505,55.128935],[-163.105382,55.183705],[-162.880827,55.183705],[-162.579595,55.446598],[-162.245502,55.682106],[-161.807347,55.89023],[-161.292514,55.983338],[-161.078914,55.939523],[-160.87079,55.999769],[-160.816021,55.912138],[-160.931036,55.813553],[-160.805067,55.736876],[-160.766728,55.857368],[-160.509312,55.868322],[-160.438112,55.791645],[-160.27928,55.76426],[-160.273803,55.857368],[-160.536697,55.939523],[-160.558604,55.994292],[-160.383342,56.251708],[-160.147834,56.399586],[-159.830171,56.541986],[-159.326293,56.667956],[-158.959338,56.848695],[-158.784076,56.782971],[-158.641675,56.810356],[-158.701922,56.925372],[-158.658106,57.034911],[-158.378782,57.264942],[-157.995396,57.41282],[-157.688688,57.609989],[-157.705118,57.719528],[-157.458656,58.497254],[-157.07527,58.705377],[-157.119086,58.869686],[-158.039212,58.634177],[-158.32949,58.661562],[-158.40069,58.760147],[-158.564998,58.803962],[-158.619768,58.913501],[-158.767645,58.864209],[-158.860753,58.694424],[-158.701922,58.480823],[-158.893615,58.387715],[-159.0634,58.420577],[-159.392016,58.760147],[-159.616571,58.929932],[-159.731586,58.929932],[-159.808264,58.803962],[-159.906848,58.782055],[-160.054726,58.886116],[-160.235465,58.902547],[-160.317619,59.072332],[-160.854359,58.88064],[-161.33633,58.743716],[-161.374669,58.667039],[-161.752577,58.552023],[-161.938793,58.656085],[-161.769008,58.776578],[-161.829255,59.061379],[-161.955224,59.36261],[-161.703285,59.48858],[-161.911409,59.740519],[-162.092148,59.88292],[-162.234548,60.091043],[-162.448149,60.178674],[-162.502918,59.997935],[-162.760334,59.959597],[-163.171105,59.844581],[-163.66403,59.795289],[-163.9324,59.806242],[-164.162431,59.866489],[-164.189816,60.02532],[-164.386986,60.074613],[-164.699171,60.29369],[-164.962064,60.337506],[-165.268773,60.578491],[-165.060649,60.68803],[-165.016834,60.890677],[-165.175665,60.846861],[-165.197573,60.972831],[-165.120896,61.076893],[-165.323543,61.170001],[-165.34545,61.071416],[-165.591913,61.109754],[-165.624774,61.279539],[-165.816467,61.301447],[-165.920529,61.416463],[-165.915052,61.558863],[-166.106745,61.49314],[-166.139607,61.630064],[-165.904098,61.662925],[-166.095791,61.81628],[-165.756221,61.827233],[-165.756221,62.013449],[-165.674067,62.139419],[-165.044219,62.539236],[-164.912772,62.659728],[-164.819664,62.637821],[-164.874433,62.807606],[-164.633448,63.097884],[-164.425324,63.212899],[-164.036462,63.262192],[-163.73523,63.212899],[-163.313505,63.037637],[-163.039658,63.059545],[-162.661749,63.22933],[-162.272887,63.486746],[-162.075717,63.514131],[-162.026424,63.448408],[-161.555408,63.448408],[-161.13916,63.503177],[-160.766728,63.771547],[-160.766728,63.837271],[-160.952944,64.08921],[-160.974852,64.237087],[-161.26513,64.395918],[-161.374669,64.532842],[-161.078914,64.494503],[-160.79959,64.609519],[-160.783159,64.719058],[-161.144637,64.921705],[-161.413007,64.762873],[-161.664946,64.790258],[-161.900455,64.702627],[-162.168825,64.680719],[-162.234548,64.620473],[-162.541257,64.532842],[-162.634365,64.384965],[-162.787719,64.324718],[-162.858919,64.49998],[-163.045135,64.538319],[-163.176582,64.401395],[-163.253259,64.467119],[-163.598306,64.565704],[-164.304832,64.560227],[-164.80871,64.450688],[-165.000403,64.434257],[-165.411174,64.49998],[-166.188899,64.576658],[-166.391546,64.636904],[-166.484654,64.735489],[-166.413454,64.872412],[-166.692778,64.987428],[-166.638008,65.113398],[-166.462746,65.179121],[-166.517516,65.337952],[-166.796839,65.337952],[-167.026871,65.381768],[-167.47598,65.414629],[-167.711489,65.496784],[-168.072967,65.578938],[-168.105828,65.682999],[-167.541703,65.819923],[-166.829701,66.049954],[-166.3313,66.186878],[-166.046499,66.110201],[-165.756221,66.09377],[-165.690498,66.203309],[-165.86576,66.21974],[-165.88219,66.312848],[-165.186619,66.466202],[-164.403417,66.581218],[-163.981692,66.592172],[-163.751661,66.553833],[-163.872153,66.389525],[-163.828338,66.274509],[-163.915969,66.192355],[-163.768091,66.060908],[-163.494244,66.082816],[-163.149197,66.060908],[-162.749381,66.088293],[-162.634365,66.039001],[-162.371472,66.028047],[-162.14144,66.077339],[-161.840208,66.02257],[-161.549931,66.241647],[-161.341807,66.252601],[-161.199406,66.208786],[-161.128206,66.334755],[-161.528023,66.395002],[-161.911409,66.345709],[-161.87307,66.510017],[-162.174302,66.68528],[-162.502918,66.740049],[-162.601503,66.89888],[-162.344087,66.937219],[-162.015471,66.778388],[-162.075717,66.652418],[-161.916886,66.553833],[-161.571838,66.438817],[-161.489684,66.55931],[-161.884024,66.718141],[-161.714239,67.002942],[-161.851162,67.052235],[-162.240025,66.991988],[-162.639842,67.008419],[-162.700088,67.057712],[-162.902735,67.008419],[-163.740707,67.128912],[-163.757138,67.254881],[-164.009077,67.534205],[-164.211724,67.638267],[-164.534863,67.725898],[-165.192096,67.966884],[-165.493328,68.059992],[-165.794559,68.081899],[-166.243668,68.246208],[-166.681824,68.339316],[-166.703731,68.372177],[-166.375115,68.42147],[-166.227238,68.574824],[-166.216284,68.881533],[-165.329019,68.859625],[-164.255539,68.930825],[-163.976215,68.985595],[-163.532583,69.138949],[-163.110859,69.374457],[-163.023228,69.609966],[-162.842489,69.812613],[-162.470057,69.982398],[-162.311225,70.108367],[-161.851162,70.311014],[-161.779962,70.256245],[-161.396576,70.239814],[-160.837928,70.343876],[-160.487404,70.453415],[-159.649432,70.792985],[-159.33177,70.809416],[-159.298908,70.760123],[-158.975769,70.798462],[-158.658106,70.787508],[-158.033735,70.831323],[-157.420318,70.979201],[-156.812377,71.285909],[-156.565915,71.351633],[-156.522099,71.296863],[-155.585543,71.170894],[-155.508865,71.083263],[-155.832005,70.968247],[-155.979882,70.96277],[-155.974405,70.809416],[-155.503388,70.858708],[-155.476004,70.940862],[-155.262403,71.017539],[-155.191203,70.973724],[-155.032372,71.148986],[-154.566832,70.990155],[-154.643509,70.869662],[-154.353231,70.8368],[-154.183446,70.7656],[-153.931507,70.880616],[-153.487874,70.886093],[-153.235935,70.924431],[-152.589656,70.886093],[-152.26104,70.842277],[-152.419871,70.606769],[-151.817408,70.546523],[-151.773592,70.486276],[-151.187559,70.382214],[-151.182082,70.431507],[-150.760358,70.49723],[-150.355064,70.491753],[-150.349588,70.436984],[-150.114079,70.431507],[-149.867617,70.508184],[-149.462323,70.519138],[-149.177522,70.486276],[-148.78866,70.404122],[-148.607921,70.420553],[-148.350504,70.305537],[-148.202627,70.349353],[-147.961642,70.316491],[-147.786379,70.245291]]],[[[-152.94018,58.026237],[-152.945657,57.982421],[-153.290705,58.048145],[-153.044242,58.305561],[-152.819688,58.327469],[-152.666333,58.562977],[-152.496548,58.354853],[-152.354148,58.426053],[-152.080301,58.311038],[-152.080301,58.152206],[-152.480117,58.130299],[-152.655379,58.059098],[-152.94018,58.026237]]],[[[-153.958891,57.538789],[-153.67409,57.670236],[-153.931507,57.69762],[-153.936983,57.812636],[-153.723383,57.889313],[-153.570028,57.834544],[-153.548121,57.719528],[-153.46049,57.796205],[-153.455013,57.96599],[-153.268797,57.889313],[-153.235935,57.998852],[-153.071627,57.933129],[-152.874457,57.933129],[-152.721103,57.993375],[-152.469163,57.889313],[-152.469163,57.599035],[-152.151501,57.620943],[-152.359625,57.42925],[-152.74301,57.505928],[-152.60061,57.379958],[-152.710149,57.275896],[-152.907319,57.325188],[-152.912796,57.128019],[-153.214027,57.073249],[-153.312612,56.991095],[-153.498828,57.067772],[-153.695998,56.859649],[-153.849352,56.837741],[-154.013661,56.744633],[-154.073907,56.969187],[-154.303938,56.848695],[-154.314892,56.919895],[-154.523016,56.991095],[-154.539447,57.193742],[-154.742094,57.275896],[-154.627078,57.511404],[-154.227261,57.659282],[-153.980799,57.648328],[-153.958891,57.538789]]],[[[-154.53397,56.602232],[-154.742094,56.399586],[-154.807817,56.432447],[-154.53397,56.602232]]],[[[-155.634835,55.923092],[-155.476004,55.912138],[-155.530773,55.704014],[-155.793666,55.731399],[-155.837482,55.802599],[-155.634835,55.923092]]],[[[-159.890418,55.28229],[-159.950664,55.068689],[-160.257373,54.893427],[-160.109495,55.161797],[-160.005433,55.134412],[-159.890418,55.28229]]],[[[-160.520266,55.358967],[-160.33405,55.358967],[-160.339527,55.249428],[-160.525743,55.128935],[-160.690051,55.211089],[-160.794113,55.134412],[-160.854359,55.320628],[-160.79959,55.380875],[-160.520266,55.358967]]],[[[-162.256456,54.981058],[-162.234548,54.893427],[-162.349564,54.838658],[-162.437195,54.931766],[-162.256456,54.981058]]],[[[-162.415287,63.634624],[-162.563165,63.536039],[-162.612457,63.62367],[-162.415287,63.634624]]],[[[-162.80415,54.488133],[-162.590549,54.449795],[-162.612457,54.367641],[-162.782242,54.373118],[-162.80415,54.488133]]],[[[-165.548097,54.29644],[-165.476897,54.181425],[-165.630251,54.132132],[-165.685021,54.252625],[-165.548097,54.29644]]],[[[-165.73979,54.15404],[-166.046499,54.044501],[-166.112222,54.121178],[-165.980775,54.219763],[-165.73979,54.15404]]],[[[-166.364161,60.359413],[-166.13413,60.397752],[-166.084837,60.326552],[-165.88219,60.342983],[-165.685021,60.277259],[-165.646682,59.992458],[-165.750744,59.89935],[-166.00816,59.844581],[-166.062929,59.745996],[-166.440838,59.855535],[-166.6161,59.850058],[-166.994009,59.992458],[-167.125456,59.992458],[-167.344534,60.074613],[-167.421211,60.206059],[-167.311672,60.238921],[-166.93924,60.206059],[-166.763978,60.310121],[-166.577762,60.321075],[-166.495608,60.392275],[-166.364161,60.359413]]],[[[-166.375115,54.01164],[-166.210807,53.934962],[-166.5449,53.748746],[-166.539423,53.715885],[-166.117699,53.852808],[-166.112222,53.776131],[-166.282007,53.683023],[-166.555854,53.622777],[-166.583239,53.529669],[-166.878994,53.431084],[-167.13641,53.425607],[-167.306195,53.332499],[-167.623857,53.250345],[-167.793643,53.337976],[-167.459549,53.442038],[-167.355487,53.425607],[-167.103548,53.513238],[-167.163794,53.611823],[-167.021394,53.715885],[-166.807793,53.666592],[-166.785886,53.732316],[-167.015917,53.754223],[-167.141887,53.825424],[-167.032348,53.945916],[-166.643485,54.017116],[-166.561331,53.880193],[-166.375115,54.01164]]],[[[-168.790446,53.157237],[-168.40706,53.34893],[-168.385152,53.431084],[-168.237275,53.524192],[-168.007243,53.568007],[-167.886751,53.518715],[-167.842935,53.387268],[-168.270136,53.244868],[-168.500168,53.036744],[-168.686384,52.965544],[-168.790446,53.157237]]],[[[-169.74891,52.894344],[-169.705095,52.795759],[-169.962511,52.790282],[-169.989896,52.856005],[-169.74891,52.894344]]],[[[-170.148727,57.221127],[-170.28565,57.128019],[-170.313035,57.221127],[-170.148727,57.221127]]],[[[-170.669036,52.697174],[-170.603313,52.604066],[-170.789529,52.538343],[-170.816914,52.636928],[-170.669036,52.697174]]],[[[-171.742517,63.716778],[-170.94836,63.5689],[-170.488297,63.69487],[-170.280174,63.683916],[-170.093958,63.612716],[-170.044665,63.492223],[-169.644848,63.4265],[-169.518879,63.366254],[-168.99857,63.338869],[-168.686384,63.295053],[-168.856169,63.147176],[-169.108108,63.180038],[-169.376478,63.152653],[-169.513402,63.08693],[-169.639372,62.939052],[-169.831064,63.075976],[-170.055619,63.169084],[-170.263743,63.180038],[-170.362328,63.2841],[-170.866206,63.415546],[-171.101715,63.421023],[-171.463193,63.306007],[-171.73704,63.366254],[-171.852055,63.486746],[-171.742517,63.716778]]],[[[-172.432611,52.390465],[-172.41618,52.275449],[-172.607873,52.253542],[-172.569535,52.352127],[-172.432611,52.390465]]],[[[-173.626584,52.14948],[-173.495138,52.105664],[-173.122706,52.111141],[-173.106275,52.07828],[-173.549907,52.028987],[-173.626584,52.14948]]],[[[-174.322156,52.280926],[-174.327632,52.379511],[-174.185232,52.41785],[-173.982585,52.319265],[-174.059262,52.226157],[-174.179755,52.231634],[-174.141417,52.127572],[-174.333109,52.116618],[-174.738403,52.007079],[-174.968435,52.039941],[-174.902711,52.116618],[-174.656249,52.105664],[-174.322156,52.280926]]],[[[-176.469116,51.853725],[-176.288377,51.870156],[-176.288377,51.744186],[-176.518409,51.760617],[-176.80321,51.61274],[-176.912748,51.80991],[-176.792256,51.815386],[-176.775825,51.963264],[-176.627947,51.968741],[-176.627947,51.859202],[-176.469116,51.853725]]],[[[-177.153734,51.946833],[-177.044195,51.897541],[-177.120872,51.727755],[-177.274226,51.678463],[-177.279703,51.782525],[-177.153734,51.946833]]],[[[-178.123152,51.919448],[-177.953367,51.913971],[-177.800013,51.793479],[-177.964321,51.651078],[-178.123152,51.919448]]],[[[-186.892443, 52.992929],[-186.706227, 52.927205],[-186.695274, 52.823143],[-187.09509, 52.762897],[-187.357983, 52.927205],[-187.357983, 53.003883],[-186.892443, 52.992929]]]]}},
+ {"type":"Feature","id":"04","properties":{"name":"Arizona"},"geometry":{"type":"Polygon","coordinates":[[[-109.042503,37.000263],[-109.04798,31.331629],[-111.074448,31.331629],[-112.246513,31.704061],[-114.815198,32.492741],[-114.72209,32.717295],[-114.524921,32.755634],[-114.470151,32.843265],[-114.524921,33.029481],[-114.661844,33.034958],[-114.727567,33.40739],[-114.524921,33.54979],[-114.497536,33.697668],[-114.535874,33.933176],[-114.415382,34.108438],[-114.256551,34.174162],[-114.136058,34.305608],[-114.333228,34.448009],[-114.470151,34.710902],[-114.634459,34.87521],[-114.634459,35.00118],[-114.574213,35.138103],[-114.596121,35.324319],[-114.678275,35.516012],[-114.738521,36.102045],[-114.371566,36.140383],[-114.251074,36.01989],[-114.152489,36.025367],[-114.048427,36.195153],[-114.048427,37.000263],[-110.499369,37.00574],[-109.042503,37.000263]]]}},
+ {"type":"Feature","id":"05","properties":{"name":"Arkansas"},"geometry":{"type":"Polygon","coordinates":[[[-94.473842,36.501861],[-90.152536,36.496384],[-90.064905,36.304691],[-90.218259,36.184199],[-90.377091,35.997983],[-89.730812,35.997983],[-89.763673,35.811767],[-89.911551,35.756997],[-89.944412,35.603643],[-90.130628,35.439335],[-90.114197,35.198349],[-90.212782,35.023087],[-90.311367,34.995703],[-90.251121,34.908072],[-90.409952,34.831394],[-90.481152,34.661609],[-90.585214,34.617794],[-90.568783,34.420624],[-90.749522,34.365854],[-90.744046,34.300131],[-90.952169,34.135823],[-90.891923,34.026284],[-91.072662,33.867453],[-91.231493,33.560744],[-91.056231,33.429298],[-91.143862,33.347144],[-91.089093,33.13902],[-91.16577,33.002096],[-93.608485,33.018527],[-94.041164,33.018527],[-94.041164,33.54979],[-94.183564,33.593606],[-94.380734,33.544313],[-94.484796,33.637421],[-94.430026,35.395519],[-94.616242,36.501861],[-94.473842,36.501861]]]}},
+ {"type":"Feature","id":"06","properties":{"name":"California"},"geometry":{"type":"Polygon","coordinates":[[[-123.233256,42.006186],[-122.378853,42.011663],[-121.037003,41.995232],[-120.001861,41.995232],[-119.996384,40.264519],[-120.001861,38.999346],[-118.71478,38.101128],[-117.498899,37.21934],[-116.540435,36.501861],[-115.85034,35.970598],[-114.634459,35.00118],[-114.634459,34.87521],[-114.470151,34.710902],[-114.333228,34.448009],[-114.136058,34.305608],[-114.256551,34.174162],[-114.415382,34.108438],[-114.535874,33.933176],[-114.497536,33.697668],[-114.524921,33.54979],[-114.727567,33.40739],[-114.661844,33.034958],[-114.524921,33.029481],[-114.470151,32.843265],[-114.524921,32.755634],[-114.72209,32.717295],[-116.04751,32.624187],[-117.126467,32.536556],[-117.24696,32.668003],[-117.252437,32.876127],[-117.329114,33.122589],[-117.471515,33.297851],[-117.7837,33.538836],[-118.183517,33.763391],[-118.260194,33.703145],[-118.413548,33.741483],[-118.391641,33.840068],[-118.566903,34.042715],[-118.802411,33.998899],[-119.218659,34.146777],[-119.278905,34.26727],[-119.558229,34.415147],[-119.875891,34.40967],[-120.138784,34.475393],[-120.472878,34.448009],[-120.64814,34.579455],[-120.609801,34.858779],[-120.670048,34.902595],[-120.631709,35.099764],[-120.894602,35.247642],[-120.905556,35.450289],[-121.004141,35.461243],[-121.168449,35.636505],[-121.283465,35.674843],[-121.332757,35.784382],[-121.716143,36.195153],[-121.896882,36.315645],[-121.935221,36.638785],[-121.858544,36.6114],[-121.787344,36.803093],[-121.929744,36.978355],[-122.105006,36.956447],[-122.335038,37.115279],[-122.417192,37.241248],[-122.400761,37.361741],[-122.515777,37.520572],[-122.515777,37.783465],[-122.329561,37.783465],[-122.406238,38.15042],[-122.488392,38.112082],[-122.504823,37.931343],[-122.701993,37.893004],[-122.937501,38.029928],[-122.97584,38.265436],[-123.129194,38.451652],[-123.331841,38.566668],[-123.44138,38.698114],[-123.737134,38.95553],[-123.687842,39.032208],[-123.824765,39.366301],[-123.764519,39.552517],[-123.85215,39.831841],[-124.109566,40.105688],[-124.361506,40.259042],[-124.410798,40.439781],[-124.158859,40.877937],[-124.109566,41.025814],[-124.158859,41.14083],[-124.065751,41.442061],[-124.147905,41.715908],[-124.257444,41.781632],[-124.213628,42.000709],[-123.233256,42.006186]]]}},
+ {"type":"Feature","id":"08","properties":{"name":"Colorado"},"geometry":{"type":"Polygon","coordinates":[[[-107.919731,41.003906],[-105.728954,40.998429],[-104.053011,41.003906],[-102.053927,41.003906],[-102.053927,40.001626],[-102.042974,36.994786],[-103.001438,37.000263],[-104.337812,36.994786],[-106.868158,36.994786],[-107.421329,37.000263],[-109.042503,37.000263],[-109.042503,38.166851],[-109.058934,38.27639],[-109.053457,39.125316],[-109.04798,40.998429],[-107.919731,41.003906]]]}},
+ {"type":"Feature","id":"09","properties":{"name":"Connecticut"},"geometry":{"type":"Polygon","coordinates":[[[-73.053528,42.039048],[-71.799309,42.022617],[-71.799309,42.006186],[-71.799309,41.414677],[-71.859555,41.321569],[-71.947186,41.338],[-72.385341,41.261322],[-72.905651,41.28323],[-73.130205,41.146307],[-73.371191,41.102491],[-73.655992,40.987475],[-73.727192,41.102491],[-73.48073,41.21203],[-73.55193,41.294184],[-73.486206,42.050002],[-73.053528,42.039048]]]}},
+ {"type":"Feature","id":"10","properties":{"name":"Delaware"},"geometry":{"type":"Polygon","coordinates":[[[-75.414089,39.804456],[-75.507197,39.683964],[-75.611259,39.61824],[-75.589352,39.459409],[-75.441474,39.311532],[-75.403136,39.065069],[-75.189535,38.807653],[-75.09095,38.796699],[-75.047134,38.451652],[-75.693413,38.462606],[-75.786521,39.722302],[-75.616736,39.831841],[-75.414089,39.804456]]]}},
+ {"type":"Feature","id":"11","properties":{"name":"District of Columbia"},"geometry":{"type":"Polygon","coordinates":[[[-77.035264,38.993869],[-76.909294,38.895284],[-77.040741,38.791222],[-77.117418,38.933623],[-77.035264,38.993869]]]}},
+ {"type":"Feature","id":"12","properties":{"name":"Florida"},"geometry":{"type":"Polygon","coordinates":[[[-85.497137,30.997536],[-85.004212,31.003013],[-84.867289,30.712735],[-83.498053,30.647012],[-82.216449,30.570335],[-82.167157,30.356734],[-82.046664,30.362211],[-82.002849,30.564858],[-82.041187,30.751074],[-81.948079,30.827751],[-81.718048,30.745597],[-81.444201,30.707258],[-81.383954,30.27458],[-81.257985,29.787132],[-80.967707,29.14633],[-80.524075,28.461713],[-80.589798,28.41242],[-80.56789,28.094758],[-80.381674,27.738757],[-80.091397,27.021277],[-80.03115,26.796723],[-80.036627,26.566691],[-80.146166,25.739673],[-80.239274,25.723243],[-80.337859,25.465826],[-80.304997,25.383672],[-80.49669,25.197456],[-80.573367,25.241272],[-80.759583,25.164595],[-81.077246,25.120779],[-81.170354,25.224841],[-81.126538,25.378195],[-81.351093,25.821827],[-81.526355,25.903982],[-81.679709,25.843735],[-81.800202,26.090198],[-81.833064,26.292844],[-82.041187,26.517399],[-82.09048,26.665276],[-82.057618,26.878877],[-82.172634,26.917216],[-82.145249,26.791246],[-82.249311,26.758384],[-82.566974,27.300601],[-82.692943,27.437525],[-82.391711,27.837342],[-82.588881,27.815434],[-82.720328,27.689464],[-82.851774,27.886634],[-82.676512,28.434328],[-82.643651,28.888914],[-82.764143,28.998453],[-82.802482,29.14633],[-82.994175,29.179192],[-83.218729,29.420177],[-83.399469,29.518762],[-83.410422,29.66664],[-83.536392,29.721409],[-83.640454,29.885717],[-84.02384,30.104795],[-84.357933,30.055502],[-84.341502,29.902148],[-84.451041,29.929533],[-84.867289,29.743317],[-85.310921,29.699501],[-85.299967,29.80904],[-85.404029,29.940487],[-85.924338,30.236241],[-86.29677,30.362211],[-86.630863,30.395073],[-86.910187,30.373165],[-87.518128,30.280057],[-87.37025,30.427934],[-87.446927,30.510088],[-87.408589,30.674397],[-87.633143,30.86609],[-87.600282,30.997536],[-85.497137,30.997536]]]}},
+ {"type":"Feature","id":"13","properties":{"name":"Georgia"},"geometry":{"type":"Polygon","coordinates":[[[-83.109191,35.00118],[-83.322791,34.787579],[-83.339222,34.683517],[-83.005129,34.469916],[-82.901067,34.486347],[-82.747713,34.26727],[-82.714851,34.152254],[-82.55602,33.94413],[-82.325988,33.81816],[-82.194542,33.631944],[-81.926172,33.462159],[-81.937125,33.347144],[-81.761863,33.160928],[-81.493493,33.007573],[-81.42777,32.843265],[-81.416816,32.629664],[-81.279893,32.558464],[-81.121061,32.290094],[-81.115584,32.120309],[-80.885553,32.032678],[-81.132015,31.693108],[-81.175831,31.517845],[-81.279893,31.364491],[-81.290846,31.20566],[-81.400385,31.13446],[-81.444201,30.707258],[-81.718048,30.745597],[-81.948079,30.827751],[-82.041187,30.751074],[-82.002849,30.564858],[-82.046664,30.362211],[-82.167157,30.356734],[-82.216449,30.570335],[-83.498053,30.647012],[-84.867289,30.712735],[-85.004212,31.003013],[-85.113751,31.27686],[-85.042551,31.539753],[-85.141136,31.840985],[-85.053504,32.01077],[-85.058981,32.13674],[-84.889196,32.262709],[-85.004212,32.322956],[-84.960397,32.421541],[-85.069935,32.580372],[-85.184951,32.859696],[-85.431413,34.124869],[-85.606675,34.984749],[-84.319594,34.990226],[-83.618546,34.984749],[-83.109191,35.00118]]]}},
+ {"type":"Feature","id":"15","properties":{"name":"Hawaii"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-155.634835,18.948267],[-155.881297,19.035898],[-155.919636,19.123529],[-155.886774,19.348084],[-156.062036,19.73147],[-155.925113,19.857439],[-155.826528,20.032702],[-155.897728,20.147717],[-155.87582,20.26821],[-155.596496,20.12581],[-155.284311,20.021748],[-155.092618,19.868393],[-155.092618,19.736947],[-154.807817,19.523346],[-154.983079,19.348084],[-155.295265,19.26593],[-155.514342,19.134483],[-155.634835,18.948267]]],[[[-156.587823,21.029505],[-156.472807,20.892581],[-156.324929,20.952827],[-156.00179,20.793996],[-156.051082,20.651596],[-156.379699,20.580396],[-156.445422,20.60778],[-156.461853,20.783042],[-156.631638,20.821381],[-156.697361,20.919966],[-156.587823,21.029505]]],[[[-156.982162,21.210244],[-157.080747,21.106182],[-157.310779,21.106182],[-157.239579,21.221198],[-156.982162,21.210244]]],[[[-157.951581,21.697691],[-157.842042,21.462183],[-157.896811,21.325259],[-158.110412,21.303352],[-158.252813,21.582676],[-158.126843,21.588153],[-157.951581,21.697691]]],[[[-159.468693,22.228955],[-159.353678,22.218001],[-159.298908,22.113939],[-159.33177,21.966061],[-159.446786,21.872953],[-159.764448,21.987969],[-159.726109,22.152277],[-159.468693,22.228955]]]]}},
+ {"type":"Feature","id":"16","properties":{"name":"Idaho"},"geometry":{"type":"Polygon","coordinates":[[[-116.04751,49.000239],[-116.04751,47.976051],[-115.724371,47.696727],[-115.718894,47.42288],[-115.527201,47.302388],[-115.324554,47.258572],[-115.302646,47.187372],[-114.930214,46.919002],[-114.886399,46.809463],[-114.623506,46.705401],[-114.612552,46.639678],[-114.322274,46.645155],[-114.464674,46.272723],[-114.492059,46.037214],[-114.387997,45.88386],[-114.568736,45.774321],[-114.497536,45.670259],[-114.546828,45.560721],[-114.333228,45.456659],[-114.086765,45.593582],[-113.98818,45.703121],[-113.807441,45.604536],[-113.834826,45.522382],[-113.736241,45.330689],[-113.571933,45.128042],[-113.45144,45.056842],[-113.456917,44.865149],[-113.341901,44.782995],[-113.133778,44.772041],[-113.002331,44.448902],[-112.887315,44.394132],[-112.783254,44.48724],[-112.471068,44.481763],[-112.241036,44.569394],[-112.104113,44.520102],[-111.868605,44.563917],[-111.819312,44.509148],[-111.616665,44.547487],[-111.386634,44.75561],[-111.227803,44.580348],[-111.047063,44.476286],[-111.047063,42.000709],[-112.164359,41.995232],[-114.04295,41.995232],[-117.027882,42.000709],[-117.027882,43.830007],[-116.896436,44.158624],[-116.97859,44.240778],[-117.170283,44.257209],[-117.241483,44.394132],[-117.038836,44.750133],[-116.934774,44.782995],[-116.830713,44.930872],[-116.847143,45.02398],[-116.732128,45.144473],[-116.671881,45.319735],[-116.463758,45.61549],[-116.545912,45.752413],[-116.78142,45.823614],[-116.918344,45.993399],[-116.92382,46.168661],[-117.055267,46.343923],[-117.038836,46.426077],[-117.044313,47.762451],[-117.033359,49.000239],[-116.04751,49.000239]]]}},
+ {"type":"Feature","id":"17","properties":{"name":"Illinois"},"geometry":{"type":"Polygon","coordinates":[[[-90.639984,42.510065],[-88.788778,42.493634],[-87.802929,42.493634],[-87.83579,42.301941],[-87.682436,42.077386],[-87.523605,41.710431],[-87.529082,39.34987],[-87.63862,39.169131],[-87.512651,38.95553],[-87.49622,38.780268],[-87.62219,38.637868],[-87.655051,38.506421],[-87.83579,38.292821],[-87.950806,38.27639],[-87.923421,38.15042],[-88.000098,38.101128],[-88.060345,37.865619],[-88.027483,37.799896],[-88.15893,37.657496],[-88.065822,37.482234],[-88.476592,37.389126],[-88.514931,37.285064],[-88.421823,37.153617],[-88.547792,37.071463],[-88.914747,37.224817],[-89.029763,37.213863],[-89.183118,37.038601],[-89.133825,36.983832],[-89.292656,36.994786],[-89.517211,37.279587],[-89.435057,37.34531],[-89.517211,37.537003],[-89.517211,37.690357],[-89.84035,37.903958],[-89.949889,37.88205],[-90.059428,38.013497],[-90.355183,38.216144],[-90.349706,38.374975],[-90.179921,38.632391],[-90.207305,38.725499],[-90.10872,38.845992],[-90.251121,38.917192],[-90.470199,38.961007],[-90.585214,38.867899],[-90.661891,38.928146],[-90.727615,39.256762],[-91.061708,39.470363],[-91.368417,39.727779],[-91.494386,40.034488],[-91.50534,40.237135],[-91.417709,40.379535],[-91.401278,40.560274],[-91.121954,40.669813],[-91.09457,40.823167],[-90.963123,40.921752],[-90.946692,41.097014],[-91.111001,41.239415],[-91.045277,41.414677],[-90.656414,41.463969],[-90.344229,41.589939],[-90.311367,41.743293],[-90.179921,41.809016],[-90.141582,42.000709],[-90.168967,42.126679],[-90.393521,42.225264],[-90.420906,42.329326],[-90.639984,42.510065]]]}},
+ {"type":"Feature","id":"18","properties":{"name":"Indiana"},"geometry":{"type":"Polygon","coordinates":[[[-85.990061,41.759724],[-84.807042,41.759724],[-84.807042,41.694001],[-84.801565,40.500028],[-84.817996,39.103408],[-84.894673,39.059592],[-84.812519,38.785745],[-84.987781,38.780268],[-85.173997,38.68716],[-85.431413,38.730976],[-85.42046,38.533806],[-85.590245,38.451652],[-85.655968,38.325682],[-85.83123,38.27639],[-85.924338,38.024451],[-86.039354,37.958727],[-86.263908,38.051835],[-86.302247,38.166851],[-86.521325,38.040881],[-86.504894,37.931343],[-86.729448,37.893004],[-86.795172,37.991589],[-87.047111,37.893004],[-87.129265,37.788942],[-87.381204,37.93682],[-87.512651,37.903958],[-87.600282,37.975158],[-87.682436,37.903958],[-87.934375,37.893004],[-88.027483,37.799896],[-88.060345,37.865619],[-88.000098,38.101128],[-87.923421,38.15042],[-87.950806,38.27639],[-87.83579,38.292821],[-87.655051,38.506421],[-87.62219,38.637868],[-87.49622,38.780268],[-87.512651,38.95553],[-87.63862,39.169131],[-87.529082,39.34987],[-87.523605,41.710431],[-87.42502,41.644708],[-87.118311,41.644708],[-86.822556,41.759724],[-85.990061,41.759724]]]}},
+ {"type":"Feature","id":"19","properties":{"name":"Iowa"},"geometry":{"type":"Polygon","coordinates":[[[-91.368417,43.501391],[-91.215062,43.501391],[-91.204109,43.353514],[-91.056231,43.254929],[-91.176724,43.134436],[-91.143862,42.909881],[-91.067185,42.75105],[-90.711184,42.636034],[-90.639984,42.510065],[-90.420906,42.329326],[-90.393521,42.225264],[-90.168967,42.126679],[-90.141582,42.000709],[-90.179921,41.809016],[-90.311367,41.743293],[-90.344229,41.589939],[-90.656414,41.463969],[-91.045277,41.414677],[-91.111001,41.239415],[-90.946692,41.097014],[-90.963123,40.921752],[-91.09457,40.823167],[-91.121954,40.669813],[-91.401278,40.560274],[-91.417709,40.379535],[-91.527248,40.412397],[-91.729895,40.615043],[-91.833957,40.609566],[-93.257961,40.582182],[-94.632673,40.571228],[-95.7664,40.587659],[-95.881416,40.719105],[-95.826646,40.976521],[-95.925231,41.201076],[-95.919754,41.453015],[-96.095016,41.540646],[-96.122401,41.67757],[-96.062155,41.798063],[-96.127878,41.973325],[-96.264801,42.039048],[-96.44554,42.488157],[-96.631756,42.707235],[-96.544125,42.855112],[-96.511264,43.052282],[-96.434587,43.123482],[-96.560556,43.222067],[-96.527695,43.397329],[-96.582464,43.479483],[-96.451017,43.501391],[-91.368417,43.501391]]]}},
+ {"type":"Feature","id":"20","properties":{"name":"Kansas"},"geometry":{"type":"Polygon","coordinates":[[[-101.90605,40.001626],[-95.306337,40.001626],[-95.207752,39.908518],[-94.884612,39.831841],[-95.109167,39.541563],[-94.983197,39.442978],[-94.824366,39.20747],[-94.610765,39.158177],[-94.616242,37.000263],[-100.087706,37.000263],[-102.042974,36.994786],[-102.053927,40.001626],[-101.90605,40.001626]]]}},
+ {"type":"Feature","id":"21","properties":{"name":"Kentucky"},"geometry":{"type":"Polygon","coordinates":[[[-83.903347,38.769315],[-83.678792,38.632391],[-83.519961,38.703591],[-83.142052,38.626914],[-83.032514,38.725499],[-82.890113,38.758361],[-82.846298,38.588575],[-82.731282,38.561191],[-82.594358,38.424267],[-82.621743,38.123036],[-82.50125,37.931343],[-82.342419,37.783465],[-82.293127,37.668449],[-82.101434,37.553434],[-81.969987,37.537003],[-82.353373,37.268633],[-82.720328,37.120755],[-82.720328,37.044078],[-82.868205,36.978355],[-82.879159,36.890724],[-83.070852,36.852385],[-83.136575,36.742847],[-83.673316,36.600446],[-83.689746,36.584015],[-84.544149,36.594969],[-85.289013,36.627831],[-85.486183,36.616877],[-86.592525,36.655216],[-87.852221,36.633308],[-88.071299,36.677123],[-88.054868,36.496384],[-89.298133,36.507338],[-89.418626,36.496384],[-89.363857,36.622354],[-89.215979,36.578538],[-89.133825,36.983832],[-89.183118,37.038601],[-89.029763,37.213863],[-88.914747,37.224817],[-88.547792,37.071463],[-88.421823,37.153617],[-88.514931,37.285064],[-88.476592,37.389126],[-88.065822,37.482234],[-88.15893,37.657496],[-88.027483,37.799896],[-87.934375,37.893004],[-87.682436,37.903958],[-87.600282,37.975158],[-87.512651,37.903958],[-87.381204,37.93682],[-87.129265,37.788942],[-87.047111,37.893004],[-86.795172,37.991589],[-86.729448,37.893004],[-86.504894,37.931343],[-86.521325,38.040881],[-86.302247,38.166851],[-86.263908,38.051835],[-86.039354,37.958727],[-85.924338,38.024451],[-85.83123,38.27639],[-85.655968,38.325682],[-85.590245,38.451652],[-85.42046,38.533806],[-85.431413,38.730976],[-85.173997,38.68716],[-84.987781,38.780268],[-84.812519,38.785745],[-84.894673,39.059592],[-84.817996,39.103408],[-84.43461,39.103408],[-84.231963,38.895284],[-84.215533,38.807653],[-83.903347,38.769315]]]}},
+ {"type":"Feature","id":"22","properties":{"name":"Louisiana"},"geometry":{"type":"Polygon","coordinates":[[[-93.608485,33.018527],[-91.16577,33.002096],[-91.072662,32.887081],[-91.143862,32.843265],[-91.154816,32.640618],[-91.006939,32.514649],[-90.985031,32.218894],[-91.105524,31.988862],[-91.341032,31.846462],[-91.401278,31.621907],[-91.499863,31.643815],[-91.516294,31.27686],[-91.636787,31.265906],[-91.565587,31.068736],[-91.636787,30.997536],[-89.747242,30.997536],[-89.845827,30.66892],[-89.681519,30.449842],[-89.643181,30.285534],[-89.522688,30.181472],[-89.818443,30.044549],[-89.84035,29.945964],[-89.599365,29.88024],[-89.495303,30.039072],[-89.287179,29.88024],[-89.30361,29.754271],[-89.424103,29.699501],[-89.648657,29.748794],[-89.621273,29.655686],[-89.69795,29.513285],[-89.506257,29.387316],[-89.199548,29.348977],[-89.09001,29.2011],[-89.002379,29.179192],[-89.16121,29.009407],[-89.336472,29.042268],[-89.484349,29.217531],[-89.851304,29.310638],[-89.851304,29.480424],[-90.032043,29.425654],[-90.021089,29.283254],[-90.103244,29.151807],[-90.23469,29.129899],[-90.333275,29.277777],[-90.563307,29.283254],[-90.645461,29.129899],[-90.798815,29.086084],[-90.963123,29.179192],[-91.09457,29.190146],[-91.220539,29.436608],[-91.445094,29.546147],[-91.532725,29.529716],[-91.620356,29.73784],[-91.883249,29.710455],[-91.888726,29.836425],[-92.146142,29.715932],[-92.113281,29.622824],[-92.31045,29.535193],[-92.617159,29.579009],[-92.97316,29.715932],[-93.2251,29.776178],[-93.767317,29.726886],[-93.838517,29.688547],[-93.926148,29.787132],[-93.690639,30.143133],[-93.767317,30.334826],[-93.696116,30.438888],[-93.728978,30.575812],[-93.630393,30.679874],[-93.526331,30.93729],[-93.542762,31.15089],[-93.816609,31.556184],[-93.822086,31.775262],[-94.041164,31.994339],[-94.041164,33.018527],[-93.608485,33.018527]]]}},
+ {"type":"Feature","id":"23","properties":{"name":"Maine"},"geometry":{"type":"Polygon","coordinates":[[[-70.703921,43.057759],[-70.824413,43.128959],[-70.807983,43.227544],[-70.966814,43.34256],[-71.032537,44.657025],[-71.08183,45.303304],[-70.649151,45.440228],[-70.720352,45.511428],[-70.556043,45.664782],[-70.386258,45.735983],[-70.41912,45.796229],[-70.260289,45.889337],[-70.309581,46.064599],[-70.210996,46.327492],[-70.057642,46.415123],[-69.997395,46.694447],[-69.225147,47.461219],[-69.044408,47.428357],[-69.033454,47.242141],[-68.902007,47.176418],[-68.578868,47.285957],[-68.376221,47.285957],[-68.233821,47.357157],[-67.954497,47.198326],[-67.790188,47.066879],[-67.779235,45.944106],[-67.801142,45.675736],[-67.456095,45.604536],[-67.505388,45.48952],[-67.417757,45.379982],[-67.488957,45.281397],[-67.346556,45.128042],[-67.16034,45.160904],[-66.979601,44.804903],[-67.187725,44.646072],[-67.308218,44.706318],[-67.406803,44.596779],[-67.549203,44.624164],[-67.565634,44.531056],[-67.75185,44.54201],[-68.047605,44.328409],[-68.118805,44.476286],[-68.222867,44.48724],[-68.173574,44.328409],[-68.403606,44.251732],[-68.458375,44.377701],[-68.567914,44.311978],[-68.82533,44.311978],[-68.830807,44.459856],[-68.984161,44.426994],[-68.956777,44.322932],[-69.099177,44.103854],[-69.071793,44.043608],[-69.258008,43.923115],[-69.444224,43.966931],[-69.553763,43.840961],[-69.707118,43.82453],[-69.833087,43.720469],[-69.986442,43.742376],[-70.030257,43.851915],[-70.254812,43.676653],[-70.194565,43.567114],[-70.358873,43.528776],[-70.369827,43.435668],[-70.556043,43.320652],[-70.703921,43.057759]]]}},
+ {"type":"Feature","id":"24","properties":{"name":"Maryland"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-75.994645,37.95325],[-76.016553,37.95325],[-76.043938,37.95325],[-75.994645,37.95325]]],[[[-79.477979,39.722302],[-75.786521,39.722302],[-75.693413,38.462606],[-75.047134,38.451652],[-75.244304,38.029928],[-75.397659,38.013497],[-75.671506,37.95325],[-75.885106,37.909435],[-75.879629,38.073743],[-75.961783,38.139466],[-75.846768,38.210667],[-76.000122,38.374975],[-76.049415,38.303775],[-76.257538,38.320205],[-76.328738,38.500944],[-76.263015,38.500944],[-76.257538,38.736453],[-76.191815,38.829561],[-76.279446,39.147223],[-76.169907,39.333439],[-76.000122,39.366301],[-75.972737,39.557994],[-76.098707,39.536086],[-76.104184,39.437501],[-76.367077,39.311532],[-76.443754,39.196516],[-76.460185,38.906238],[-76.55877,38.769315],[-76.514954,38.539283],[-76.383508,38.380452],[-76.399939,38.259959],[-76.317785,38.139466],[-76.3616,38.057312],[-76.591632,38.216144],[-76.920248,38.292821],[-77.018833,38.446175],[-77.205049,38.358544],[-77.276249,38.479037],[-77.128372,38.632391],[-77.040741,38.791222],[-76.909294,38.895284],[-77.035264,38.993869],[-77.117418,38.933623],[-77.248864,39.026731],[-77.456988,39.076023],[-77.456988,39.223901],[-77.566527,39.306055],[-77.719881,39.322485],[-77.834897,39.601809],[-78.004682,39.601809],[-78.174467,39.694917],[-78.267575,39.61824],[-78.431884,39.623717],[-78.470222,39.514178],[-78.765977,39.585379],[-78.963147,39.437501],[-79.094593,39.470363],[-79.291763,39.300578],[-79.488933,39.20747],[-79.477979,39.722302]]]]}},
+ {"type":"Feature","id":"25","properties":{"name":"Massachusetts"},"geometry":{"type":"Polygon","coordinates":[[[-70.917521,42.887974],[-70.818936,42.871543],[-70.780598,42.696281],[-70.824413,42.55388],[-70.983245,42.422434],[-70.988722,42.269079],[-70.769644,42.247172],[-70.638197,42.08834],[-70.660105,41.962371],[-70.550566,41.929509],[-70.539613,41.814493],[-70.260289,41.715908],[-69.937149,41.809016],[-70.008349,41.672093],[-70.484843,41.5516],[-70.660105,41.546123],[-70.764167,41.639231],[-70.928475,41.611847],[-70.933952,41.540646],[-71.120168,41.496831],[-71.196845,41.67757],[-71.22423,41.710431],[-71.328292,41.781632],[-71.383061,42.01714],[-71.530939,42.01714],[-71.799309,42.006186],[-71.799309,42.022617],[-73.053528,42.039048],[-73.486206,42.050002],[-73.508114,42.08834],[-73.267129,42.745573],[-72.456542,42.729142],[-71.29543,42.696281],[-71.185891,42.789389],[-70.917521,42.887974]]]}},
+ {"type":"Feature","id":"26","properties":{"name":"Michigan"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-83.454238,41.732339],[-84.807042,41.694001],[-84.807042,41.759724],[-85.990061,41.759724],[-86.822556,41.759724],[-86.619909,41.891171],[-86.482986,42.115725],[-86.357016,42.252649],[-86.263908,42.444341],[-86.209139,42.718189],[-86.231047,43.013943],[-86.526801,43.594499],[-86.433693,43.813577],[-86.499417,44.07647],[-86.269385,44.34484],[-86.220093,44.569394],[-86.252954,44.689887],[-86.088646,44.73918],[-86.066738,44.903488],[-85.809322,44.947303],[-85.612152,45.128042],[-85.628583,44.766564],[-85.524521,44.750133],[-85.393075,44.930872],[-85.387598,45.237581],[-85.305444,45.314258],[-85.031597,45.363551],[-85.119228,45.577151],[-84.938489,45.75789],[-84.713934,45.768844],[-84.461995,45.653829],[-84.215533,45.637398],[-84.09504,45.494997],[-83.908824,45.484043],[-83.596638,45.352597],[-83.4871,45.358074],[-83.317314,45.144473],[-83.454238,45.029457],[-83.322791,44.88158],[-83.273499,44.711795],[-83.333745,44.339363],[-83.536392,44.246255],[-83.585684,44.054562],[-83.82667,43.988839],[-83.958116,43.758807],[-83.908824,43.671176],[-83.667839,43.589022],[-83.481623,43.714992],[-83.262545,43.972408],[-82.917498,44.070993],[-82.747713,43.994316],[-82.643651,43.851915],[-82.539589,43.435668],[-82.523158,43.227544],[-82.413619,42.975605],[-82.517681,42.614127],[-82.681989,42.559357],[-82.687466,42.690804],[-82.797005,42.652465],[-82.922975,42.351234],[-83.125621,42.236218],[-83.185868,42.006186],[-83.437807,41.814493],[-83.454238,41.732339]]],[[[-85.508091,45.730506],[-85.49166,45.610013],[-85.623106,45.588105],[-85.568337,45.75789],[-85.508091,45.730506]]],[[[-87.589328,45.095181],[-87.742682,45.199243],[-87.649574,45.341643],[-87.885083,45.363551],[-87.791975,45.500474],[-87.781021,45.675736],[-87.989145,45.796229],[-88.10416,45.922199],[-88.531362,46.020784],[-88.662808,45.987922],[-89.09001,46.135799],[-90.119674,46.338446],[-90.229213,46.508231],[-90.415429,46.568478],[-90.026566,46.672539],[-89.851304,46.793032],[-89.413149,46.842325],[-89.128348,46.990202],[-88.996902,46.995679],[-88.887363,47.099741],[-88.575177,47.247618],[-88.416346,47.373588],[-88.180837,47.455742],[-87.956283,47.384542],[-88.350623,47.077833],[-88.443731,46.973771],[-88.438254,46.787555],[-88.246561,46.929956],[-87.901513,46.908048],[-87.633143,46.809463],[-87.392158,46.535616],[-87.260711,46.486323],[-87.008772,46.530139],[-86.948526,46.469893],[-86.696587,46.437031],[-86.159846,46.667063],[-85.880522,46.68897],[-85.508091,46.678016],[-85.256151,46.754694],[-85.064458,46.760171],[-85.02612,46.480847],[-84.82895,46.442508],[-84.63178,46.486323],[-84.549626,46.4206],[-84.418179,46.502754],[-84.127902,46.530139],[-84.122425,46.179615],[-83.990978,46.031737],[-83.793808,45.993399],[-83.7719,46.091984],[-83.580208,46.091984],[-83.476146,45.987922],[-83.563777,45.911245],[-84.111471,45.976968],[-84.374364,45.933153],[-84.659165,46.053645],[-84.741319,45.944106],[-84.70298,45.850998],[-84.82895,45.872906],[-85.015166,46.00983],[-85.338305,46.091984],[-85.502614,46.097461],[-85.661445,45.966014],[-85.924338,45.933153],[-86.209139,45.960537],[-86.324155,45.905768],[-86.351539,45.796229],[-86.663725,45.703121],[-86.647294,45.834568],[-86.784218,45.861952],[-86.838987,45.725029],[-87.069019,45.719552],[-87.17308,45.659305],[-87.326435,45.423797],[-87.611236,45.122565],[-87.589328,45.095181]]],[[[-88.805209,47.976051],[-89.057148,47.850082],[-89.188594,47.833651],[-89.177641,47.937713],[-88.547792,48.173221],[-88.668285,48.008913],[-88.805209,47.976051]]]]}},
+ {"type":"Feature","id":"27","properties":{"name":"Minnesota"},"geometry":{"type":"Polygon","coordinates":[[[-92.014696,46.705401],[-92.091373,46.749217],[-92.29402,46.667063],[-92.29402,46.075553],[-92.354266,46.015307],[-92.639067,45.933153],[-92.869098,45.719552],[-92.885529,45.577151],[-92.770513,45.566198],[-92.644544,45.440228],[-92.75956,45.286874],[-92.737652,45.117088],[-92.808852,44.750133],[-92.545959,44.569394],[-92.337835,44.552964],[-92.233773,44.443425],[-91.927065,44.333886],[-91.877772,44.202439],[-91.592971,44.032654],[-91.43414,43.994316],[-91.242447,43.775238],[-91.269832,43.616407],[-91.215062,43.501391],[-91.368417,43.501391],[-96.451017,43.501391],[-96.451017,45.297827],[-96.681049,45.412843],[-96.856311,45.604536],[-96.582464,45.818137],[-96.560556,45.933153],[-96.598895,46.332969],[-96.719387,46.437031],[-96.801542,46.656109],[-96.785111,46.924479],[-96.823449,46.968294],[-96.856311,47.609096],[-97.053481,47.948667],[-97.130158,48.140359],[-97.16302,48.545653],[-97.097296,48.682577],[-97.228743,49.000239],[-95.152983,49.000239],[-95.152983,49.383625],[-94.955813,49.372671],[-94.824366,49.295994],[-94.69292,48.775685],[-94.588858,48.715438],[-94.260241,48.699007],[-94.221903,48.649715],[-93.838517,48.627807],[-93.794701,48.518268],[-93.466085,48.545653],[-93.466085,48.589469],[-93.208669,48.644238],[-92.984114,48.62233],[-92.726698,48.540176],[-92.655498,48.436114],[-92.50762,48.447068],[-92.370697,48.222514],[-92.304974,48.315622],[-92.053034,48.359437],[-92.009219,48.266329],[-91.713464,48.200606],[-91.713464,48.112975],[-91.565587,48.041775],[-91.264355,48.080113],[-91.083616,48.178698],[-90.837154,48.238944],[-90.749522,48.091067],[-90.579737,48.123929],[-90.377091,48.091067],[-90.141582,48.112975],[-89.873212,47.987005],[-89.615796,48.008913],[-89.637704,47.954144],[-89.971797,47.828174],[-90.437337,47.729589],[-90.738569,47.625527],[-91.171247,47.368111],[-91.357463,47.20928],[-91.642264,47.028541],[-92.091373,46.787555],[-92.014696,46.705401]]]}},
+ {"type":"Feature","id":"28","properties":{"name":"Mississippi"},"geometry":{"type":"Polygon","coordinates":[[[-88.471115,34.995703],[-88.202745,34.995703],[-88.098683,34.891641],[-88.241084,33.796253],[-88.471115,31.895754],[-88.394438,30.367688],[-88.503977,30.323872],[-88.744962,30.34578],[-88.843547,30.411504],[-89.084533,30.367688],[-89.418626,30.252672],[-89.522688,30.181472],[-89.643181,30.285534],[-89.681519,30.449842],[-89.845827,30.66892],[-89.747242,30.997536],[-91.636787,30.997536],[-91.565587,31.068736],[-91.636787,31.265906],[-91.516294,31.27686],[-91.499863,31.643815],[-91.401278,31.621907],[-91.341032,31.846462],[-91.105524,31.988862],[-90.985031,32.218894],[-91.006939,32.514649],[-91.154816,32.640618],[-91.143862,32.843265],[-91.072662,32.887081],[-91.16577,33.002096],[-91.089093,33.13902],[-91.143862,33.347144],[-91.056231,33.429298],[-91.231493,33.560744],[-91.072662,33.867453],[-90.891923,34.026284],[-90.952169,34.135823],[-90.744046,34.300131],[-90.749522,34.365854],[-90.568783,34.420624],[-90.585214,34.617794],[-90.481152,34.661609],[-90.409952,34.831394],[-90.251121,34.908072],[-90.311367,34.995703],[-88.471115,34.995703]]]}},
+ {"type":"Feature","id":"29","properties":{"name":"Missouri"},"geometry":{"type":"Polygon","coordinates":[[[-91.833957,40.609566],[-91.729895,40.615043],[-91.527248,40.412397],[-91.417709,40.379535],[-91.50534,40.237135],[-91.494386,40.034488],[-91.368417,39.727779],[-91.061708,39.470363],[-90.727615,39.256762],[-90.661891,38.928146],[-90.585214,38.867899],[-90.470199,38.961007],[-90.251121,38.917192],[-90.10872,38.845992],[-90.207305,38.725499],[-90.179921,38.632391],[-90.349706,38.374975],[-90.355183,38.216144],[-90.059428,38.013497],[-89.949889,37.88205],[-89.84035,37.903958],[-89.517211,37.690357],[-89.517211,37.537003],[-89.435057,37.34531],[-89.517211,37.279587],[-89.292656,36.994786],[-89.133825,36.983832],[-89.215979,36.578538],[-89.363857,36.622354],[-89.418626,36.496384],[-89.484349,36.496384],[-89.539119,36.496384],[-89.533642,36.249922],[-89.730812,35.997983],[-90.377091,35.997983],[-90.218259,36.184199],[-90.064905,36.304691],[-90.152536,36.496384],[-94.473842,36.501861],[-94.616242,36.501861],[-94.616242,37.000263],[-94.610765,39.158177],[-94.824366,39.20747],[-94.983197,39.442978],[-95.109167,39.541563],[-94.884612,39.831841],[-95.207752,39.908518],[-95.306337,40.001626],[-95.552799,40.264519],[-95.7664,40.587659],[-94.632673,40.571228],[-93.257961,40.582182],[-91.833957,40.609566]]]}},
+ {"type":"Feature","id":"30","properties":{"name":"Montana"},"geometry":{"type":"Polygon","coordinates":[[[-104.047534,49.000239],[-104.042057,47.861036],[-104.047534,45.944106],[-104.042057,44.996596],[-104.058488,44.996596],[-105.91517,45.002073],[-109.080842,45.002073],[-111.05254,45.002073],[-111.047063,44.476286],[-111.227803,44.580348],[-111.386634,44.75561],[-111.616665,44.547487],[-111.819312,44.509148],[-111.868605,44.563917],[-112.104113,44.520102],[-112.241036,44.569394],[-112.471068,44.481763],[-112.783254,44.48724],[-112.887315,44.394132],[-113.002331,44.448902],[-113.133778,44.772041],[-113.341901,44.782995],[-113.456917,44.865149],[-113.45144,45.056842],[-113.571933,45.128042],[-113.736241,45.330689],[-113.834826,45.522382],[-113.807441,45.604536],[-113.98818,45.703121],[-114.086765,45.593582],[-114.333228,45.456659],[-114.546828,45.560721],[-114.497536,45.670259],[-114.568736,45.774321],[-114.387997,45.88386],[-114.492059,46.037214],[-114.464674,46.272723],[-114.322274,46.645155],[-114.612552,46.639678],[-114.623506,46.705401],[-114.886399,46.809463],[-114.930214,46.919002],[-115.302646,47.187372],[-115.324554,47.258572],[-115.527201,47.302388],[-115.718894,47.42288],[-115.724371,47.696727],[-116.04751,47.976051],[-116.04751,49.000239],[-111.50165,48.994762],[-109.453274,49.000239],[-104.047534,49.000239]]]}},
+ {"type":"Feature","id":"31","properties":{"name":"Nebraska"},"geometry":{"type":"Polygon","coordinates":[[[-103.324578,43.002989],[-101.626726,42.997512],[-98.499393,42.997512],[-98.466531,42.94822],[-97.951699,42.767481],[-97.831206,42.866066],[-97.688806,42.844158],[-97.217789,42.844158],[-96.692003,42.657942],[-96.626279,42.515542],[-96.44554,42.488157],[-96.264801,42.039048],[-96.127878,41.973325],[-96.062155,41.798063],[-96.122401,41.67757],[-96.095016,41.540646],[-95.919754,41.453015],[-95.925231,41.201076],[-95.826646,40.976521],[-95.881416,40.719105],[-95.7664,40.587659],[-95.552799,40.264519],[-95.306337,40.001626],[-101.90605,40.001626],[-102.053927,40.001626],[-102.053927,41.003906],[-104.053011,41.003906],[-104.053011,43.002989],[-103.324578,43.002989]]]}},
+ {"type":"Feature","id":"32","properties":{"name":"Nevada"},"geometry":{"type":"Polygon","coordinates":[[[-117.027882,42.000709],[-114.04295,41.995232],[-114.048427,37.000263],[-114.048427,36.195153],[-114.152489,36.025367],[-114.251074,36.01989],[-114.371566,36.140383],[-114.738521,36.102045],[-114.678275,35.516012],[-114.596121,35.324319],[-114.574213,35.138103],[-114.634459,35.00118],[-115.85034,35.970598],[-116.540435,36.501861],[-117.498899,37.21934],[-118.71478,38.101128],[-120.001861,38.999346],[-119.996384,40.264519],[-120.001861,41.995232],[-118.698349,41.989755],[-117.027882,42.000709]]]}},
+ {"type":"Feature","id":"33","properties":{"name":"New Hampshire"},"geometry":{"type":"Polygon","coordinates":[[[-71.08183,45.303304],[-71.032537,44.657025],[-70.966814,43.34256],[-70.807983,43.227544],[-70.824413,43.128959],[-70.703921,43.057759],[-70.818936,42.871543],[-70.917521,42.887974],[-71.185891,42.789389],[-71.29543,42.696281],[-72.456542,42.729142],[-72.544173,42.80582],[-72.533219,42.953697],[-72.445588,43.008466],[-72.456542,43.150867],[-72.379864,43.572591],[-72.204602,43.769761],[-72.116971,43.994316],[-72.02934,44.07647],[-72.034817,44.322932],[-71.700724,44.41604],[-71.536416,44.585825],[-71.629524,44.750133],[-71.4926,44.914442],[-71.503554,45.013027],[-71.361154,45.270443],[-71.131122,45.243058],[-71.08183,45.303304]]]}},
+ {"type":"Feature","id":"34","properties":{"name":"New Jersey"},"geometry":{"type":"Polygon","coordinates":[[[-74.236547,41.14083],[-73.902454,40.998429],[-74.022947,40.708151],[-74.187255,40.642428],[-74.274886,40.489074],[-74.001039,40.412397],[-73.979131,40.297381],[-74.099624,39.760641],[-74.411809,39.360824],[-74.614456,39.245808],[-74.795195,38.993869],[-74.888303,39.158177],[-75.178581,39.240331],[-75.534582,39.459409],[-75.55649,39.607286],[-75.561967,39.629194],[-75.507197,39.683964],[-75.414089,39.804456],[-75.145719,39.88661],[-75.129289,39.963288],[-74.82258,40.127596],[-74.773287,40.215227],[-75.058088,40.417874],[-75.069042,40.543843],[-75.195012,40.576705],[-75.205966,40.691721],[-75.052611,40.866983],[-75.134765,40.971045],[-74.882826,41.179168],[-74.828057,41.288707],[-74.69661,41.359907],[-74.236547,41.14083]]]}},
+ {"type":"Feature","id":"35","properties":{"name":"New Mexico"},"geometry":{"type":"Polygon","coordinates":[[[-107.421329,37.000263],[-106.868158,36.994786],[-104.337812,36.994786],[-103.001438,37.000263],[-103.001438,36.501861],[-103.039777,36.501861],[-103.045254,34.01533],[-103.067161,33.002096],[-103.067161,31.999816],[-106.616219,31.999816],[-106.643603,31.901231],[-106.528588,31.786216],[-108.210008,31.786216],[-108.210008,31.331629],[-109.04798,31.331629],[-109.042503,37.000263],[-107.421329,37.000263]]]}},
+ {"type":"Feature","id":"36","properties":{"name":"New York"},"geometry":{"type":"Polygon","coordinates":[[[-73.343806,45.013027],[-73.332852,44.804903],[-73.387622,44.618687],[-73.294514,44.437948],[-73.321898,44.246255],[-73.436914,44.043608],[-73.349283,43.769761],[-73.404052,43.687607],[-73.245221,43.523299],[-73.278083,42.833204],[-73.267129,42.745573],[-73.508114,42.08834],[-73.486206,42.050002],[-73.55193,41.294184],[-73.48073,41.21203],[-73.727192,41.102491],[-73.655992,40.987475],[-73.22879,40.905321],[-73.141159,40.965568],[-72.774204,40.965568],[-72.587988,40.998429],[-72.28128,41.157261],[-72.259372,41.042245],[-72.100541,40.992952],[-72.467496,40.845075],[-73.239744,40.625997],[-73.562884,40.582182],[-73.776484,40.593136],[-73.935316,40.543843],[-74.022947,40.708151],[-73.902454,40.998429],[-74.236547,41.14083],[-74.69661,41.359907],[-74.740426,41.431108],[-74.89378,41.436584],[-75.074519,41.60637],[-75.052611,41.754247],[-75.173104,41.869263],[-75.249781,41.863786],[-75.35932,42.000709],[-79.76278,42.000709],[-79.76278,42.252649],[-79.76278,42.269079],[-79.149363,42.55388],[-79.050778,42.690804],[-78.853608,42.783912],[-78.930285,42.953697],[-79.012439,42.986559],[-79.072686,43.260406],[-78.486653,43.375421],[-77.966344,43.369944],[-77.75822,43.34256],[-77.533665,43.233021],[-77.391265,43.276836],[-76.958587,43.271359],[-76.695693,43.34256],[-76.41637,43.523299],[-76.235631,43.528776],[-76.230154,43.802623],[-76.137046,43.961454],[-76.3616,44.070993],[-76.312308,44.196962],[-75.912491,44.366748],[-75.764614,44.514625],[-75.282643,44.848718],[-74.828057,45.018503],[-74.148916,44.991119],[-73.343806,45.013027]]]}},
+ {"type":"Feature","id":"37","properties":{"name":"North Carolina"},"geometry":{"type":"Polygon","coordinates":[[[-80.978661,36.562108],[-80.294043,36.545677],[-79.510841,36.5402],[-75.868676,36.551154],[-75.75366,36.151337],[-76.032984,36.189676],[-76.071322,36.140383],[-76.410893,36.080137],[-76.460185,36.025367],[-76.68474,36.008937],[-76.673786,35.937736],[-76.399939,35.987029],[-76.3616,35.943213],[-76.060368,35.992506],[-75.961783,35.899398],[-75.781044,35.937736],[-75.715321,35.696751],[-75.775568,35.581735],[-75.89606,35.570781],[-76.147999,35.324319],[-76.482093,35.313365],[-76.536862,35.14358],[-76.394462,34.973795],[-76.279446,34.940933],[-76.493047,34.661609],[-76.673786,34.694471],[-76.991448,34.667086],[-77.210526,34.60684],[-77.555573,34.415147],[-77.82942,34.163208],[-77.971821,33.845545],[-78.179944,33.916745],[-78.541422,33.851022],[-79.675149,34.80401],[-80.797922,34.820441],[-80.781491,34.935456],[-80.934845,35.105241],[-81.038907,35.044995],[-81.044384,35.149057],[-82.276696,35.198349],[-82.550543,35.160011],[-82.764143,35.066903],[-83.109191,35.00118],[-83.618546,34.984749],[-84.319594,34.990226],[-84.29221,35.225734],[-84.09504,35.247642],[-84.018363,35.41195],[-83.7719,35.559827],[-83.498053,35.565304],[-83.251591,35.718659],[-82.994175,35.773428],[-82.775097,35.997983],[-82.638174,36.063706],[-82.610789,35.965121],[-82.216449,36.156814],[-82.03571,36.118475],[-81.909741,36.304691],[-81.723525,36.353984],[-81.679709,36.589492],[-80.978661,36.562108]]]}},
+ {"type":"Feature","id":"38","properties":{"name":"North Dakota"},"geometry":{"type":"Polygon","coordinates":[[[-97.228743,49.000239],[-97.097296,48.682577],[-97.16302,48.545653],[-97.130158,48.140359],[-97.053481,47.948667],[-96.856311,47.609096],[-96.823449,46.968294],[-96.785111,46.924479],[-96.801542,46.656109],[-96.719387,46.437031],[-96.598895,46.332969],[-96.560556,45.933153],[-104.047534,45.944106],[-104.042057,47.861036],[-104.047534,49.000239],[-97.228743,49.000239]]]}},
+ {"type":"Feature","id":"39","properties":{"name":"Ohio"},"geometry":{"type":"Polygon","coordinates":[[[-80.518598,41.978802],[-80.518598,40.636951],[-80.666475,40.582182],[-80.595275,40.472643],[-80.600752,40.319289],[-80.737675,40.078303],[-80.830783,39.711348],[-81.219646,39.388209],[-81.345616,39.344393],[-81.455155,39.410117],[-81.57017,39.267716],[-81.685186,39.273193],[-81.811156,39.0815],[-81.783771,38.966484],[-81.887833,38.873376],[-82.03571,39.026731],[-82.221926,38.785745],[-82.172634,38.632391],[-82.293127,38.577622],[-82.331465,38.446175],[-82.594358,38.424267],[-82.731282,38.561191],[-82.846298,38.588575],[-82.890113,38.758361],[-83.032514,38.725499],[-83.142052,38.626914],[-83.519961,38.703591],[-83.678792,38.632391],[-83.903347,38.769315],[-84.215533,38.807653],[-84.231963,38.895284],[-84.43461,39.103408],[-84.817996,39.103408],[-84.801565,40.500028],[-84.807042,41.694001],[-83.454238,41.732339],[-83.065375,41.595416],[-82.933929,41.513262],[-82.835344,41.589939],[-82.616266,41.431108],[-82.479343,41.381815],[-82.013803,41.513262],[-81.739956,41.485877],[-81.444201,41.672093],[-81.011523,41.852832],[-80.518598,41.978802],[-80.518598,41.978802]]]}},
+ {"type":"Feature","id":"40","properties":{"name":"Oklahoma"},"geometry":{"type":"Polygon","coordinates":[[[-100.087706,37.000263],[-94.616242,37.000263],[-94.616242,36.501861],[-94.430026,35.395519],[-94.484796,33.637421],[-94.868182,33.74696],[-94.966767,33.861976],[-95.224183,33.960561],[-95.289906,33.87293],[-95.547322,33.878407],[-95.602092,33.933176],[-95.8376,33.834591],[-95.936185,33.889361],[-96.149786,33.840068],[-96.346956,33.686714],[-96.423633,33.774345],[-96.631756,33.845545],[-96.850834,33.845545],[-96.922034,33.960561],[-97.173974,33.736006],[-97.256128,33.861976],[-97.371143,33.823637],[-97.458774,33.905791],[-97.694283,33.982469],[-97.869545,33.851022],[-97.946222,33.987946],[-98.088623,34.004376],[-98.170777,34.113915],[-98.36247,34.157731],[-98.488439,34.064623],[-98.570593,34.146777],[-98.767763,34.135823],[-98.986841,34.223454],[-99.189488,34.2125],[-99.260688,34.404193],[-99.57835,34.415147],[-99.698843,34.382285],[-99.923398,34.573978],[-100.000075,34.563024],[-100.000075,36.501861],[-101.812942,36.501861],[-103.001438,36.501861],[-103.001438,37.000263],[-102.042974,36.994786],[-100.087706,37.000263]]]}},
+ {"type":"Feature","id":"41","properties":{"name":"Oregon"},"geometry":{"type":"Polygon","coordinates":[[[-123.211348,46.174138],[-123.11824,46.185092],[-122.904639,46.08103],[-122.811531,45.960537],[-122.762239,45.659305],[-122.247407,45.549767],[-121.809251,45.708598],[-121.535404,45.725029],[-121.217742,45.670259],[-121.18488,45.604536],[-120.637186,45.746937],[-120.505739,45.697644],[-120.209985,45.725029],[-119.963522,45.823614],[-119.525367,45.911245],[-119.125551,45.933153],[-118.988627,45.998876],[-116.918344,45.993399],[-116.78142,45.823614],[-116.545912,45.752413],[-116.463758,45.61549],[-116.671881,45.319735],[-116.732128,45.144473],[-116.847143,45.02398],[-116.830713,44.930872],[-116.934774,44.782995],[-117.038836,44.750133],[-117.241483,44.394132],[-117.170283,44.257209],[-116.97859,44.240778],[-116.896436,44.158624],[-117.027882,43.830007],[-117.027882,42.000709],[-118.698349,41.989755],[-120.001861,41.995232],[-121.037003,41.995232],[-122.378853,42.011663],[-123.233256,42.006186],[-124.213628,42.000709],[-124.356029,42.115725],[-124.432706,42.438865],[-124.416275,42.663419],[-124.553198,42.838681],[-124.454613,43.002989],[-124.383413,43.271359],[-124.235536,43.55616],[-124.169813,43.8081],[-124.060274,44.657025],[-124.076705,44.772041],[-123.97812,45.144473],[-123.939781,45.659305],[-123.994551,45.944106],[-123.945258,46.113892],[-123.545441,46.261769],[-123.370179,46.146753],[-123.211348,46.174138]]]}},
+ {"type":"Feature","id":"42","properties":{"name":"Pennsylvania"},"geometry":{"type":"Polygon","coordinates":[[[-79.76278,42.252649],[-79.76278,42.000709],[-75.35932,42.000709],[-75.249781,41.863786],[-75.173104,41.869263],[-75.052611,41.754247],[-75.074519,41.60637],[-74.89378,41.436584],[-74.740426,41.431108],[-74.69661,41.359907],[-74.828057,41.288707],[-74.882826,41.179168],[-75.134765,40.971045],[-75.052611,40.866983],[-75.205966,40.691721],[-75.195012,40.576705],[-75.069042,40.543843],[-75.058088,40.417874],[-74.773287,40.215227],[-74.82258,40.127596],[-75.129289,39.963288],[-75.145719,39.88661],[-75.414089,39.804456],[-75.616736,39.831841],[-75.786521,39.722302],[-79.477979,39.722302],[-80.518598,39.722302],[-80.518598,40.636951],[-80.518598,41.978802],[-80.518598,41.978802],[-80.332382,42.033571],[-79.76278,42.269079],[-79.76278,42.252649]]]}},
+ {"type":"Feature","id":"44","properties":{"name":"Rhode Island"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-71.196845,41.67757],[-71.120168,41.496831],[-71.317338,41.474923],[-71.196845,41.67757]]],[[[-71.530939,42.01714],[-71.383061,42.01714],[-71.328292,41.781632],[-71.22423,41.710431],[-71.344723,41.726862],[-71.448785,41.578985],[-71.481646,41.370861],[-71.859555,41.321569],[-71.799309,41.414677],[-71.799309,42.006186],[-71.530939,42.01714]]]]}},
+ {"type":"Feature","id":"45","properties":{"name":"South Carolina"},"geometry":{"type":"Polygon","coordinates":[[[-82.764143,35.066903],[-82.550543,35.160011],[-82.276696,35.198349],[-81.044384,35.149057],[-81.038907,35.044995],[-80.934845,35.105241],[-80.781491,34.935456],[-80.797922,34.820441],[-79.675149,34.80401],[-78.541422,33.851022],[-78.716684,33.80173],[-78.935762,33.637421],[-79.149363,33.380005],[-79.187701,33.171881],[-79.357487,33.007573],[-79.582041,33.007573],[-79.631334,32.887081],[-79.866842,32.755634],[-79.998289,32.613234],[-80.206412,32.552987],[-80.430967,32.399633],[-80.452875,32.328433],[-80.660998,32.246279],[-80.885553,32.032678],[-81.115584,32.120309],[-81.121061,32.290094],[-81.279893,32.558464],[-81.416816,32.629664],[-81.42777,32.843265],[-81.493493,33.007573],[-81.761863,33.160928],[-81.937125,33.347144],[-81.926172,33.462159],[-82.194542,33.631944],[-82.325988,33.81816],[-82.55602,33.94413],[-82.714851,34.152254],[-82.747713,34.26727],[-82.901067,34.486347],[-83.005129,34.469916],[-83.339222,34.683517],[-83.322791,34.787579],[-83.109191,35.00118],[-82.764143,35.066903]]]}},
+ {"type":"Feature","id":"46","properties":{"name":"South Dakota"},"geometry":{"type":"Polygon","coordinates":[[[-104.047534,45.944106],[-96.560556,45.933153],[-96.582464,45.818137],[-96.856311,45.604536],[-96.681049,45.412843],[-96.451017,45.297827],[-96.451017,43.501391],[-96.582464,43.479483],[-96.527695,43.397329],[-96.560556,43.222067],[-96.434587,43.123482],[-96.511264,43.052282],[-96.544125,42.855112],[-96.631756,42.707235],[-96.44554,42.488157],[-96.626279,42.515542],[-96.692003,42.657942],[-97.217789,42.844158],[-97.688806,42.844158],[-97.831206,42.866066],[-97.951699,42.767481],[-98.466531,42.94822],[-98.499393,42.997512],[-101.626726,42.997512],[-103.324578,43.002989],[-104.053011,43.002989],[-104.058488,44.996596],[-104.042057,44.996596],[-104.047534,45.944106]]]}},
+ {"type":"Feature","id":"47","properties":{"name":"Tennessee"},"geometry":{"type":"Polygon","coordinates":[[[-88.054868,36.496384],[-88.071299,36.677123],[-87.852221,36.633308],[-86.592525,36.655216],[-85.486183,36.616877],[-85.289013,36.627831],[-84.544149,36.594969],[-83.689746,36.584015],[-83.673316,36.600446],[-81.679709,36.589492],[-81.723525,36.353984],[-81.909741,36.304691],[-82.03571,36.118475],[-82.216449,36.156814],[-82.610789,35.965121],[-82.638174,36.063706],[-82.775097,35.997983],[-82.994175,35.773428],[-83.251591,35.718659],[-83.498053,35.565304],[-83.7719,35.559827],[-84.018363,35.41195],[-84.09504,35.247642],[-84.29221,35.225734],[-84.319594,34.990226],[-85.606675,34.984749],[-87.359296,35.00118],[-88.202745,34.995703],[-88.471115,34.995703],[-90.311367,34.995703],[-90.212782,35.023087],[-90.114197,35.198349],[-90.130628,35.439335],[-89.944412,35.603643],[-89.911551,35.756997],[-89.763673,35.811767],[-89.730812,35.997983],[-89.533642,36.249922],[-89.539119,36.496384],[-89.484349,36.496384],[-89.418626,36.496384],[-89.298133,36.507338],[-88.054868,36.496384]]]}},
+ {"type":"Feature","id":"48","properties":{"name":"Texas"},"geometry":{"type":"Polygon","coordinates":[[[-101.812942,36.501861],[-100.000075,36.501861],[-100.000075,34.563024],[-99.923398,34.573978],[-99.698843,34.382285],[-99.57835,34.415147],[-99.260688,34.404193],[-99.189488,34.2125],[-98.986841,34.223454],[-98.767763,34.135823],[-98.570593,34.146777],[-98.488439,34.064623],[-98.36247,34.157731],[-98.170777,34.113915],[-98.088623,34.004376],[-97.946222,33.987946],[-97.869545,33.851022],[-97.694283,33.982469],[-97.458774,33.905791],[-97.371143,33.823637],[-97.256128,33.861976],[-97.173974,33.736006],[-96.922034,33.960561],[-96.850834,33.845545],[-96.631756,33.845545],[-96.423633,33.774345],[-96.346956,33.686714],[-96.149786,33.840068],[-95.936185,33.889361],[-95.8376,33.834591],[-95.602092,33.933176],[-95.547322,33.878407],[-95.289906,33.87293],[-95.224183,33.960561],[-94.966767,33.861976],[-94.868182,33.74696],[-94.484796,33.637421],[-94.380734,33.544313],[-94.183564,33.593606],[-94.041164,33.54979],[-94.041164,33.018527],[-94.041164,31.994339],[-93.822086,31.775262],[-93.816609,31.556184],[-93.542762,31.15089],[-93.526331,30.93729],[-93.630393,30.679874],[-93.728978,30.575812],[-93.696116,30.438888],[-93.767317,30.334826],[-93.690639,30.143133],[-93.926148,29.787132],[-93.838517,29.688547],[-94.002825,29.68307],[-94.523134,29.546147],[-94.70935,29.622824],[-94.742212,29.787132],[-94.873659,29.672117],[-94.966767,29.699501],[-95.016059,29.557101],[-94.911997,29.496854],[-94.895566,29.310638],[-95.081782,29.113469],[-95.383014,28.867006],[-95.985477,28.604113],[-96.045724,28.647929],[-96.226463,28.582205],[-96.23194,28.642452],[-96.478402,28.598636],[-96.593418,28.724606],[-96.664618,28.697221],[-96.401725,28.439805],[-96.593418,28.357651],[-96.774157,28.406943],[-96.801542,28.226204],[-97.026096,28.039988],[-97.256128,27.694941],[-97.404005,27.333463],[-97.513544,27.360848],[-97.540929,27.229401],[-97.425913,27.262263],[-97.480682,26.99937],[-97.557359,26.988416],[-97.562836,26.840538],[-97.469728,26.758384],[-97.442344,26.457153],[-97.332805,26.353091],[-97.30542,26.161398],[-97.217789,25.991613],[-97.524498,25.887551],[-97.650467,26.018997],[-97.885976,26.06829],[-98.198161,26.057336],[-98.466531,26.221644],[-98.669178,26.238075],[-98.822533,26.369522],[-99.030656,26.413337],[-99.173057,26.539307],[-99.266165,26.840538],[-99.446904,27.021277],[-99.424996,27.174632],[-99.50715,27.33894],[-99.479765,27.48134],[-99.605735,27.640172],[-99.709797,27.656603],[-99.879582,27.799003],[-99.934351,27.979742],[-100.082229,28.14405],[-100.29583,28.280974],[-100.399891,28.582205],[-100.498476,28.66436],[-100.629923,28.905345],[-100.673738,29.102515],[-100.799708,29.244915],[-101.013309,29.370885],[-101.062601,29.458516],[-101.259771,29.535193],[-101.413125,29.754271],[-101.851281,29.803563],[-102.114174,29.792609],[-102.338728,29.869286],[-102.388021,29.765225],[-102.629006,29.732363],[-102.809745,29.524239],[-102.919284,29.190146],[-102.97953,29.184669],[-103.116454,28.987499],[-103.280762,28.982022],[-103.527224,29.135376],[-104.146119,29.381839],[-104.266611,29.513285],[-104.507597,29.639255],[-104.677382,29.924056],[-104.688336,30.181472],[-104.858121,30.389596],[-104.896459,30.570335],[-105.005998,30.685351],[-105.394861,30.855136],[-105.602985,31.085167],[-105.77277,31.167321],[-105.953509,31.364491],[-106.205448,31.468553],[-106.38071,31.731446],[-106.528588,31.786216],[-106.643603,31.901231],[-106.616219,31.999816],[-103.067161,31.999816],[-103.067161,33.002096],[-103.045254,34.01533],[-103.039777,36.501861],[-103.001438,36.501861],[-101.812942,36.501861]]]}},
+ {"type":"Feature","id":"49","properties":{"name":"Utah"},"geometry":{"type":"Polygon","coordinates":[[[-112.164359,41.995232],[-111.047063,42.000709],[-111.047063,40.998429],[-109.04798,40.998429],[-109.053457,39.125316],[-109.058934,38.27639],[-109.042503,38.166851],[-109.042503,37.000263],[-110.499369,37.00574],[-114.048427,37.000263],[-114.04295,41.995232],[-112.164359,41.995232]]]}},
+ {"type":"Feature","id":"50","properties":{"name":"Vermont"},"geometry":{"type":"Polygon","coordinates":[[[-71.503554,45.013027],[-71.4926,44.914442],[-71.629524,44.750133],[-71.536416,44.585825],[-71.700724,44.41604],[-72.034817,44.322932],[-72.02934,44.07647],[-72.116971,43.994316],[-72.204602,43.769761],[-72.379864,43.572591],[-72.456542,43.150867],[-72.445588,43.008466],[-72.533219,42.953697],[-72.544173,42.80582],[-72.456542,42.729142],[-73.267129,42.745573],[-73.278083,42.833204],[-73.245221,43.523299],[-73.404052,43.687607],[-73.349283,43.769761],[-73.436914,44.043608],[-73.321898,44.246255],[-73.294514,44.437948],[-73.387622,44.618687],[-73.332852,44.804903],[-73.343806,45.013027],[-72.308664,45.002073],[-71.503554,45.013027]]]}},
+ {"type":"Feature","id":"51","properties":{"name":"Virginia"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-75.397659,38.013497],[-75.244304,38.029928],[-75.375751,37.860142],[-75.512674,37.799896],[-75.594828,37.569865],[-75.802952,37.197433],[-75.972737,37.120755],[-76.027507,37.257679],[-75.939876,37.564388],[-75.671506,37.95325],[-75.397659,38.013497]]],[[[-76.016553,37.95325],[-75.994645,37.95325],[-76.043938,37.95325],[-76.016553,37.95325]]],[[[-78.349729,39.464886],[-77.82942,39.130793],[-77.719881,39.322485],[-77.566527,39.306055],[-77.456988,39.223901],[-77.456988,39.076023],[-77.248864,39.026731],[-77.117418,38.933623],[-77.040741,38.791222],[-77.128372,38.632391],[-77.248864,38.588575],[-77.325542,38.446175],[-77.281726,38.342113],[-77.013356,38.374975],[-76.964064,38.216144],[-76.613539,38.15042],[-76.514954,38.024451],[-76.235631,37.887527],[-76.3616,37.608203],[-76.246584,37.389126],[-76.383508,37.285064],[-76.399939,37.159094],[-76.273969,37.082417],[-76.410893,36.961924],[-76.619016,37.120755],[-76.668309,37.065986],[-76.48757,36.95097],[-75.994645,36.923586],[-75.868676,36.551154],[-79.510841,36.5402],[-80.294043,36.545677],[-80.978661,36.562108],[-81.679709,36.589492],[-83.673316,36.600446],[-83.136575,36.742847],[-83.070852,36.852385],[-82.879159,36.890724],[-82.868205,36.978355],[-82.720328,37.044078],[-82.720328,37.120755],[-82.353373,37.268633],[-81.969987,37.537003],[-81.986418,37.454849],[-81.849494,37.285064],[-81.679709,37.20291],[-81.55374,37.208387],[-81.362047,37.339833],[-81.225123,37.235771],[-80.967707,37.290541],[-80.513121,37.482234],[-80.474782,37.421987],[-80.29952,37.509618],[-80.294043,37.690357],[-80.184505,37.849189],[-79.998289,37.997066],[-79.921611,38.177805],[-79.724442,38.364021],[-79.647764,38.594052],[-79.477979,38.457129],[-79.313671,38.413313],[-79.209609,38.495467],[-78.996008,38.851469],[-78.870039,38.763838],[-78.404499,39.169131],[-78.349729,39.464886]]]]}},
+ {"type":"Feature","id":"53","properties":{"name":"Washington"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-117.033359,49.000239],[-117.044313,47.762451],[-117.038836,46.426077],[-117.055267,46.343923],[-116.92382,46.168661],[-116.918344,45.993399],[-118.988627,45.998876],[-119.125551,45.933153],[-119.525367,45.911245],[-119.963522,45.823614],[-120.209985,45.725029],[-120.505739,45.697644],[-120.637186,45.746937],[-121.18488,45.604536],[-121.217742,45.670259],[-121.535404,45.725029],[-121.809251,45.708598],[-122.247407,45.549767],[-122.762239,45.659305],[-122.811531,45.960537],[-122.904639,46.08103],[-123.11824,46.185092],[-123.211348,46.174138],[-123.370179,46.146753],[-123.545441,46.261769],[-123.72618,46.300108],[-123.874058,46.239861],[-124.065751,46.327492],[-124.027412,46.464416],[-123.895966,46.535616],[-124.098612,46.74374],[-124.235536,47.285957],[-124.31769,47.357157],[-124.427229,47.740543],[-124.624399,47.88842],[-124.706553,48.184175],[-124.597014,48.381345],[-124.394367,48.288237],[-123.983597,48.162267],[-123.704273,48.167744],[-123.424949,48.118452],[-123.162056,48.167744],[-123.036086,48.080113],[-122.800578,48.08559],[-122.636269,47.866512],[-122.515777,47.882943],[-122.493869,47.587189],[-122.422669,47.318818],[-122.324084,47.346203],[-122.422669,47.576235],[-122.395284,47.800789],[-122.230976,48.030821],[-122.362422,48.123929],[-122.373376,48.288237],[-122.471961,48.468976],[-122.422669,48.600422],[-122.488392,48.753777],[-122.647223,48.775685],[-122.795101,48.8907],[-122.756762,49.000239],[-117.033359,49.000239]]],[[[-122.718423,48.310145],[-122.586977,48.35396],[-122.608885,48.151313],[-122.767716,48.227991],[-122.718423,48.310145]]],[[[-123.025132,48.583992],[-122.915593,48.715438],[-122.767716,48.556607],[-122.811531,48.419683],[-123.041563,48.458022],[-123.025132,48.583992]]]]}},
+ {"type":"Feature","id":"54","properties":{"name":"West Virginia"},"geometry":{"type":"Polygon","coordinates":[[[-80.518598,40.636951],[-80.518598,39.722302],[-79.477979,39.722302],[-79.488933,39.20747],[-79.291763,39.300578],[-79.094593,39.470363],[-78.963147,39.437501],[-78.765977,39.585379],[-78.470222,39.514178],[-78.431884,39.623717],[-78.267575,39.61824],[-78.174467,39.694917],[-78.004682,39.601809],[-77.834897,39.601809],[-77.719881,39.322485],[-77.82942,39.130793],[-78.349729,39.464886],[-78.404499,39.169131],[-78.870039,38.763838],[-78.996008,38.851469],[-79.209609,38.495467],[-79.313671,38.413313],[-79.477979,38.457129],[-79.647764,38.594052],[-79.724442,38.364021],[-79.921611,38.177805],[-79.998289,37.997066],[-80.184505,37.849189],[-80.294043,37.690357],[-80.29952,37.509618],[-80.474782,37.421987],[-80.513121,37.482234],[-80.967707,37.290541],[-81.225123,37.235771],[-81.362047,37.339833],[-81.55374,37.208387],[-81.679709,37.20291],[-81.849494,37.285064],[-81.986418,37.454849],[-81.969987,37.537003],[-82.101434,37.553434],[-82.293127,37.668449],[-82.342419,37.783465],[-82.50125,37.931343],[-82.621743,38.123036],[-82.594358,38.424267],[-82.331465,38.446175],[-82.293127,38.577622],[-82.172634,38.632391],[-82.221926,38.785745],[-82.03571,39.026731],[-81.887833,38.873376],[-81.783771,38.966484],[-81.811156,39.0815],[-81.685186,39.273193],[-81.57017,39.267716],[-81.455155,39.410117],[-81.345616,39.344393],[-81.219646,39.388209],[-80.830783,39.711348],[-80.737675,40.078303],[-80.600752,40.319289],[-80.595275,40.472643],[-80.666475,40.582182],[-80.518598,40.636951]]]}},
+ {"type":"Feature","id":"55","properties":{"name":"Wisconsin"},"geometry":{"type":"Polygon","coordinates":[[[-90.415429,46.568478],[-90.229213,46.508231],[-90.119674,46.338446],[-89.09001,46.135799],[-88.662808,45.987922],[-88.531362,46.020784],[-88.10416,45.922199],[-87.989145,45.796229],[-87.781021,45.675736],[-87.791975,45.500474],[-87.885083,45.363551],[-87.649574,45.341643],[-87.742682,45.199243],[-87.589328,45.095181],[-87.627666,44.974688],[-87.819359,44.95278],[-87.983668,44.722749],[-88.043914,44.563917],[-87.928898,44.536533],[-87.775544,44.640595],[-87.611236,44.837764],[-87.403112,44.914442],[-87.238804,45.166381],[-87.03068,45.22115],[-87.047111,45.089704],[-87.189511,44.969211],[-87.468835,44.552964],[-87.545512,44.322932],[-87.540035,44.158624],[-87.644097,44.103854],[-87.737205,43.8793],[-87.704344,43.687607],[-87.791975,43.561637],[-87.912467,43.249452],[-87.885083,43.002989],[-87.76459,42.783912],[-87.802929,42.493634],[-88.788778,42.493634],[-90.639984,42.510065],[-90.711184,42.636034],[-91.067185,42.75105],[-91.143862,42.909881],[-91.176724,43.134436],[-91.056231,43.254929],[-91.204109,43.353514],[-91.215062,43.501391],[-91.269832,43.616407],[-91.242447,43.775238],[-91.43414,43.994316],[-91.592971,44.032654],[-91.877772,44.202439],[-91.927065,44.333886],[-92.233773,44.443425],[-92.337835,44.552964],[-92.545959,44.569394],[-92.808852,44.750133],[-92.737652,45.117088],[-92.75956,45.286874],[-92.644544,45.440228],[-92.770513,45.566198],[-92.885529,45.577151],[-92.869098,45.719552],[-92.639067,45.933153],[-92.354266,46.015307],[-92.29402,46.075553],[-92.29402,46.667063],[-92.091373,46.749217],[-92.014696,46.705401],[-91.790141,46.694447],[-91.09457,46.864232],[-90.837154,46.95734],[-90.749522,46.88614],[-90.886446,46.754694],[-90.55783,46.584908],[-90.415429,46.568478]]]}},
+ {"type":"Feature","id":"56","properties":{"name":"Wyoming"},"geometry":{"type":"Polygon","coordinates":[[[-109.080842,45.002073],[-105.91517,45.002073],[-104.058488,44.996596],[-104.053011,43.002989],[-104.053011,41.003906],[-105.728954,40.998429],[-107.919731,41.003906],[-109.04798,40.998429],[-111.047063,40.998429],[-111.047063,42.000709],[-111.047063,44.476286],[-111.05254,45.002073],[-109.080842,45.002073]]]}},
+ {"type":"Feature","id":"72","properties":{"name":"Puerto Rico"},"geometry":{"type":"Polygon","coordinates":[[[-66.448338,17.984326],[-66.771478,18.006234],[-66.924832,17.929556],[-66.985078,17.973372],[-67.209633,17.956941],[-67.154863,18.19245],[-67.269879,18.362235],[-67.094617,18.515589],[-66.957694,18.488204],[-66.409999,18.488204],[-65.840398,18.433435],[-65.632274,18.367712],[-65.626797,18.203403],[-65.730859,18.186973],[-65.834921,18.017187],[-66.234737,17.929556],[-66.448338,17.984326]]]}}
+ ]},
+ defaultDatasourceBoxplot: [
+ ["Income", "Life Expectancy", "Population", "Country", "Year"],
+ [815, 34.05, 351014, "Australia", 1800],
+ [1314, 39, 645526, "Canada", 1800],
+ [985, 32, 321675013, "China", 1800],
+ [864, 32.2, 345043, "Cuba", 1800],
+ [1244, 36.5731262, 977662, "Finland", 1800],
+ [1803, 33.96717024, 29355111, "France", 1800],
+ [1639, 38.37, 22886919, "Germany", 1800],
+ [926, 42.84559912, 61428, "Iceland", 1800],
+ [1052, 25.4424, 168574895, "India", 1800],
+ [1050, 36.4, 30294378, "Japan", 1800],
+ [658, 34.05, 100000, "New Zealand", 1800],
+ [1278, 37.91620899, 868570, "Norway", 1800],
+ [1213, 35.9, 9508747, "Poland", 1800],
+ [1430, 29.5734572, 31088398, "Russia", 1800],
+ [1221, 35, 9773456, "Turkey", 1800],
+ [3431, 38.6497603, 12327466, "United Kingdom", 1800],
+ [2128, 39.41, 6801854, "United States", 1800],
+ [834, 34.05, 342440, "Australia", 1810],
+ [1400, 39.01496774, 727603, "Canada", 1810],
+ [985, 32, 350542958, "China", 1810],
+ [970, 33.64, 470176, "Cuba", 1810],
+ [1267, 36.9473378, 1070625, "Finland", 1810],
+ [1839, 37.4, 30293172, "France", 1810],
+ [1759, 38.37, 23882461, "Germany", 1810],
+ [928, 43.13915533, 61428, "Iceland", 1810],
+ [1051, 25.4424, 171940819, "India", 1810],
+ [1064, 36.40397538, 30645903, "Japan", 1810],
+ [659, 34.05, 100000, "New Zealand", 1810],
+ [1299, 36.47500606, 918398, "Norway", 1810],
+ [1260, 35.9, 9960687, "Poland", 1810],
+ [1447, 29.5734572, 31088398, "Russia", 1810],
+ [1223, 35, 9923007, "Turkey", 1810],
+ [3575, 38.34738144, 14106058, "United Kingdom", 1810],
+ [2283, 39.41, 8294928, "United States", 1810],
+ [853, 34.05, 334002, "Australia", 1820],
+ [1491, 39.02993548, 879432, "Canada", 1820],
+ [985, 32, 380055273, "China", 1820],
+ [1090, 35.04, 607664, "Cuba", 1820],
+ [1290, 37.29122269, 1190807, "Finland", 1820],
+ [1876, 39.21, 31549988, "France", 1820],
+ [1887, 38.37, 25507768, "Germany", 1820],
+ [929, 36.56365268, 62498, "Iceland", 1820],
+ [1050, 25.4424, 176225709, "India", 1820],
+ [1079, 36.40795077, 30993147, "Japan", 1820],
+ [660, 34.05, 100000, "New Zealand", 1820],
+ [1320, 46.96239815, 995904, "Norway", 1820],
+ [1309, 35.9, 10508375, "Poland", 1820],
+ [1464, 29.5734572, 31861526, "Russia", 1820],
+ [1225, 35, 10118315, "Turkey", 1820],
+ [3403, 41.31247671, 16221883, "United Kingdom", 1820],
+ [2242, 39.41, 10361646, "United States", 1820],
+ [1399, 34.05, 348143, "Australia", 1830],
+ [1651, 39.04490323, 1202146, "Canada", 1830],
+ [986, 32, 402373519, "China", 1830],
+ [1224, 35.74, 772812, "Cuba", 1830],
+ [1360, 36.29644969, 1327905, "Finland", 1830],
+ [1799, 39.56, 33174810, "France", 1830],
+ [2024, 38.37, 28016571, "Germany", 1830],
+ [1036, 40.5022162, 65604, "Iceland", 1830],
+ [1052, 25.4424, 182214537, "India", 1830],
+ [1094, 36.41192615, 31330455, "Japan", 1830],
+ [661, 34.05, 91723, "New Zealand", 1830],
+ [1403, 45.75400094, 1115667, "Norway", 1830],
+ [1360, 35.9, 11232857, "Poland", 1830],
+ [1562, 29.5734572, 34134430, "Russia", 1830],
+ [1292, 35, 10398375, "Turkey", 1830],
+ [3661, 43.01830917, 18533999, "United Kingdom", 1830],
+ [2552, 39.41, 13480460, "United States", 1830],
+ [2269, 34.05, 434095, "Australia", 1840],
+ [1922, 40.19012, 1745604, "Canada", 1840],
+ [986, 32, 411213424, "China", 1840],
+ [1374, 36.48, 975565, "Cuba", 1840],
+ [1434, 41.46900965, 1467238, "Finland", 1840],
+ [2184, 40.37, 34854476, "France", 1840],
+ [2102, 38.37, 31016143, "Germany", 1840],
+ [1155, 31.97, 70010, "Iceland", 1840],
+ [1053, 25.4424, 189298397, "India", 1840],
+ [1110, 36.41590154, 31663783, "Japan", 1840],
+ [662, 34.05, 82479, "New Zealand", 1840],
+ [1604, 45.61661054, 1252476, "Norway", 1840],
+ [1413, 35.9, 12090161, "Poland", 1840],
+ [1666, 29.5734572, 37420913, "Russia", 1840],
+ [1362, 35, 10731241, "Turkey", 1840],
+ [4149, 39.92715263, 20737251, "United Kingdom", 1840],
+ [2792, 39.41, 17942443, "United States", 1840],
+ [3267, 34.05, 742619, "Australia", 1850],
+ [2202, 40.985432, 2487811, "Canada", 1850],
+ [985, 32, 402711280, "China", 1850],
+ [1543, 36.26, 1181650, "Cuba", 1850],
+ [1512, 37.35415172, 1607810, "Finland", 1850],
+ [2146, 43.28, 36277905, "France", 1850],
+ [2182, 38.37, 33663143, "Germany", 1850],
+ [1287, 36.61, 74711, "Iceland", 1850],
+ [1055, 25.4424, 196657653, "India", 1850],
+ [1125, 36.41987692, 32223184, "Japan", 1850],
+ [1898, 34.05, 94934, "New Zealand", 1850],
+ [1675, 49.53, 1401619, "Norway", 1850],
+ [1468, 35.9, 13219914, "Poland", 1850],
+ [1778, 29.5734572, 41023821, "Russia", 1850],
+ [1436, 35, 11074762, "Turkey", 1850],
+ [4480, 42.8, 22623571, "United Kingdom", 1850],
+ [3059, 39.41, 24136293, "United States", 1850],
+ [4795, 34.05, 1256048, "Australia", 1860],
+ [2406, 41.541504, 3231465, "Canada", 1860],
+ [1023, 28.85, 380047548, "China", 1860],
+ [1733, 36.24, 1324000, "Cuba", 1860],
+ [1594, 38.15099864, 1734254, "Finland", 1860],
+ [3086, 43.33, 37461341, "France", 1860],
+ [2509, 38.37, 36383150, "Germany", 1860],
+ [1435, 19.76, 79662, "Iceland", 1860],
+ [1056, 23, 204966302, "India", 1860],
+ [1168, 36.42385231, 33176900, "Japan", 1860],
+ [3674, 34.05, 157114, "New Zealand", 1860],
+ [2033, 50, 1580366, "Norway", 1860],
+ [1525, 35.9, 14848599, "Poland", 1860],
+ [1896, 29.5734572, 44966686, "Russia", 1860],
+ [1514, 35, 11428718, "Turkey", 1860],
+ [5268, 43.01, 24783522, "United Kingdom", 1860],
+ [3714, 39.41, 31936643, "United States", 1860],
+ [5431, 34.05, 1724213, "Australia", 1870],
+ [2815, 42.460624, 3817167, "Canada", 1870],
+ [1099, 31.95714286, 363661158, "China", 1870],
+ [1946, 29.66, 1424672, "Cuba", 1870],
+ [1897, 45.66140699, 1847468, "Finland", 1870],
+ [3297, 36.41, 38170355, "France", 1870],
+ [2819, 38.37, 39702235, "Germany", 1870],
+ [1599, 38.37, 84941, "Iceland", 1870],
+ [1058, 25.4424, 213725049, "India", 1870],
+ [1213, 36.59264, 34638021, "Japan", 1870],
+ [5156, 34.05, 301045, "New Zealand", 1870],
+ [2483, 50.86, 1746718, "Norway", 1870],
+ [1584, 35.9, 17013787, "Poland", 1870],
+ [2023, 31.12082604, 49288504, "Russia", 1870],
+ [1597, 35, 11871788, "Turkey", 1870],
+ [6046, 40.95, 27651628, "United Kingdom", 1870],
+ [4058, 39.41, 40821569, "United States", 1870],
+ [7120, 39.34215686, 2253007, "Australia", 1880],
+ [3021, 44.512464, 4360348, "Canada", 1880],
+ [1015, 32, 365544192, "China", 1880],
+ [2185, 36.84, 1555081, "Cuba", 1880],
+ [1925, 39.67, 2047577, "Finland", 1880],
+ [3555, 42.73, 39014053, "France", 1880],
+ [3057, 38.905, 43577358, "Germany", 1880],
+ [2035, 42.32, 90546, "Iceland", 1880],
+ [1084, 25.4424, 223020377, "India", 1880],
+ [1395, 37.03648, 36826469, "Japan", 1880],
+ [6241, 38.51282051, 505065, "New Zealand", 1880],
+ [2827, 51.91, 1883716, "Norway", 1880],
+ [1848, 35.9, 19669587, "Poland", 1880],
+ [2158, 30.20106663, 53996807, "Russia", 1880],
+ [1535, 35, 12474351, "Turkey", 1880],
+ [6553, 43.78, 30849957, "United Kingdom", 1880],
+ [5292, 39.41, 51256498, "United States", 1880],
+ [7418, 44.63431373, 3088808, "Australia", 1890],
+ [3963, 45.12972, 4908078, "Canada", 1890],
+ [918, 32, 377135349, "China", 1890],
+ [2454, 39.54, 1658274, "Cuba", 1890],
+ [2305, 44.61, 2358344, "Finland", 1890],
+ [3639, 43.36, 40015501, "France", 1890],
+ [3733, 40.91, 48211294, "Germany", 1890],
+ [2009, 36.58, 96517, "Iceland", 1890],
+ [1163, 24.384, 232819584, "India", 1890],
+ [1606, 37.67568, 39878734, "Japan", 1890],
+ [6265, 42.97564103, 669985, "New Zealand", 1890],
+ [3251, 48.6, 2003954, "Norway", 1890],
+ [2156, 37.41086957, 22618933, "Poland", 1890],
+ [2233, 29.93047652, 59151534, "Russia", 1890],
+ [1838, 35, 13188522, "Turkey", 1890],
+ [7169, 44.75, 34215580, "United Kingdom", 1890],
+ [5646, 45.21, 63810074, "United States", 1890],
+ [6688, 49.92647059, 3743708, "Australia", 1900],
+ [4858, 48.288448, 5530806, "Canada", 1900],
+ [894, 32, 395184556, "China", 1900],
+ [2756, 33.11248, 1762227, "Cuba", 1900],
+ [2789, 41.8, 2633389, "Finland", 1900],
+ [4314, 45.08, 40628638, "France", 1900],
+ [4596, 43.915, 55293434, "Germany", 1900],
+ [2352, 46.64, 102913, "Iceland", 1900],
+ [1194, 18.35, 243073946, "India", 1900],
+ [1840, 38.6, 44040263, "Japan", 1900],
+ [7181, 47.43846154, 815519, "New Zealand", 1900],
+ [3643, 53.47, 2214923, "Norway", 1900],
+ [2583, 40.4326087, 24700965, "Poland", 1900],
+ [3087, 30.74960789, 64836675, "Russia", 1900],
+ [1985, 35, 13946634, "Turkey", 1900],
+ [8013, 46.32, 37995759, "United Kingdom", 1900],
+ [6819, 48.92818182, 77415610, "United States", 1900],
+ [8695, 55.21862745, 4408209, "Australia", 1910],
+ [6794, 52.123024, 7181200, "Canada", 1910],
+ [991, 32, 417830774, "China", 1910],
+ [3095, 35.21936, 2268558, "Cuba", 1910],
+ [3192, 48.53, 2930441, "Finland", 1910],
+ [4542, 51.37, 41294572, "France", 1910],
+ [5162, 48.40833333, 64064129, "Germany", 1910],
+ [3012, 52.67, 109714, "Iceland", 1910],
+ [1391, 23.18032, 253761202, "India", 1910],
+ [1998, 39.9736, 49314848, "Japan", 1910],
+ [8896, 51.90128205, 1044340, "New Zealand", 1910],
+ [4332, 57.99, 2383631, "Norway", 1910],
+ [2846, 43.45434783, 26493422, "Poland", 1910],
+ [3487, 31.40217766, 71044207, "Russia", 1910],
+ [2144, 35, 14746479, "Turkey", 1910],
+ [8305, 53.99, 41804912, "United Kingdom", 1910],
+ [8287, 51.8, 93559186, "United States", 1910],
+ [7867, 60.51078431, 5345428, "Australia", 1920],
+ [6430, 56.569064, 8764205, "Canada", 1920],
+ [1012, 32, 462750597, "China", 1920],
+ [4042, 37.38208, 3067116, "Cuba", 1920],
+ [3097, 47.55, 3140763, "Finland", 1920],
+ [4550, 51.6, 39069937, "France", 1920],
+ [4482, 53.5, 62277173, "Germany", 1920],
+ [2514, 54.58, 117013, "Iceland", 1920],
+ [1197, 24.71866667, 267795301, "India", 1920],
+ [2496, 42.04432, 55545937, "Japan", 1920],
+ [9453, 56.36410256, 1236395, "New Zealand", 1920],
+ [5483, 58.89, 2634635, "Norway", 1920],
+ [3276, 46.47608696, 24166006, "Poland", 1920],
+ [1489, 20.5, 77871987, "Russia", 1920],
+ [1525, 29, 14200404, "Turkey", 1920],
+ [8316, 56.6, 43825720, "United Kingdom", 1920],
+ [9181, 55.4, 108441644, "United States", 1920],
+ [7714, 64.998, 6473803, "Australia", 1930],
+ [7976, 58.94, 10450983, "Canada", 1930],
+ [1055, 33.26984, 481222579, "China", 1930],
+ [5027, 42.03308, 3918827, "Cuba", 1930],
+ [4489, 54.438, 3450505, "Finland", 1930],
+ [6835, 56.938, 41662571, "France", 1930],
+ [6791, 59.4991686, 66439556, "Germany", 1930],
+ [4444, 60.228, 124871, "Iceland", 1930],
+ [1244, 28.8016, 285470839, "India", 1930],
+ [2592, 46.65403, 63863524, "Japan", 1930],
+ [8359, 60.86092308, 1491937, "New Zealand", 1930],
+ [7369, 64.074, 2807922, "Norway", 1930],
+ [3591, 49.52382609, 28169922, "Poland", 1930],
+ [3779, 36.428, 85369549, "Russia", 1930],
+ [2323, 35.7818, 14930772, "Turkey", 1930],
+ [8722, 60.85, 45957969, "United Kingdom", 1930],
+ [10139, 59.556, 125055606, "United States", 1930],
+ [10057, 66.336, 7052012, "Australia", 1940],
+ [8871, 63.99, 11655920, "Canada", 1940],
+ [841, 33.30311174, 509858820, "China", 1940],
+ [4631, 48.5472, 4672303, "Cuba", 1940],
+ [5439, 46.586, 3696232, "Finland", 1940],
+ [4821, 49.586, 40927546, "France", 1940],
+ [9711, 60.73821096, 71244059, "Germany", 1940],
+ [5373, 65.786, 133257, "Iceland", 1940],
+ [1081, 32.13056, 324372335, "India", 1940],
+ [3888, 49.052, 72709185, "Japan", 1940],
+ [10673, 65.35774359, 1629869, "New Zealand", 1940],
+ [8349, 65.818, 2971546, "Norway", 1940],
+ [3696, 44.752, 30041062, "Poland", 1940],
+ [5632, 41.056, 93588981, "Russia", 1940],
+ [3163, 34.5396, 17777172, "Turkey", 1940],
+ [10935, 60.89, 48235963, "United Kingdom", 1940],
+ [11320, 63.192, 134354133, "United States", 1940],
+ [12073, 69.134, 8177344, "Australia", 1950],
+ [12022, 68.25, 13736997, "Canada", 1950],
+ [535, 39.9994, 544112923, "China", 1950],
+ [8630, 59.8384, 5919997, "Cuba", 1950],
+ [7198, 64.144, 4008299, "Finland", 1950],
+ [7914, 66.594, 41879607, "France", 1950],
+ [7251, 67.0215058, 69786246, "Germany", 1950],
+ [8670, 71.004, 142656, "Iceland", 1950],
+ [908, 34.6284, 376325205, "India", 1950],
+ [2549, 59.378, 82199470, "Japan", 1950],
+ [14391, 69.392, 1908001, "New Zealand", 1950],
+ [11452, 71.492, 3265278, "Norway", 1950],
+ [4670, 59.123, 24824013, "Poland", 1950],
+ [7514, 57.084, 102798657, "Russia", 1950],
+ [3103, 42.5164, 21238496, "Turkey", 1950],
+ [11135, 68.58, 50616012, "United Kingdom", 1950],
+ [15319, 67.988, 157813040, "United States", 1950],
+ [12229, 68.8378, 8417640, "Australia", 1951],
+ [12419, 68.519, 14099994, "Canada", 1951],
+ [582, 40.936264, 558820362, "China", 1951],
+ [9245, 60.18618, 6051290, "Cuba", 1951],
+ [7738, 65.5708, 4049689, "Finland", 1951],
+ [8301, 66.3308, 42071027, "France", 1951],
+ [7884, 67.18742266, 70111671, "Germany", 1951],
+ [8350, 71.0438, 144928, "Iceland", 1951],
+ [908, 34.95868, 382231042, "India", 1951],
+ [2728, 61.0706, 83794452, "Japan", 1951],
+ [13032, 69.2654, 1947802, "New Zealand", 1951],
+ [11986, 72.4284, 3300422, "Norway", 1951],
+ [4801, 59.7336, 25264029, "Poland", 1951],
+ [7424, 57.5768, 104306354, "Russia", 1951],
+ [3701, 42.78358, 21806355, "Turkey", 1951],
+ [11416, 68.176, 50620538, "United Kingdom", 1951],
+ [16198, 68.0836, 159880756, "United States", 1951],
+ [12084, 69.2416, 8627052, "Australia", 1952],
+ [12911, 68.718, 14481497, "Canada", 1952],
+ [631, 41.873128, 570764965, "China", 1952],
+ [9446, 60.82796, 6180031, "Cuba", 1952],
+ [7914, 66.4476, 4095130, "Finland", 1952],
+ [8446, 67.6276, 42365756, "France", 1952],
+ [8561, 67.51033952, 70421462, "Germany", 1952],
+ [8120, 72.4836, 147681, "Iceland", 1952],
+ [912, 35.62796, 388515758, "India", 1952],
+ [3015, 63.1132, 85174909, "Japan", 1952],
+ [13281, 69.4988, 1992619, "New Zealand", 1952],
+ [12316, 72.5548, 3333895, "Norway", 1952],
+ [4832, 60.9112, 25738253, "Poland", 1952],
+ [7775, 57.9696, 105969442, "Russia", 1952],
+ [3963, 43.25976, 22393931, "Turkey", 1952],
+ [11367, 69.472, 50683596, "United Kingdom", 1952],
+ [16508, 68.2992, 162280405, "United States", 1952],
+ [12228, 69.8254, 8821938, "Australia", 1953],
+ [13158, 69.097, 14882050, "Canada", 1953],
+ [692, 42.809992, 580886559, "China", 1953],
+ [8192, 61.46974, 6304524, "Cuba", 1953],
+ [7877, 66.5044, 4142353, "Finland", 1953],
+ [8622, 67.5644, 42724452, "France", 1953],
+ [9252, 67.82125638, 70720721, "Germany", 1953],
+ [9169, 72.3034, 150779, "Iceland", 1953],
+ [947, 36.30024, 395137696, "India", 1953],
+ [3168, 63.4558, 86378004, "Japan", 1953],
+ [13388, 70.3522, 2040015, "New Zealand", 1953],
+ [12707, 73.0312, 3366281, "Norway", 1953],
+ [5027, 62.0038, 26236679, "Poland", 1953],
+ [7981, 58.7624, 107729541, "Russia", 1953],
+ [4361, 43.77694, 22999018, "Turkey", 1953],
+ [11751, 69.738, 50792671, "United Kingdom", 1953],
+ [16974, 68.6448, 164941716, "United States", 1953],
+ [12694, 69.9792, 9014508, "Australia", 1954],
+ [12687, 69.956, 15300472, "Canada", 1954],
+ [694, 44.663056, 589955812, "China", 1954],
+ [8492, 62.11152, 6424173, "Cuba", 1954],
+ [8470, 67.4612, 4189559, "Finland", 1954],
+ [9006, 68.4412, 43118110, "France", 1954],
+ [9926, 68.12117324, 71015688, "Germany", 1954],
+ [9821, 73.3532, 154110, "Iceland", 1954],
+ [962, 36.97552, 402065915, "India", 1954],
+ [3280, 64.6984, 87438747, "Japan", 1954],
+ [14907, 70.4656, 2088194, "New Zealand", 1954],
+ [13247, 73.1076, 3398028, "Norway", 1954],
+ [5224, 63.0134, 26750026, "Poland", 1954],
+ [8234, 60.7552, 109537868, "Russia", 1954],
+ [3892, 44.33512, 23619469, "Turkey", 1954],
+ [12173, 70.104, 50938227, "United Kingdom", 1954],
+ [16558, 69.4304, 167800046, "United States", 1954],
+ [13082, 70.303, 9212824, "Australia", 1955],
+ [13513, 70.015, 15733858, "Canada", 1955],
+ [706, 46.1666, 598574241, "China", 1955],
+ [8757, 62.7523, 6539470, "Cuba", 1955],
+ [8802, 67.258, 4235423, "Finland", 1955],
+ [9453, 68.708, 43528065, "France", 1955],
+ [10998, 68.4080901, 71313740, "Germany", 1955],
+ [10548, 73.293, 157584, "Iceland", 1955],
+ [963, 37.6538, 409280196, "India", 1955],
+ [3464, 65.861, 88389994, "Japan", 1955],
+ [14883, 70.599, 2136000, "New Zealand", 1955],
+ [13438, 73.314, 3429431, "Norway", 1955],
+ [5386, 63.939, 27269745, "Poland", 1955],
+ [8787, 63.148, 111355224, "Russia", 1955],
+ [4156, 44.9343, 24253200, "Turkey", 1955],
+ [12531, 70.07, 51113711, "United Kingdom", 1955],
+ [17409, 69.476, 170796378, "United States", 1955],
+ [13217, 70.1868, 9420602, "Australia", 1956],
+ [14253, 70.004, 16177451, "Canada", 1956],
+ [736, 48.536704, 607167524, "China", 1956],
+ [9424, 63.39308, 6652086, "Cuba", 1956],
+ [8971, 67.8748, 4279108, "Finland", 1956],
+ [9907, 68.7448, 43946534, "France", 1956],
+ [11751, 68.70345102, 71623569, "Germany", 1956],
+ [10575, 72.9728, 161136, "Iceland", 1956],
+ [993, 38.33608, 416771502, "India", 1956],
+ [3646, 65.7236, 89262489, "Japan", 1956],
+ [15358, 70.8624, 2182943, "New Zealand", 1956],
+ [14054, 73.3604, 3460640, "Norway", 1956],
+ [5530, 64.7816, 27787997, "Poland", 1956],
+ [9465, 64.6408, 113152347, "Russia", 1956],
+ [4122, 45.57448, 24898170, "Turkey", 1956],
+ [12572, 70.336, 51315724, "United Kingdom", 1956],
+ [17428, 69.5516, 173877321, "United States", 1956],
+ [13191, 70.4706, 9637408, "Australia", 1957],
+ [14177, 69.923, 16624767, "Canada", 1957],
+ [780, 48.587368, 615992182, "China", 1957],
+ [10636, 64.03586, 6764787, "Cuba", 1957],
+ [9302, 67.3716, 4320250, "Finland", 1957],
+ [10442, 69.1816, 44376073, "France", 1957],
+ [12385, 68.62532856, 71955005, "Germany", 1957],
+ [10295, 73.4626, 164721, "Iceland", 1957],
+ [959, 39.02236, 424541513, "India", 1957],
+ [3843, 65.5962, 90084818, "Japan", 1957],
+ [15441, 70.3858, 2229176, "New Zealand", 1957],
+ [14379, 73.3068, 3491657, "Norway", 1957],
+ [5730, 65.5442, 28297669, "Poland", 1957],
+ [9496, 63.7336, 114909562, "Russia", 1957],
+ [4943, 46.25466, 25552398, "Turkey", 1957],
+ [12702, 70.452, 51543847, "United Kingdom", 1957],
+ [17430, 69.3272, 176995108, "United States", 1957],
+ [13545, 71.0244, 9859257, "Australia", 1958],
+ [14056, 70.582, 17067983, "Canada", 1958],
+ [889, 48.143792, 625155626, "China", 1958],
+ [10501, 64.67964, 6881209, "Cuba", 1958],
+ [9276, 68.5084, 4358901, "Finland", 1958],
+ [10681, 70.4184, 44827950, "France", 1958],
+ [12884, 69.36929231, 72318498, "Germany", 1958],
+ [10896, 73.4224, 168318, "Iceland", 1958],
+ [1005, 39.71364, 432601236, "India", 1958],
+ [3996, 67.2188, 90883290, "Japan", 1958],
+ [15688, 71.0192, 2275392, "New Zealand", 1958],
+ [14285, 73.2932, 3522361, "Norway", 1958],
+ [5923, 66.0188, 28792427, "Poland", 1958],
+ [10037, 66.6264, 116615781, "Russia", 1958],
+ [5252, 46.97084, 26214022, "Turkey", 1958],
+ [12672, 70.628, 51800117, "United Kingdom", 1958],
+ [16961, 69.5928, 180107612, "United States", 1958],
+ [14076, 70.5982, 10079604, "Australia", 1959],
+ [14289, 70.621, 17498573, "Canada", 1959],
+ [958, 36.336856, 634649557, "China", 1959],
+ [9234, 65.32842, 7005486, "Cuba", 1959],
+ [9751, 68.6852, 4395427, "Finland", 1959],
+ [10911, 70.4552, 45319442, "France", 1959],
+ [13759, 69.48021979, 72724260, "Germany", 1959],
+ [10865, 72.6522, 171919, "Iceland", 1959],
+ [1002, 40.41292, 440968677, "India", 1959],
+ [4288, 67.6114, 91681713, "Japan", 1959],
+ [16454, 70.9326, 2322669, "New Zealand", 1959],
+ [14797, 73.4196, 3552545, "Norway", 1959],
+ [6009, 65.6314, 29266789, "Poland", 1959],
+ [9755, 67.3692, 118266807, "Russia", 1959],
+ [4869, 47.72102, 26881379, "Turkey", 1959],
+ [13122, 70.724, 52088147, "United Kingdom", 1959],
+ [17909, 69.8084, 183178348, "United States", 1959],
+ [14346, 71.042, 10292328, "Australia", 1960],
+ [14414, 71, 17909232, "Canada", 1960],
+ [889, 29.51112, 644450173, "China", 1960],
+ [9213, 65.9852, 7141129, "Cuba", 1960],
+ [10560, 68.882, 4430228, "Finland", 1960],
+ [11642, 70.672, 45865699, "France", 1960],
+ [14808, 69.40190727, 73179665, "Germany", 1960],
+ [10993, 74.082, 175520, "Iceland", 1960],
+ [1048, 41.1222, 449661874, "India", 1960],
+ [4756, 67.904, 92500754, "Japan", 1960],
+ [16179, 71.396, 2371999, "New Zealand", 1960],
+ [15542, 73.436, 3582016, "Norway", 1960],
+ [6248, 67.964, 29716363, "Poland", 1960],
+ [10496, 68.382, 119860289, "Russia", 1960],
+ [4735, 48.4992, 27553280, "Turkey", 1960],
+ [13697, 70.94, 52410496, "United Kingdom", 1960],
+ [18059, 69.734, 186176524, "United States", 1960],
+ [14126, 71.3158, 10494911, "Australia", 1961],
+ [14545, 71.229, 18295922, "Canada", 1961],
+ [558, 31.930824, 654625069, "China", 1961],
+ [9248, 66.64998, 7289828, "Cuba", 1961],
+ [11286, 68.9088, 4463432, "Finland", 1961],
+ [12168, 71.2588, 46471083, "France", 1961],
+ [15317, 69.99702797, 73686490, "Germany", 1961],
+ [10801, 73.4618, 179106, "Iceland", 1961],
+ [1051, 41.84348, 458691457, "India", 1961],
+ [5276, 68.5566, 93357259, "Japan", 1961],
+ [16664, 71.1194, 2423769, "New Zealand", 1961],
+ [16425, 73.4424, 3610710, "Norway", 1961],
+ [6669, 68.0866, 30138099, "Poland", 1961],
+ [10908, 68.6248, 121390327, "Russia", 1961],
+ [4691, 49.30038, 28229291, "Turkey", 1961],
+ [13887, 70.686, 52765864, "United Kingdom", 1961],
+ [18170, 70.1396, 189077076, "United States", 1961],
+ [14742, 71.0896, 10691220, "Australia", 1962],
+ [15276, 71.258, 18659663, "Canada", 1962],
+ [567, 42.274688, 665426760, "China", 1962],
+ [9273, 67.32476, 7450404, "Cuba", 1962],
+ [11560, 68.6156, 4494623, "Finland", 1962],
+ [12767, 70.7956, 47121575, "France", 1962],
+ [15872, 70.16889372, 74238494, "Germany", 1962],
+ [11489, 73.6716, 182640, "Iceland", 1962],
+ [1046, 42.57776, 468054145, "India", 1962],
+ [5686, 68.8392, 94263646, "Japan", 1962],
+ [16646, 71.3828, 2477328, "New Zealand", 1962],
+ [16793, 73.3188, 3638791, "Norway", 1962],
+ [6511, 67.7492, 30530513, "Poland", 1962],
+ [11027, 68.2776, 122842753, "Russia", 1962],
+ [4849, 50.11556, 28909985, "Turkey", 1962],
+ [13897, 70.752, 53146634, "United Kingdom", 1962],
+ [18966, 70.0252, 191860710, "United States", 1962],
+ [15357, 71.1534, 10892700, "Australia", 1963],
+ [15752, 71.267, 19007305, "Canada", 1963],
+ [635, 49.619432, 677332765, "China", 1963],
+ [9244, 68.00654, 7618359, "Cuba", 1963],
+ [11858, 69.0224, 4522727, "Finland", 1963],
+ [13235, 70.6524, 47781535, "France", 1963],
+ [16221, 70.26131586, 74820389, "Germany", 1963],
+ [12447, 72.9714, 186056, "Iceland", 1963],
+ [1071, 43.32404, 477729958, "India", 1963],
+ [6106, 69.9218, 95227653, "Japan", 1963],
+ [17340, 71.4562, 2530791, "New Zealand", 1963],
+ [17347, 72.9552, 3666690, "Norway", 1963],
+ [6836, 68.6818, 30893775, "Poland", 1963],
+ [10620, 68.7404, 124193114, "Russia", 1963],
+ [5188, 50.93674, 29597047, "Turkey", 1963],
+ [14393, 70.658, 53537821, "United Kingdom", 1963],
+ [19497, 69.8508, 194513911, "United States", 1963],
+ [16098, 70.8172, 11114995, "Australia", 1964],
+ [16464, 71.646, 19349346, "Canada", 1964],
+ [713, 50.988016, 690932043, "China", 1964],
+ [9179, 68.69332, 7787149, "Cuba", 1964],
+ [12389, 69.2292, 4546343, "Finland", 1964],
+ [13969, 71.6192, 48402900, "France", 1964],
+ [17100, 70.82344196, 75410766, "Germany", 1964],
+ [13450, 73.5612, 189276, "Iceland", 1964],
+ [1125, 44.07932, 487690114, "India", 1964],
+ [6741, 70.3944, 96253064, "Japan", 1964],
+ [17837, 71.4996, 2581578, "New Zealand", 1964],
+ [18118, 73.4516, 3694987, "Norway", 1964],
+ [7078, 68.9144, 31229448, "Poland", 1964],
+ [11836, 69.5332, 125412397, "Russia", 1964],
+ [5296, 51.75292, 30292969, "Turkey", 1964],
+ [15067, 71.444, 53920055, "United Kingdom", 1964],
+ [20338, 70.1364, 197028908, "United States", 1964],
+ [16601, 71.151, 11368011, "Australia", 1965],
+ [17243, 71.745, 19693538, "Canada", 1965],
+ [772, 53.26108, 706590947, "China", 1965],
+ [9116, 69.3761, 7951928, "Cuba", 1965],
+ [13006, 68.986, 4564690, "Finland", 1965],
+ [14514, 71.456, 48952283, "France", 1965],
+ [17838, 70.81075623, 75990737, "Germany", 1965],
+ [14173, 73.831, 192251, "Iceland", 1965],
+ [1053, 44.8386, 497920270, "India", 1965],
+ [7048, 70.447, 97341852, "Japan", 1965],
+ [18632, 71.433, 2628003, "New Zealand", 1965],
+ [18980, 73.568, 3724065, "Norway", 1965],
+ [7409, 69.617, 31539695, "Poland", 1965],
+ [12363, 69.116, 126483874, "Russia", 1965],
+ [5309, 52.5551, 31000167, "Turkey", 1965],
+ [15292, 71.43, 54278349, "United Kingdom", 1965],
+ [21361, 70.212, 199403532, "United States", 1965],
+ [16756, 70.9948, 11657281, "Australia", 1966],
+ [18022, 71.874, 20041006, "Canada", 1966],
+ [826, 54.364464, 724490033, "China", 1966],
+ [9436, 70.04688, 8110428, "Cuba", 1966],
+ [13269, 69.5028, 4577033, "Finland", 1966],
+ [15158, 71.8728, 49411342, "France", 1966],
+ [18262, 70.92828395, 76558016, "Germany", 1966],
+ [15166, 73.2208, 194935, "Iceland", 1966],
+ [1037, 45.59388, 508402908, "India", 1966],
+ [7724, 71.2596, 98494630, "Japan", 1966],
+ [19467, 71.2964, 2668590, "New Zealand", 1966],
+ [19588, 73.8444, 3754010, "Norway", 1966],
+ [7818, 70.0296, 31824145, "Poland", 1966],
+ [12823, 69.1788, 127396324, "Russia", 1966],
+ [5906, 53.33228, 31718266, "Turkey", 1966],
+ [15494, 71.346, 54606608, "United Kingdom", 1966],
+ [22495, 70.2276, 201629471, "United States", 1966],
+ [17570, 71.2786, 11975795, "Australia", 1967],
+ [18240, 72.083, 20389445, "Canada", 1967],
+ [719, 55.889368, 744365635, "China", 1967],
+ [10372, 70.69866, 8263547, "Cuba", 1967],
+ [13477, 69.6796, 4584264, "Finland", 1967],
+ [15759, 71.8696, 49791771, "France", 1967],
+ [18311, 71.15404398, 77106876, "Germany", 1967],
+ [14734, 73.7206, 197356, "Iceland", 1967],
+ [1096, 46.33916, 519162069, "India", 1967],
+ [8454, 71.5522, 99711082, "Japan", 1967],
+ [18309, 71.6798, 2704205, "New Zealand", 1967],
+ [20686, 73.9108, 3784579, "Norway", 1967],
+ [8044, 69.7322, 32085011, "Poland", 1967],
+ [13256, 68.9616, 128165823, "Russia", 1967],
+ [6020, 54.08346, 32448404, "Turkey", 1967],
+ [15777, 71.972, 54904680, "United Kingdom", 1967],
+ [22803, 70.5532, 203713082, "United States", 1967],
+ [18261, 70.9124, 12305530, "Australia", 1968],
+ [18900, 72.242, 20739031, "Canada", 1968],
+ [669, 56.860432, 765570668, "China", 1968],
+ [9626, 71.32644, 8413329, "Cuba", 1968],
+ [13726, 69.6364, 4589226, "Finland", 1968],
+ [16321, 71.8664, 50126895, "France", 1968],
+ [19254, 70.80345367, 77611000, "Germany", 1968],
+ [13752, 73.9304, 199634, "Iceland", 1968],
+ [1095, 47.07144, 530274729, "India", 1968],
+ [9439, 71.8748, 100988866, "Japan", 1968],
+ [18082, 71.3432, 2738283, "New Zealand", 1968],
+ [21022, 73.7872, 3815399, "Norway", 1968],
+ [8473, 70.3748, 32330582, "Poland", 1968],
+ [13902, 68.9144, 128837792, "Russia", 1968],
+ [6295, 54.80964, 33196289, "Turkey", 1968],
+ [16357, 71.598, 55171084, "United Kingdom", 1968],
+ [23647, 70.2088, 205687611, "United States", 1968],
+ [18949, 71.3262, 12621240, "Australia", 1969],
+ [19614, 72.401, 21089228, "Canada", 1969],
+ [732, 58.367416, 787191243, "China", 1969],
+ [9377, 71.92622, 8563191, "Cuba", 1969],
+ [15058, 69.5132, 4595807, "Finland", 1969],
+ [17339, 71.6032, 50466183, "France", 1969],
+ [20409, 70.65682236, 78038271, "Germany", 1969],
+ [13983, 73.7002, 201941, "Iceland", 1969],
+ [1141, 47.78972, 541844848, "India", 1969],
+ [10548, 72.1074, 102323674, "Japan", 1969],
+ [19745, 71.7166, 2775684, "New Zealand", 1969],
+ [21845, 73.4936, 3845932, "Norway", 1969],
+ [8331, 69.8674, 32571673, "Poland", 1969],
+ [13972, 68.3872, 129475269, "Russia", 1969],
+ [6470, 55.51382, 33969201, "Turkey", 1969],
+ [16616, 71.554, 55406435, "United Kingdom", 1969],
+ [24147, 70.4444, 207599308, "United States", 1969],
+ [19719, 71, 12904760, "Australia", 1970],
+ [19842, 72.6, 21439200, "Canada", 1970],
+ [848, 60, 808510713, "China", 1970],
+ [8918, 72.5, 8715123, "Cuba", 1970],
+ [16245, 70.2, 4606740, "Finland", 1970],
+ [18185, 72.5, 50843830, "France", 1970],
+ [21218, 70.9, 78366605, "Germany", 1970],
+ [14937, 73.8, 204392, "Iceland", 1970],
+ [1170, 48.5, 553943226, "India", 1970],
+ [14203, 72.2, 103707537, "Japan", 1970],
+ [19200, 71.5, 2819548, "New Zealand", 1970],
+ [22186, 73.9, 3875719, "Norway", 1970],
+ [8705, 70, 32816751, "Poland", 1970],
+ [14915, 68.5, 130126383, "Russia", 1970],
+ [6740, 56.2, 34772031, "Turkey", 1970],
+ [16933, 71.8, 55611401, "United Kingdom", 1970],
+ [23908, 70.7, 209485807, "United States", 1970],
+ [20176, 71.3, 13150591, "Australia", 1971],
+ [20688, 72.9, 21790338, "Canada", 1971],
+ [876, 60.6, 829367784, "China", 1971],
+ [9471, 73.2, 8869961, "Cuba", 1971],
+ [16564, 70.5, 4623389, "Finland", 1971],
+ [18891, 72.6, 51273975, "France", 1971],
+ [21695, 71, 78584779, "Germany", 1971],
+ [16687, 73.8, 207050, "Iceland", 1971],
+ [1154, 48.9, 566605402, "India", 1971],
+ [14673, 72.8, 105142875, "Japan", 1971],
+ [19871, 71.6, 2871810, "New Zealand", 1971],
+ [23239, 74.1, 3904750, "Norway", 1971],
+ [9256, 70.2, 33068997, "Poland", 1971],
+ [15170, 68.6, 130808492, "Russia", 1971],
+ [6765, 56.9, 35608079, "Turkey", 1971],
+ [17207, 72, 55785325, "United Kingdom", 1971],
+ [24350, 71, 211357912, "United States", 1971],
+ [20385, 71.7, 13364238, "Australia", 1972],
+ [21532, 72.9, 22141998, "Canada", 1972],
+ [843, 61.1, 849787991, "China", 1972],
+ [9745, 73.9, 9025299, "Cuba", 1972],
+ [17722, 70.9, 4644847, "Finland", 1972],
+ [19570, 72.8, 51741044, "France", 1972],
+ [22497, 71.2, 78700104, "Germany", 1972],
+ [17413, 73.9, 209868, "Iceland", 1972],
+ [1125, 49.3, 579800632, "India", 1972],
+ [15694, 73.2, 106616535, "Japan", 1972],
+ [20349, 71.8, 2930469, "New Zealand", 1972],
+ [24308, 74.3, 3932945, "Norway", 1972],
+ [9854, 70.6, 33328713, "Poland", 1972],
+ [15113, 68.7, 131517584, "Russia", 1972],
+ [7186, 57.7, 36475356, "Turkey", 1972],
+ [17793, 72, 55927492, "United Kingdom", 1972],
+ [25374, 71.3, 213219515, "United States", 1972],
+ [21185, 72, 13552190, "Australia", 1973],
+ [22797, 73.1, 22488744, "Canada", 1973],
+ [894, 61.7, 869474823, "China", 1973],
+ [10439, 74.1, 9176051, "Cuba", 1973],
+ [18804, 71.3, 4668813, "Finland", 1973],
+ [20486, 73.1, 52214014, "France", 1973],
+ [23461, 71.5, 78732884, "Germany", 1973],
+ [18360, 74.1, 212731, "Iceland", 1973],
+ [1151, 49.9, 593451889, "India", 1973],
+ [16731, 73.5, 108085729, "Japan", 1973],
+ [21342, 71.8, 2989985, "New Zealand", 1973],
+ [25278, 74.5, 3959705, "Norway", 1973],
+ [10504, 70.9, 33597810, "Poland", 1973],
+ [16236, 68.7, 132254362, "Russia", 1973],
+ [7442, 58.3, 37366922, "Turkey", 1973],
+ [19043, 72, 56039166, "United Kingdom", 1973],
+ [26567, 71.6, 215092900, "United States", 1973],
+ [21383, 72.1, 13725400, "Australia", 1974],
+ [23405, 73.2, 22823272, "Canada", 1974],
+ [888, 62.1, 888132761, "China", 1974],
+ [10805, 74.3, 9315371, "Cuba", 1974],
+ [19273, 71.4, 4691818, "Finland", 1974],
+ [20997, 73.3, 52647616, "France", 1974],
+ [23662, 71.8, 78713928, "Germany", 1974],
+ [19123, 74.3, 215465, "Iceland", 1974],
+ [1139, 50.4, 607446519, "India", 1974],
+ [16320, 73.9, 109495053, "Japan", 1974],
+ [22131, 72, 3042573, "New Zealand", 1974],
+ [26252, 74.7, 3984291, "Norway", 1974],
+ [11020, 71.2, 33877397, "Poland", 1974],
+ [16594, 68.6, 133012558, "Russia", 1974],
+ [7991, 58.9, 38272701, "Turkey", 1974],
+ [18801, 72.3, 56122405, "United Kingdom", 1974],
+ [26258, 72.1, 217001865, "United States", 1974],
+ [21708, 72.5, 13892674, "Australia", 1975],
+ [23593, 73.6, 23140609, "Canada", 1975],
+ [920, 62.6, 905580445, "China", 1975],
+ [11176, 74.6, 9438445, "Cuba", 1975],
+ [19409, 71.6, 4711459, "Finland", 1975],
+ [20851, 73.2, 53010727, "France", 1975],
+ [23630, 71.9, 78667327, "Germany", 1975],
+ [19023, 74.7, 217958, "Iceland", 1975],
+ [1212, 50.9, 621703641, "India", 1975],
+ [16632, 74.4, 110804519, "Japan", 1975],
+ [21467, 72.1, 3082883, "New Zealand", 1975],
+ [27553, 74.8, 4006221, "Norway", 1975],
+ [11430, 70.9, 34168112, "Poland", 1975],
+ [16530, 68.2, 133788113, "Russia", 1975],
+ [8381, 59.5, 39185637, "Turkey", 1975],
+ [18699, 72.6, 56179925, "United Kingdom", 1975],
+ [25934, 72.6, 218963561, "United States", 1975],
+ [22372, 73, 14054956, "Australia", 1976],
+ [24563, 73.9, 23439940, "Canada", 1976],
+ [891, 62.4, 921688199, "China", 1976],
+ [11334, 74.6, 9544268, "Cuba", 1976],
+ [19268, 72, 4726803, "Finland", 1976],
+ [21661, 73.4, 53293030, "France", 1976],
+ [24904, 72.3, 78604473, "Germany", 1976],
+ [19978, 75.2, 220162, "Iceland", 1976],
+ [1201, 51.4, 636182810, "India", 1976],
+ [17117, 74.9, 111992858, "Japan", 1976],
+ [21749, 72.3, 3108745, "New Zealand", 1976],
+ [29117, 75, 4025297, "Norway", 1976],
+ [11605, 70.8, 34468877, "Poland", 1976],
+ [17192, 68, 134583945, "Russia", 1976],
+ [9142, 60, 40100696, "Turkey", 1976],
+ [19207, 72.9, 56212943, "United Kingdom", 1976],
+ [27041, 72.9, 220993166, "United States", 1976],
+ [22373, 73.4, 14211657, "Australia", 1977],
+ [25095, 74.2, 23723801, "Canada", 1977],
+ [904, 63.3, 936554514, "China", 1977],
+ [11712, 74.4, 9634677, "Cuba", 1977],
+ [19261, 72.4, 4738949, "Finland", 1977],
+ [22270, 73.8, 53509578, "France", 1977],
+ [25678, 72.6, 78524727, "Germany", 1977],
+ [21583, 75.6, 222142, "Iceland", 1977],
+ [1266, 52, 650907559, "India", 1977],
+ [17705, 75.3, 113067848, "Japan", 1977],
+ [20623, 72.4, 3122551, "New Zealand", 1977],
+ [30319, 75.2, 4041789, "Norway", 1977],
+ [11713, 70.6, 34779313, "Poland", 1977],
+ [17487, 67.8, 135406786, "Russia", 1977],
+ [8863, 60.9, 41020211, "Turkey", 1977],
+ [19684, 73.1, 56224944, "United Kingdom", 1977],
+ [27990, 73.2, 223090871, "United States", 1977],
+ [22763, 73.8, 14368543, "Australia", 1978],
+ [25853, 74.4, 23994948, "Canada", 1978],
+ [1016, 63.7, 950537317, "China", 1978],
+ [12312, 74.5, 9711393, "Cuba", 1978],
+ [19608, 72.9, 4749940, "Finland", 1978],
+ [22928, 74.1, 53685486, "France", 1978],
+ [26444, 72.7, 78426715, "Germany", 1978],
+ [22659, 76, 224019, "Iceland", 1978],
+ [1305, 52.6, 665936435, "India", 1978],
+ [18484, 75.7, 114054587, "Japan", 1978],
+ [20707, 72.7, 3129098, "New Zealand", 1978],
+ [31348, 75.3, 4056280, "Norway", 1978],
+ [12033, 70.7, 35100942, "Poland", 1978],
+ [17818, 67.7, 136259517, "Russia", 1978],
+ [8400, 61.4, 41953105, "Turkey", 1978],
+ [20337, 73, 56223974, "United Kingdom", 1978],
+ [29281, 73.5, 225239456, "United States", 1978],
+ [23697, 74.2, 14532401, "Australia", 1979],
+ [26665, 74.7, 24257594, "Canada", 1979],
+ [1059, 64, 964155176, "China", 1979],
+ [12519, 74.6, 9777287, "Cuba", 1979],
+ [20918, 73.3, 4762758, "Finland", 1979],
+ [23647, 74.3, 53857610, "France", 1979],
+ [27515, 72.9, 78305017, "Germany", 1979],
+ [23523, 76.4, 225972, "Iceland", 1979],
+ [1211, 53.1, 681358553, "India", 1979],
+ [19346, 76.1, 114993274, "Japan", 1979],
+ [21144, 73, 3135453, "New Zealand", 1979],
+ [32737, 75.5, 4069626, "Norway", 1979],
+ [11703, 70.7, 35435627, "Poland", 1979],
+ [17632, 67.4, 137144808, "Russia", 1979],
+ [8160, 62, 42912350, "Turkey", 1979],
+ [20871, 73.1, 56220089, "United Kingdom", 1979],
+ [29951, 73.7, 227411604, "United States", 1979],
+ [23872, 74.5, 14708323, "Australia", 1980],
+ [26678, 75, 24515788, "Canada", 1980],
+ [1073, 64.5, 977837433, "China", 1980],
+ [12284, 74.6, 9835177, "Cuba", 1980],
+ [21965, 73.7, 4779454, "Finland", 1980],
+ [23962, 74.5, 54053224, "France", 1980],
+ [27765, 73.1, 78159527, "Germany", 1980],
+ [24580, 76.7, 228127, "Iceland", 1980],
+ [1270, 53.6, 697229745, "India", 1980],
+ [19741, 76.3, 115912104, "Japan", 1980],
+ [21259, 73.2, 3146771, "New Zealand", 1980],
+ [34346, 75.7, 4082525, "Norway", 1980],
+ [11307, 70.6, 35782855, "Poland", 1980],
+ [17557, 67.3, 138063062, "Russia", 1980],
+ [7828, 62.7, 43905790, "Turkey", 1980],
+ [20417, 73.4, 56221513, "United Kingdom", 1980],
+ [29619, 73.8, 229588208, "United States", 1980],
+ [24308, 74.8, 14898019, "Australia", 1981],
+ [27171, 75.4, 24768525, "Canada", 1981],
+ [1099, 64.8, 991553829, "China", 1981],
+ [13224, 74.6, 9884219, "Cuba", 1981],
+ [22279, 74, 4800899, "Finland", 1981],
+ [24186, 74.8, 54279038, "France", 1981],
+ [27846, 73.4, 77990369, "Germany", 1981],
+ [25312, 76.9, 230525, "Iceland", 1981],
+ [1322, 54.2, 713561406, "India", 1981],
+ [20413, 76.7, 116821569, "Japan", 1981],
+ [22191, 73.5, 3164965, "New Zealand", 1981],
+ [34659, 75.8, 4095177, "Norway", 1981],
+ [10610, 71, 36145211, "Poland", 1981],
+ [17619, 67.5, 139006739, "Russia", 1981],
+ [8518, 63.2, 44936836, "Turkey", 1981],
+ [20149, 73.8, 56231020, "United Kingdom", 1981],
+ [30070, 74, 231765783, "United States", 1981],
+ [23884, 75, 15101227, "Australia", 1982],
+ [26031, 75.8, 25017501, "Canada", 1982],
+ [1175, 65.2, 1005328574, "China", 1982],
+ [13421, 74.7, 9925618, "Cuba", 1982],
+ [22873, 74.3, 4826135, "Finland", 1982],
+ [24753, 75, 54528408, "France", 1982],
+ [27645, 73.6, 77812348, "Germany", 1982],
+ [25455, 77.1, 233121, "Iceland", 1982],
+ [1334, 54.6, 730303461, "India", 1982],
+ [20951, 77, 117708919, "Japan", 1982],
+ [22436, 73.7, 3188664, "New Zealand", 1982],
+ [34704, 75.9, 4107655, "Norway", 1982],
+ [10420, 71.2, 36517072, "Poland", 1982],
+ [17951, 67.9, 139969243, "Russia", 1982],
+ [8323, 63.7, 45997940, "Turkey", 1982],
+ [20607, 74.1, 56250124, "United Kingdom", 1982],
+ [29230, 74.4, 233953874, "United States", 1982],
+ [23584, 75.3, 15318254, "Australia", 1983],
+ [26525, 76.1, 25272656, "Canada", 1983],
+ [1229, 65.6, 1019698475, "China", 1983],
+ [13669, 74.6, 9966733, "Cuba", 1983],
+ [23351, 74.5, 4853196, "Finland", 1983],
+ [25188, 75.2, 54799049, "France", 1983],
+ [28227, 74, 77657451, "Germany", 1983],
+ [24594, 77.3, 235860, "Iceland", 1983],
+ [1412, 55.1, 747374856, "India", 1983],
+ [21446, 77.1, 118552097, "Japan", 1983],
+ [22808, 73.9, 3215826, "New Zealand", 1983],
+ [35932, 76, 4120386, "Norway", 1983],
+ [10835, 71.1, 36879742, "Poland", 1983],
+ [18417, 67.7, 140951400, "Russia", 1983],
+ [8535, 64.2, 47072603, "Turkey", 1983],
+ [21357, 74.3, 56283959, "United Kingdom", 1983],
+ [30185, 74.6, 236161961, "United States", 1983],
+ [24934, 75.5, 15548591, "Australia", 1984],
+ [27781, 76.4, 25546736, "Canada", 1984],
+ [1456, 66, 1035328572, "China", 1984],
+ [14019, 74.4, 10017061, "Cuba", 1984],
+ [23926, 74.6, 4879222, "Finland", 1984],
+ [25497, 75.5, 55084677, "France", 1984],
+ [29135, 74.4, 77566776, "Germany", 1984],
+ [25356, 77.4, 238647, "Iceland", 1984],
+ [1436, 55.5, 764664278, "India", 1984],
+ [22268, 77.4, 119318921, "Japan", 1984],
+ [23698, 74.1, 3243078, "New Zealand", 1984],
+ [38057, 76.1, 4133833, "Norway", 1984],
+ [11138, 70.8, 37208529, "Poland", 1984],
+ [18527, 67.4, 141955200, "Russia", 1984],
+ [8798, 64.8, 48138191, "Turkey", 1984],
+ [21904, 74.6, 56337848, "United Kingdom", 1984],
+ [32110, 74.8, 238404223, "United States", 1984],
+ [25875, 75.7, 15791043, "Australia", 1985],
+ [29016, 76.5, 25848173, "Canada", 1985],
+ [1557, 66.4, 1052622410, "China", 1985],
+ [14135, 74.3, 10082990, "Cuba", 1985],
+ [24630, 74.7, 4902219, "Finland", 1985],
+ [25917, 75.7, 55379923, "France", 1985],
+ [29851, 74.6, 77570009, "Germany", 1985],
+ [25997, 77.6, 241411, "Iceland", 1985],
+ [1462, 55.9, 782085127, "India", 1985],
+ [23554, 77.8, 119988663, "Japan", 1985],
+ [23750, 74.2, 3268192, "New Zealand", 1985],
+ [40031, 76.1, 4148355, "Norway", 1985],
+ [11159, 70.7, 37486105, "Poland", 1985],
+ [18576, 68.2, 142975753, "Russia", 1985],
+ [9163, 65.2, 49178079, "Turkey", 1985],
+ [22648, 74.7, 56415196, "United Kingdom", 1985],
+ [33065, 74.8, 240691557, "United States", 1985],
+ [26057, 76, 16047026, "Australia", 1986],
+ [29482, 76.6, 26181342, "Canada", 1986],
+ [1604, 66.8, 1071834975, "China", 1986],
+ [14025, 74.5, 10167998, "Cuba", 1986],
+ [25133, 74.7, 4921293, "Finland", 1986],
+ [26453, 76, 55686610, "France", 1986],
+ [30514, 74.8, 77671877, "Germany", 1986],
+ [27379, 77.6, 244145, "Iceland", 1986],
+ [1493, 56.3, 799607235, "India", 1986],
+ [24116, 78.1, 120551455, "Japan", 1986],
+ [24180, 74.2, 3290132, "New Zealand", 1986],
+ [41450, 76.1, 4164166, "Norway", 1986],
+ [11429, 70.9, 37703942, "Poland", 1986],
+ [19221, 69.8, 144016095, "Russia", 1986],
+ [9556, 65.7, 50187091, "Turkey", 1986],
+ [23516, 74.9, 56519444, "United Kingdom", 1986],
+ [33899, 74.9, 243032017, "United States", 1986],
+ [26969, 76.2, 16314778, "Australia", 1987],
+ [30288, 76.8, 26541981, "Canada", 1987],
+ [1652, 67.2, 1092646739, "China", 1987],
+ [13805, 74.6, 10269276, "Cuba", 1987],
+ [26086, 74.7, 4937259, "Finland", 1987],
+ [26963, 76.4, 56005443, "France", 1987],
+ [30986, 75.1, 77864381, "Germany", 1987],
+ [29335, 77.7, 246867, "Iceland", 1987],
+ [1525, 56.6, 817232241, "India", 1987],
+ [25018, 78.4, 121021830, "Japan", 1987],
+ [24222, 74.4, 3310408, "New Zealand", 1987],
+ [42225, 76.1, 4181326, "Norway", 1987],
+ [11207, 71.1, 37867481, "Poland", 1987],
+ [19355, 70.1, 145056221, "Russia", 1987],
+ [10351, 66.1, 51168841, "Turkey", 1987],
+ [24551, 75.1, 56649375, "United Kingdom", 1987],
+ [34787, 75, 245425409, "United States", 1987],
+ [27757, 76.4, 16585905, "Australia", 1988],
+ [31356, 77.1, 26919036, "Canada", 1988],
+ [1597, 67.5, 1114162025, "China", 1988],
+ [13925, 74.6, 10379080, "Cuba", 1988],
+ [27282, 74.8, 4951886, "Finland", 1988],
+ [28101, 76.6, 56328053, "France", 1988],
+ [31906, 75.3, 78146938, "Germany", 1988],
+ [28780, 77.8, 249563, "Iceland", 1988],
+ [1649, 57, 834944397, "India", 1988],
+ [26724, 78.6, 121432942, "Japan", 1988],
+ [24060, 74.6, 3332297, "New Zealand", 1988],
+ [42101, 76.3, 4199817, "Norway", 1988],
+ [11418, 71.2, 37990683, "Poland", 1988],
+ [19660, 70, 146040116, "Russia", 1988],
+ [10421, 66.5, 52126497, "Turkey", 1988],
+ [25750, 75.3, 56797704, "United Kingdom", 1988],
+ [35929, 75, 247865202, "United States", 1988],
+ [28556, 76.6, 16849253, "Australia", 1989],
+ [31550, 77.2, 27296517, "Canada", 1989],
+ [1474, 67.7, 1135128009, "China", 1989],
+ [13829, 74.7, 10486110, "Cuba", 1989],
+ [28735, 74.8, 4967776, "Finland", 1989],
+ [28942, 76.9, 56643349, "France", 1989],
+ [32706, 75.4, 78514790, "Germany", 1989],
+ [28629, 78, 252219, "Iceland", 1989],
+ [1723, 57.3, 852736160, "India", 1989],
+ [28077, 78.9, 121831143, "Japan", 1989],
+ [24206, 75, 3360350, "New Zealand", 1989],
+ [42449, 76.5, 4219532, "Norway", 1989],
+ [11212, 71.1, 38094812, "Poland", 1989],
+ [19906, 69.8, 146895053, "Russia", 1989],
+ [10103, 66.9, 53066569, "Turkey", 1989],
+ [26279, 75.5, 56953861, "United Kingdom", 1989],
+ [36830, 75.2, 250340795, "United States", 1989],
+ [28604, 77, 17096869, "Australia", 1990],
+ [31163, 77.4, 27662440, "Canada", 1990],
+ [1516, 68, 1154605773, "China", 1990],
+ [13670, 74.7, 10582082, "Cuba", 1990],
+ [28599, 75, 4986705, "Finland", 1990],
+ [29476, 77.1, 56943299, "France", 1990],
+ [31476, 75.4, 78958237, "Germany", 1990],
+ [28666, 78.1, 254830, "Iceland", 1990],
+ [1777, 57.7, 870601776, "India", 1990],
+ [29550, 79.1, 122249285, "Japan", 1990],
+ [24021, 75.4, 3397534, "New Zealand", 1990],
+ [43296, 76.8, 4240375, "Norway", 1990],
+ [10088, 70.8, 38195258, "Poland", 1990],
+ [19349, 69.6, 147568552, "Russia", 1990],
+ [10670, 67.3, 53994605, "Turkey", 1990],
+ [26424, 75.7, 57110117, "United Kingdom", 1990],
+ [37062, 75.4, 252847810, "United States", 1990],
+ [28122, 77.4, 17325818, "Australia", 1991],
+ [30090, 77.6, 28014102, "Canada", 1991],
+ [1634, 68.3, 1172327831, "China", 1991],
+ [12113, 74.7, 10664577, "Cuba", 1991],
+ [26761, 75.4, 5009381, "Finland", 1991],
+ [29707, 77.3, 57226524, "France", 1991],
+ [32844, 75.6, 79483739, "Germany", 1991],
+ [28272, 78.3, 257387, "Iceland", 1991],
+ [1760, 58, 888513869, "India", 1991],
+ [30437, 79.2, 122702527, "Japan", 1991],
+ [22636, 75.8, 3445596, "New Zealand", 1991],
+ [44419, 77.1, 4262367, "Norway", 1991],
+ [9347, 70.7, 38297549, "Poland", 1991],
+ [18332, 69.4, 148040354, "Russia", 1991],
+ [10568, 67.6, 54909508, "Turkey", 1991],
+ [26017, 76, 57264600, "United Kingdom", 1991],
+ [36543, 75.6, 255367160, "United States", 1991],
+ [27895, 77.7, 17538387, "Australia", 1992],
+ [29977, 77.7, 28353843, "Canada", 1992],
+ [1845, 68.6, 1188450231, "China", 1992],
+ [10637, 74.8, 10735775, "Cuba", 1992],
+ [25726, 75.8, 5034898, "Finland", 1992],
+ [30033, 77.5, 57495252, "France", 1992],
+ [33221, 75.9, 80075940, "Germany", 1992],
+ [26977, 78.5, 259895, "Iceland", 1992],
+ [1821, 58.3, 906461358, "India", 1992],
+ [30610, 79.4, 123180357, "Japan", 1992],
+ [22651, 76.1, 3502765, "New Zealand", 1992],
+ [45742, 77.3, 4285504, "Norway", 1992],
+ [9553, 71.1, 38396826, "Poland", 1992],
+ [15661, 68, 148322473, "Russia", 1992],
+ [10920, 67.9, 55811134, "Turkey", 1992],
+ [26062, 76.3, 57419469, "United Kingdom", 1992],
+ [37321, 75.8, 257908206, "United States", 1992],
+ [28732, 78, 17738428, "Australia", 1993],
+ [30424, 77.8, 28680921, "Canada", 1993],
+ [2078, 68.9, 1202982955, "China", 1993],
+ [9001, 74.8, 10797556, "Cuba", 1993],
+ [25414, 76.2, 5061465, "Finland", 1993],
+ [29719, 77.7, 57749881, "France", 1993],
+ [32689, 76.2, 80675999, "Germany", 1993],
+ [27055, 78.7, 262383, "Iceland", 1993],
+ [1871, 58.6, 924475633, "India", 1993],
+ [30587, 79.6, 123658854, "Japan", 1993],
+ [23830, 76.5, 3564227, "New Zealand", 1993],
+ [46765, 77.6, 4309606, "Norway", 1993],
+ [9884, 71.7, 38485892, "Poland", 1993],
+ [14320, 65.2, 148435811, "Russia", 1993],
+ [11569, 68.3, 56707454, "Turkey", 1993],
+ [26688, 76.5, 57575969, "United Kingdom", 1993],
+ [37844, 75.7, 260527420, "United States", 1993],
+ [29580, 78.2, 17932214, "Australia", 1994],
+ [31505, 77.9, 28995822, "Canada", 1994],
+ [2323, 69.3, 1216067023, "China", 1994],
+ [9018, 74.8, 10853435, "Cuba", 1994],
+ [26301, 76.5, 5086499, "Finland", 1994],
+ [30303, 77.9, 57991973, "France", 1994],
+ [33375, 76.4, 81206786, "Germany", 1994],
+ [27789, 78.8, 264893, "Iceland", 1994],
+ [1959, 59, 942604211, "India", 1994],
+ [30746, 79.8, 124101546, "Japan", 1994],
+ [24716, 76.7, 3623181, "New Zealand", 1994],
+ [48850, 77.8, 4334434, "Norway", 1994],
+ [10386, 71.8, 38553355, "Poland", 1994],
+ [12535, 63.6, 148416292, "Russia", 1994],
+ [10857, 68.6, 57608769, "Turkey", 1994],
+ [27691, 76.7, 57736667, "United Kingdom", 1994],
+ [38892, 75.8, 263301323, "United States", 1994],
+ [30359, 78.4, 18124770, "Australia", 1995],
+ [32101, 78, 29299478, "Canada", 1995],
+ [2551, 69.6, 1227841281, "China", 1995],
+ [9195, 74.9, 10906048, "Cuba", 1995],
+ [27303, 76.7, 5108176, "Finland", 1995],
+ [30823, 78.1, 58224051, "France", 1995],
+ [33843, 76.6, 81612900, "Germany", 1995],
+ [27671, 78.9, 267454, "Iceland", 1995],
+ [2069, 59.3, 960874982, "India", 1995],
+ [31224, 79.9, 124483305, "Japan", 1995],
+ [25476, 76.9, 3674886, "New Zealand", 1995],
+ [50616, 78, 4359788, "Norway", 1995],
+ [11093, 72, 38591860, "Poland", 1995],
+ [12013, 64.2, 148293265, "Russia", 1995],
+ [11530, 69, 58522320, "Turkey", 1995],
+ [28317, 76.8, 57903790, "United Kingdom", 1995],
+ [39476, 75.9, 266275528, "United States", 1995],
+ [31145, 78.6, 18318340, "Australia", 1996],
+ [32290, 78.3, 29590952, "Canada", 1996],
+ [2775, 69.9, 1238234851, "China", 1996],
+ [9871, 75.2, 10955372, "Cuba", 1996],
+ [28210, 76.9, 5126021, "Finland", 1996],
+ [31141, 78.4, 58443318, "France", 1996],
+ [34008, 76.9, 81870772, "Germany", 1996],
+ [28839, 79.1, 270089, "Iceland", 1996],
+ [2186, 59.6, 979290432, "India", 1996],
+ [31958, 80.3, 124794817, "Japan", 1996],
+ [25984, 77.1, 3717239, "New Zealand", 1996],
+ [52892, 78.1, 4385951, "Norway", 1996],
+ [11776, 72.4, 38599825, "Poland", 1996],
+ [11597, 65.9, 148078355, "Russia", 1996],
+ [12190, 69.4, 59451488, "Turkey", 1996],
+ [28998, 76.9, 58079322, "United Kingdom", 1996],
+ [40501, 76.3, 269483224, "United States", 1996],
+ [32013, 78.9, 18512971, "Australia", 1997],
+ [33310, 78.7, 29871092, "Canada", 1997],
+ [3000, 70.3, 1247259143, "China", 1997],
+ [10106, 75.3, 11000431, "Cuba", 1997],
+ [29884, 77.1, 5140755, "Finland", 1997],
+ [31756, 78.7, 58652709, "France", 1997],
+ [34578, 77.3, 81993831, "Germany", 1997],
+ [30009, 79.3, 272798, "Iceland", 1997],
+ [2235, 60, 997817250, "India", 1997],
+ [32391, 80.6, 125048424, "Japan", 1997],
+ [26152, 77.4, 3752102, "New Zealand", 1997],
+ [55386, 78.2, 4412958, "Norway", 1997],
+ [12602, 72.7, 38583109, "Poland", 1997],
+ [11779, 67.4, 147772805, "Russia", 1997],
+ [12911, 69.8, 60394104, "Turkey", 1997],
+ [29662, 77.2, 58263858, "United Kingdom", 1997],
+ [41812, 76.8, 272882865, "United States", 1997],
+ [33085, 79.1, 18709175, "Australia", 1998],
+ [34389, 78.9, 30145148, "Canada", 1998],
+ [3205, 70.7, 1255262566, "China", 1998],
+ [10086, 75.4, 11041893, "Cuba", 1998],
+ [31423, 77.3, 5153229, "Finland", 1998],
+ [32764, 78.8, 58867465, "France", 1998],
+ [35254, 77.7, 82010184, "Germany", 1998],
+ [31601, 79.5, 275568, "Iceland", 1998],
+ [2332, 60.3, 1016402907, "India", 1998],
+ [31656, 80.6, 125266403, "Japan", 1998],
+ [26077, 77.8, 3783516, "New Zealand", 1998],
+ [56502, 78.3, 4440109, "Norway", 1998],
+ [13225, 73, 38550777, "Poland", 1998],
+ [11173, 67.6, 147385440, "Russia", 1998],
+ [13008, 70.4, 61344874, "Turkey", 1998],
+ [30614, 77.4, 58456989, "United Kingdom", 1998],
+ [43166, 77, 276354096, "United States", 1998],
+ [34346, 79.3, 18906936, "Australia", 1999],
+ [35810, 79.1, 30420216, "Canada", 1999],
+ [3419, 71.1, 1262713651, "China", 1999],
+ [10674, 75.6, 11080506, "Cuba", 1999],
+ [32743, 77.5, 5164780, "Finland", 1999],
+ [33707, 78.9, 59107738, "France", 1999],
+ [35931, 77.9, 81965830, "Germany", 1999],
+ [32521, 79.7, 278376, "Iceland", 1999],
+ [2496, 60.7, 1034976626, "India", 1999],
+ [31535, 80.7, 125481050, "Japan", 1999],
+ [27371, 78.1, 3817489, "New Zealand", 1999],
+ [57246, 78.5, 4466468, "Norway", 1999],
+ [13824, 73.2, 38515359, "Poland", 1999],
+ [11925, 66.2, 146924174, "Russia", 1999],
+ [12381, 70.3, 62295617, "Turkey", 1999],
+ [31474, 77.6, 58657794, "United Kingdom", 1999],
+ [44673, 77.1, 279730801, "United States", 1999],
+ [35253, 79.7, 19107251, "Australia", 2000],
+ [37314, 79.3, 30701903, "Canada", 2000],
+ [3678, 71.5, 1269974572, "China", 2000],
+ [11268, 75.9, 11116787, "Cuba", 2000],
+ [34517, 77.8, 5176482, "Finland", 2000],
+ [34774, 79.1, 59387183, "France", 2000],
+ [36953, 78.1, 81895925, "Germany", 2000],
+ [33599, 79.9, 281214, "Iceland", 2000],
+ [2548, 61.1, 1053481072, "India", 2000],
+ [32193, 81.1, 125714674, "Japan", 2000],
+ [27963, 78.5, 3858234, "New Zealand", 2000],
+ [58699, 78.7, 4491572, "Norway", 2000],
+ [14565, 73.8, 38486305, "Poland", 2000],
+ [13173, 65.4, 146400951, "Russia", 2000],
+ [13025, 71.5, 63240157, "Turkey", 2000],
+ [32543, 77.8, 58867004, "United Kingdom", 2000],
+ [45986, 77.1, 282895741, "United States", 2000],
+ [35452, 80.1, 19308681, "Australia", 2001],
+ [37563, 79.5, 30991344, "Canada", 2001],
+ [3955, 71.9, 1277188787, "China", 2001],
+ [11588, 76.2, 11151472, "Cuba", 2001],
+ [35327, 78.2, 5188446, "Finland", 2001],
+ [35197, 79.2, 59711914, "France", 2001],
+ [37517, 78.3, 81809438, "Germany", 2001],
+ [34403, 80.2, 284037, "Iceland", 2001],
+ [2628, 61.5, 1071888190, "India", 2001],
+ [32230, 81.4, 125974298, "Japan", 2001],
+ [28752, 78.8, 3906911, "New Zealand", 2001],
+ [59620, 78.9, 4514907, "Norway", 2001],
+ [14744, 74.3, 38466543, "Poland", 2001],
+ [13902, 65.1, 145818121, "Russia", 2001],
+ [12106, 72, 64182694, "Turkey", 2001],
+ [33282, 78, 59080221, "United Kingdom", 2001],
+ [45978, 77.1, 285796198, "United States", 2001],
+ [36375, 80.4, 19514385, "Australia", 2002],
+ [38270, 79.7, 31288572, "Canada", 2002],
+ [4285, 72.4, 1284349938, "China", 2002],
+ [11715, 76.6, 11184540, "Cuba", 2002],
+ [35834, 78.5, 5200632, "Finland", 2002],
+ [35333, 79.4, 60075783, "France", 2002],
+ [37458, 78.5, 81699829, "Germany", 2002],
+ [34252, 80.5, 286865, "Iceland", 2002],
+ [2684, 61.9, 1090189358, "India", 2002],
+ [32248, 81.7, 126249509, "Japan", 2002],
+ [29637, 79, 3961695, "New Zealand", 2002],
+ [60152, 79.2, 4537240, "Norway", 2002],
+ [14964, 74.6, 38454823, "Poland", 2002],
+ [14629, 64.9, 145195521, "Russia", 2002],
+ [12669, 72.5, 65125766, "Turkey", 2002],
+ [33954, 78.2, 59301235, "United Kingdom", 2002],
+ [46367, 77.2, 288470847, "United States", 2002],
+ [37035, 80.7, 19735255, "Australia", 2003],
+ [38621, 79.9, 31596593, "Canada", 2003],
+ [4685, 72.9, 1291485488, "China", 2003],
+ [12123, 76.8, 11214837, "Cuba", 2003],
+ [36461, 78.6, 5213800, "Finland", 2003],
+ [35371, 79.7, 60464857, "France", 2003],
+ [37167, 78.8, 81569481, "Germany", 2003],
+ [34938, 80.8, 289824, "Iceland", 2003],
+ [2850, 62.4, 1108369577, "India", 2003],
+ [32721, 81.8, 126523884, "Japan", 2003],
+ [30404, 79.3, 4020195, "New Zealand", 2003],
+ [60351, 79.5, 4560947, "Norway", 2003],
+ [15508, 74.9, 38451227, "Poland", 2003],
+ [15768, 64.8, 144583147, "Russia", 2003],
+ [13151, 72.9, 66060121, "Turkey", 2003],
+ [35250, 78.5, 59548421, "United Kingdom", 2003],
+ [47260, 77.3, 291005482, "United States", 2003],
+ [38130, 81, 19985475, "Australia", 2004],
+ [39436, 80.1, 31918582, "Canada", 2004],
+ [5127, 73.4, 1298573031, "China", 2004],
+ [12791, 76.9, 11240680, "Cuba", 2004],
+ [37783, 78.6, 5228842, "Finland", 2004],
+ [36090, 80.1, 60858654, "France", 2004],
+ [37614, 79.1, 81417791, "Germany", 2004],
+ [37482, 81.1, 293084, "Iceland", 2004],
+ [3029, 62.8, 1126419321, "India", 2004],
+ [33483, 82, 126773081, "Japan", 2004],
+ [31098, 79.5, 4078779, "New Zealand", 2004],
+ [62370, 79.7, 4589241, "Norway", 2004],
+ [16314, 75, 38454520, "Poland", 2004],
+ [16967, 65, 144043914, "Russia", 2004],
+ [14187, 73.4, 66973561, "Turkey", 2004],
+ [35910, 78.8, 59846226, "United Kingdom", 2004],
+ [48597, 77.6, 293530886, "United States", 2004],
+ [38840, 81.2, 20274282, "Australia", 2005],
+ [40284, 80.3, 32256333, "Canada", 2005],
+ [5675, 73.9, 1305600630, "China", 2005],
+ [14200, 77.1, 11261052, "Cuba", 2005],
+ [38700, 78.8, 5246368, "Finland", 2005],
+ [36395, 80.4, 61241700, "France", 2005],
+ [37901, 79.4, 81246801, "Germany", 2005],
+ [39108, 81.3, 296745, "Iceland", 2005],
+ [3262, 63.2, 1144326293, "India", 2005],
+ [33916, 82.2, 126978754, "Japan", 2005],
+ [31798, 79.8, 4134699, "New Zealand", 2005],
+ [63573, 80.1, 4624388, "Norway", 2005],
+ [16900, 75, 38463514, "Poland", 2005],
+ [18118, 64.8, 143622566, "Russia", 2005],
+ [15176, 73.8, 67860617, "Turkey", 2005],
+ [36665, 79.1, 60210012, "United Kingdom", 2005],
+ [49762, 77.7, 296139635, "United States", 2005],
+ [39416, 81.4, 20606228, "Australia", 2006],
+ [41012, 80.5, 32611436, "Canada", 2006],
+ [6360, 74.4, 1312600877, "China", 2006],
+ [15901, 77.4, 11275199, "Cuba", 2006],
+ [40115, 79, 5266600, "Finland", 2006],
+ [37001, 80.7, 61609991, "France", 2006],
+ [39352, 79.7, 81055904, "Germany", 2006],
+ [39818, 81.5, 300887, "Iceland", 2006],
+ [3514, 63.6, 1162088305, "India", 2006],
+ [34468, 82.3, 127136576, "Japan", 2006],
+ [32281, 80, 4187584, "New Zealand", 2006],
+ [64573, 80.4, 4667105, "Norway", 2006],
+ [17959, 75, 38478763, "Poland", 2006],
+ [19660, 66.1, 143338407, "Russia", 2006],
+ [16013, 74.3, 68704721, "Turkey", 2006],
+ [37504, 79.3, 60648850, "United Kingdom", 2006],
+ [50599, 77.8, 298860519, "United States", 2006],
+ [40643, 81.5, 20975949, "Australia", 2007],
+ [41432, 80.6, 32982275, "Canada", 2007],
+ [7225, 74.9, 1319625197, "China", 2007],
+ [17055, 77.6, 11284043, "Cuba", 2007],
+ [42016, 79.2, 5289333, "Finland", 2007],
+ [37641, 80.9, 61966193, "France", 2007],
+ [40693, 79.8, 80854515, "Germany", 2007],
+ [42598, 81.8, 305415, "Iceland", 2007],
+ [3806, 64, 1179685631, "India", 2007],
+ [35183, 82.5, 127250015, "Japan", 2007],
+ [32928, 80.1, 4238021, "New Zealand", 2007],
+ [65781, 80.6, 4716584, "Norway", 2007],
+ [19254, 75.1, 38500356, "Poland", 2007],
+ [21374, 67.2, 143180249, "Russia", 2007],
+ [16551, 74.7, 69515492, "Turkey", 2007],
+ [38164, 79.4, 61151820, "United Kingdom", 2007],
+ [51011, 78.1, 301655953, "United States", 2007],
+ [41312, 81.5, 21370348, "Australia", 2008],
+ [41468, 80.7, 33363256, "Canada", 2008],
+ [7880, 75.1, 1326690636, "China", 2008],
+ [17765, 77.8, 11290239, "Cuba", 2008],
+ [42122, 79.4, 5314170, "Finland", 2008],
+ [37505, 81, 62309529, "France", 2008],
+ [41199, 80, 80665906, "Germany", 2008],
+ [42294, 82, 310033, "Iceland", 2008],
+ [3901, 64.4, 1197070109, "India", 2008],
+ [34800, 82.6, 127317900, "Japan", 2008],
+ [32122, 80.2, 4285380, "New Zealand", 2008],
+ [65216, 80.7, 4771633, "Norway", 2008],
+ [19996, 75.3, 38525752, "Poland", 2008],
+ [22506, 67.6, 143123163, "Russia", 2008],
+ [16454, 75.1, 70344357, "Turkey", 2008],
+ [37739, 79.5, 61689620, "United Kingdom", 2008],
+ [50384, 78.2, 304473143, "United States", 2008],
+ [41170, 81.6, 21770690, "Australia", 2009],
+ [39884, 80.9, 33746559, "Canada", 2009],
+ [8565, 75.6, 1333807063, "China", 2009],
+ [18035, 77.9, 11297442, "Cuba", 2009],
+ [38455, 79.7, 5340485, "Finland", 2009],
+ [36215, 81, 62640901, "France", 2009],
+ [38975, 80, 80519685, "Germany", 2009],
+ [39979, 82.2, 314336, "Iceland", 2009],
+ [4177, 64.7, 1214182182, "India", 2009],
+ [32880, 82.8, 127340884, "Japan", 2009],
+ [31723, 80.3, 4329124, "New Zealand", 2009],
+ [63354, 80.8, 4830371, "Norway", 2009],
+ [20507, 75.6, 38551489, "Poland", 2009],
+ [20739, 68.3, 143126660, "Russia", 2009],
+ [15467, 75.4, 71261307, "Turkey", 2009],
+ [35840, 79.7, 62221164, "United Kingdom", 2009],
+ [48558, 78.3, 307231961, "United States", 2009],
+ [41330, 81.7, 22162863, "Australia", 2010],
+ [40773, 81.1, 34126173, "Canada", 2010],
+ [9430, 75.9, 1340968737, "China", 2010],
+ [18477, 78, 11308133, "Cuba", 2010],
+ [39425, 80, 5367693, "Finland", 2010],
+ [36745, 81.2, 62961136, "France", 2010],
+ [40632, 80.2, 80435307, "Germany", 2010],
+ [38809, 82.5, 318042, "Iceland", 2010],
+ [4547, 65.1, 1230984504, "India", 2010],
+ [34404, 83, 127319802, "Japan", 2010],
+ [31824, 80.5, 4369027, "New Zealand", 2010],
+ [62946, 80.9, 4891251, "Norway", 2010],
+ [21328, 76.1, 38574682, "Poland", 2010],
+ [21664, 68.7, 143158099, "Russia", 2010],
+ [16674, 75.7, 72310416, "Turkey", 2010],
+ [36240, 80, 62716684, "United Kingdom", 2010],
+ [49373, 78.5, 309876170, "United States", 2010],
+ [41706, 81.8, 22542371, "Australia", 2011],
+ [41567, 81.3, 34499905, "Canada", 2011],
+ [10274, 76.1, 1348174478, "China", 2011],
+ [19005, 78.1, 11323570, "Cuba", 2011],
+ [40251, 80.3, 5395816, "Finland", 2011],
+ [37328, 81.4, 63268405, "France", 2011],
+ [42080, 80.3, 80424665, "Germany", 2011],
+ [39619, 82.7, 321030, "Iceland", 2011],
+ [4787, 65.5, 1247446011, "India", 2011],
+ [34316, 82.8, 127252900, "Japan", 2011],
+ [32283, 80.6, 4404483, "New Zealand", 2011],
+ [62737, 81.1, 4953945, "Norway", 2011],
+ [22333, 76.5, 38594217, "Poland", 2011],
+ [22570, 69.4, 143211476, "Russia", 2011],
+ [17908, 76, 73517002, "Turkey", 2011],
+ [36549, 80.4, 63164949, "United Kingdom", 2011],
+ [49781, 78.7, 312390368, "United States", 2011],
+ [42522, 81.8, 22911375, "Australia", 2012],
+ [41865, 81.4, 34868151, "Canada", 2012],
+ [11017, 76.3, 1355386952, "China", 2012],
+ [19586, 78.2, 11342631, "Cuba", 2012],
+ [39489, 80.5, 5424644, "Finland", 2012],
+ [37227, 81.6, 63561798, "France", 2012],
+ [42959, 80.5, 80477952, "Germany", 2012],
+ [39925, 82.8, 323407, "Iceland", 2012],
+ [4967, 65.9, 1263589639, "India", 2012],
+ [34988, 83.2, 127139821, "Japan", 2012],
+ [32806, 80.6, 4435883, "New Zealand", 2012],
+ [63620, 81.3, 5018367, "Norway", 2012],
+ [22740, 76.7, 38609486, "Poland", 2012],
+ [23299, 70.4, 143287536, "Russia", 2012],
+ [18057, 76.2, 74849187, "Turkey", 2012],
+ [36535, 80.8, 63573766, "United Kingdom", 2012],
+ [50549, 78.8, 314799465, "United States", 2012],
+ [42840, 81.8, 23270465, "Australia", 2013],
+ [42213, 81.5, 35230612, "Canada", 2013],
+ [11805, 76.5, 1362514260, "China", 2013],
+ [20122, 78.3, 11362505, "Cuba", 2013],
+ [38788, 80.6, 5453061, "Finland", 2013],
+ [37309, 81.7, 63844529, "France", 2013],
+ [42887, 80.7, 80565861, "Germany", 2013],
+ [40958, 82.8, 325392, "Iceland", 2013],
+ [5244, 66.2, 1279498874, "India", 2013],
+ [35614, 83.3, 126984964, "Japan", 2013],
+ [33360, 80.6, 4465276, "New Zealand", 2013],
+ [63322, 81.4, 5083450, "Norway", 2013],
+ [23144, 76.9, 38618698, "Poland", 2013],
+ [23561, 71.3, 143367341, "Russia", 2013],
+ [18579, 76.3, 76223639, "Turkey", 2013],
+ [36908, 81, 63955654, "United Kingdom", 2013],
+ [51282, 78.9, 317135919, "United States", 2013],
+ [43219, 81.8, 23622353, "Australia", 2014],
+ [42817, 81.6, 35587793, "Canada", 2014],
+ [12609, 76.7, 1369435670, "China", 2014],
+ [20704, 78.4, 11379111, "Cuba", 2014],
+ [38569, 80.7, 5479660, "Finland", 2014],
+ [37218, 81.8, 64121249, "France", 2014],
+ [43444, 80.9, 80646262, "Germany", 2014],
+ [41237, 82.8, 327318, "Iceland", 2014],
+ [5565, 66.5, 1295291543, "India", 2014],
+ [35635, 83.4, 126794564, "Japan", 2014],
+ [33538, 80.6, 4495482, "New Zealand", 2014],
+ [64020, 81.5, 5147970, "Norway", 2014],
+ [23952, 77.1, 38619974, "Poland", 2014],
+ [23293, 72.21, 143429435, "Russia", 2014],
+ [18884, 76.4, 77523788, "Turkey", 2014],
+ [37614, 81.2, 64331348, "United Kingdom", 2014],
+ [52118, 79, 319448634, "United States", 2014],
+ [44056, 81.8, 23968973, "Australia", 2015],
+ [43294, 81.7, 35939927, "Canada", 2015],
+ [13334, 76.9, 1376048943, "China", 2015],
+ [21291, 78.5, 11389562, "Cuba", 2015],
+ [38923, 80.8, 5503457, "Finland", 2015],
+ [37599, 81.9, 64395345, "France", 2015],
+ [44053, 81.1, 80688545, "Germany", 2015],
+ [42182, 82.8, 329425, "Iceland", 2015],
+ [5903, 66.8, 1311050527, "India", 2015],
+ [36162, 83.5, 126573481, "Japan", 2015],
+ [34186, 80.6, 4528526, "New Zealand", 2015],
+ [64304, 81.6, 5210967, "Norway", 2015],
+ [24787, 77.3, 38611794, "Poland", 2015],
+ [23038, 73.13, 143456918, "Russia", 2015],
+ [19360, 76.5, 78665830, "Turkey", 2015],
+ [38225, 81.4, 64715810, "United Kingdom", 2015],
+ [53354, 79.1, 321773631, "United States", 2015]
+ ],
+ defaultDatasourceParallel: [
+ ['Price', 'Net Weight', 'Amount', 'Score'],
+ [12.99, 100, 82, 'Good'],
+ [9.99, 80, 77, 'OK'],
+ [20, 120, 60, 'Excellent']
+ ],
+ defaultDatasource3DGlobe: [[[-75.440806,40.652083],[-80.943139,35.214]],[[-75.440806,40.652083],[-75.241139,39.871944]],[[-99.681897,32.411319],[-97.037997,32.896828]],[[-106.6091944,35.0402222],[-97.037997,32.896828]],[[-106.6091944,35.0402222],[-118.408075,33.942536]],[[-106.6091944,35.0402222],[-87.904842,41.978603]],[[-106.6091944,35.0402222],[-112.011583,33.434278]],[[-2.197778,57.201944],[-0.461389,51.4775]],[[-0.166786,5.605186],[-0.461389,51.4775]],[[-97.230519,31.611289],[-97.037997,32.896828]],[[138.530556,-34.945],[153.1175,-27.384167]],[[138.530556,-34.945],[151.177222,-33.946111]],[[-92.549833,31.3274],[-97.037997,32.896828]],[[-4.499106,36.6749],[-0.461389,51.4775]],[[-81.9645,33.369944],[-80.943139,35.214]],[[-81.9645,33.369944],[-77.037722,38.852083]],[[-102.317858,21.705558],[-97.037997,32.896828]],[[174.791667,-37.008056],[153.1175,-27.384167]],[[174.791667,-37.008056],[-149.611389,-17.556667]],[[174.791667,-37.008056],[151.177222,-33.946111]],[[-73.801692,42.748267],[-80.943139,35.214]],[[-73.801692,42.748267],[-77.037722,38.852083]],[[-73.801692,42.748267],[-75.241139,39.871944]],[[-92.4003,42.5571],[-87.904842,41.978603]],[[-101.705931,35.219369],[-97.037997,32.896828]],[[35.993214,31.722556],[-73.778925,40.639751]],[[35.993214,31.722556],[-87.904842,41.978603]],[[35.993214,31.722556],[-73.740833,45.470556]],[[4.763889,52.308613],[-0.461389,51.4775]],[[4.763889,52.308613],[-75.241139,39.871944]],[[-149.996361,61.174361],[-118.408075,33.942536]],[[-149.996361,61.174361],[-112.011583,33.434278]],[[-61.792667,17.136749],[-80.943139,35.214]],[[-61.792667,17.136749],[-73.778925,40.639751]],[[-61.792667,17.136749],[-80.290556,25.79325]],[[-71.583083,-16.341072],[-77.114319,-12.021889]],[[17.918611,59.651944],[-0.461389,51.4775]],[[-76.021739,43.991922],[-87.904842,41.978603]],[[-76.021739,43.991922],[-75.241139,39.871944]],[[133.902222,-23.806667],[151.177222,-33.946111]],[[-57.519133,-25.23985],[-80.290556,25.79325]],[[23.944467,37.936358],[-0.461389,51.4775]],[[23.944467,37.936358],[-75.241139,39.871944]],[[-84.428067,33.636719],[-80.943139,35.214]],[[-84.428067,33.636719],[-97.037997,32.896828]],[[-84.428067,33.636719],[-0.461389,51.4775]],[[-84.428067,33.636719],[-80.290556,25.79325]],[[-84.428067,33.636719],[-87.904842,41.978603]],[[-84.428067,33.636719],[-75.241139,39.871944]],[[-84.428067,33.636719],[-112.011583,33.434278]],[[-70.015221,12.501389],[-80.943139,35.214]],[[-70.015221,12.501389],[-80.290556,25.79325]],[[-70.015221,12.501389],[-75.241139,39.871944]],[[54.651138,24.432972],[79.884117,7.180756]],[[54.651138,24.432972],[6.766775,51.289453]],[[54.651138,24.432972],[-77.455811,38.944533]],[[54.651138,24.432972],[73.099233,33.616653]],[[54.651138,24.432972],[-73.778925,40.639751]],[[54.651138,24.432972],[74.403594,31.521564]],[[54.651138,24.432972],[-0.461389,51.4775]],[[54.651138,24.432972],[58.284444,23.593278]],[[54.651138,24.432972],[-87.904842,41.978603]],[[-97.669889,30.194528],[-80.943139,35.214]],[[-97.669889,30.194528],[-97.037997,32.896828]],[[-97.669889,30.194528],[-73.778925,40.639751]],[[-97.669889,30.194528],[-118.408075,33.942536]],[[-97.669889,30.194528],[-0.461389,51.4775]],[[-97.669889,30.194528],[-90.258028,29.993389]],[[-97.669889,30.194528],[-87.904842,41.978603]],[[-97.669889,30.194528],[-75.241139,39.871944]],[[-97.669889,30.194528],[-112.011583,33.434278]],[[-82.541806,35.436194],[-80.943139,35.214]],[[-75.723403,41.338478],[-80.943139,35.214]],[[-75.723403,41.338478],[-75.241139,39.871944]],[[-85.552058,42.234875],[-87.904842,41.978603]],[[50.63361,26.270834],[51.565056,25.261125]],[[50.63361,26.270834],[-0.461389,51.4775]],[[2.078464,41.297078],[-73.778925,40.639751]],[[2.078464,41.297078],[-0.461389,51.4775]],[[2.078464,41.297078],[-80.290556,25.79325]],[[2.078464,41.297078],[-75.241139,39.871944]],[[-64.678703,32.364042],[-73.778925,40.639751]],[[-64.678703,32.364042],[-80.290556,25.79325]],[[-64.678703,32.364042],[-75.241139,39.871944]],[[-72.683222,41.938889],[-80.943139,35.214]],[[-72.683222,41.938889],[-77.037722,38.852083]],[[-72.683222,41.938889],[-97.037997,32.896828]],[[-72.683222,41.938889],[-118.408075,33.942536]],[[-72.683222,41.938889],[-80.290556,25.79325]],[[-72.683222,41.938889],[-87.904842,41.978603]],[[-72.683222,41.938889],[-75.241139,39.871944]],[[-72.683222,41.938889],[-80.232872,40.491467]],[[-119.05677,35.433598],[-112.011583,33.434278]],[[-59.492456,13.074603],[-80.290556,25.79325]],[[-75.979839,42.208689],[-75.241139,39.871944]],[[5.218142,60.293386],[-0.461389,51.4775]],[[-68.828139,44.807444],[-77.037722,38.852083]],[[-68.828139,44.807444],[-75.241139,39.871944]],[[-5.8725,54.618056],[-0.461389,51.4775]],[[-86.75355,33.562942],[-80.943139,35.214]],[[-86.75355,33.562942],[-77.037722,38.852083]],[[-86.75355,33.562942],[-97.037997,32.896828]],[[-86.75355,33.562942],[-80.290556,25.79325]],[[-86.75355,33.562942],[-75.241139,39.871944]],[[-16.652206,13.337961],[-17.490225,14.739708]],[[-101.480847,20.993464],[-97.037997,32.896828]],[[100.747283,13.681108],[101.709917,2.745578]]],
};
diff --git a/client/packages/lowcoder-comps/src/i18n/comps/locales/types.tsx b/client/packages/lowcoder-comps/src/i18n/comps/locales/types.tsx
index 674e7fc8a..1276360a0 100644
--- a/client/packages/lowcoder-comps/src/i18n/comps/locales/types.tsx
+++ b/client/packages/lowcoder-comps/src/i18n/comps/locales/types.tsx
@@ -2,6 +2,7 @@ import { JSONObject } from "lowcoder-sdk";
import { XAXisComponentOption } from "echarts";
export type I18nObjects = {
+ defaultBarChartOption: Record;
defaultDataSource: JSONObject[];
defaultEchartsJsonOption: Record;
defaultGaugeChartOption: Record;
@@ -26,4 +27,8 @@ export type I18nObjects = {
defaultMapJsonOption: Record;
timeXAxisLabel?: XAXisComponentOption["axisLabel"];
imageEditorLocale?: Record;
+ defaultPieBg: string;
+ usaMap: Record;
+ defaultDatasourceBoxplot: unknown[];
+ defaultDatasourceParallel: unknown[];
};
diff --git a/client/packages/lowcoder-comps/src/index.ts b/client/packages/lowcoder-comps/src/index.ts
index acdc6c784..4d621f71b 100644
--- a/client/packages/lowcoder-comps/src/index.ts
+++ b/client/packages/lowcoder-comps/src/index.ts
@@ -19,10 +19,24 @@ import { MeetingControllerComp } from "./comps/agoraMeetingComp/meetingControlle
import { VideoMeetingStreamComp } from "./comps/agoraMeetingComp/videoMeetingStreamComp";
import { VideoSharingStreamComp } from "./comps/agoraMeetingComp/videoSharingStreamComp";
import { BasicChartCompWithDefault } from "comps/basicChartComp/chartComp";
+import { BarChartCompWithDefault } from "comps/barChartComp/barChartComp";
+import { LineChartCompWithDefault } from "comps/lineChartComp/lineChartComp";
+import { PieChartCompWithDefault } from "comps/pieChartComp/pieChartComp";
+import { ScatterChartCompWithDefault } from "comps/scatterChartComp/scatterChartComp";
+import { BoxplotChartCompWithDefault } from "comps/boxplotChartComp/boxplotChartComp";
+import { ParallelChartCompWithDefault } from "comps/parallelChartComp/parallelChartComp";
+import { Line3DChartCompWithDefault } from "comps/line3dChartComp/line3dChartComp";
export default {
chart: ChartCompWithDefault,
basicChart: BasicChartCompWithDefault,
+ barChart: BarChartCompWithDefault,
+ lineChart: LineChartCompWithDefault,
+ pieChart: PieChartCompWithDefault,
+ scatterChart: ScatterChartCompWithDefault,
+ boxplotChart: BoxplotChartCompWithDefault,
+ parallelChart: ParallelChartCompWithDefault,
+ line3dChart: Line3DChartCompWithDefault,
chartsGeoMap: ChartsGeoMapComp,
funnelChart: FunnelChartCompWithDefault,
gaugeChart: GaugeChartCompWithDefault,
diff --git a/client/packages/lowcoder-core/lib/index.js b/client/packages/lowcoder-core/lib/index.js
index 66045110c..32166ca50 100644
--- a/client/packages/lowcoder-core/lib/index.js
+++ b/client/packages/lowcoder-core/lib/index.js
@@ -3331,7 +3331,7 @@ function styleNamespace(id) {
function evalStyle(id, css, globalStyle) {
var _a;
var styleId = styleNamespace(id);
- var prefixId = globalStyle ? id : "#".concat(id);
+ var prefixId = globalStyle ? id : ".".concat(id);
var compiledCSS = "";
css.forEach(function (i) {
if (!i.trim()) {
diff --git a/client/packages/lowcoder-core/src/eval/utils/evalStyle.ts b/client/packages/lowcoder-core/src/eval/utils/evalStyle.ts
index b54322727..a7956a5d9 100644
--- a/client/packages/lowcoder-core/src/eval/utils/evalStyle.ts
+++ b/client/packages/lowcoder-core/src/eval/utils/evalStyle.ts
@@ -6,7 +6,7 @@ function styleNamespace(id: string) {
export function evalStyle(id: string, css: string[], globalStyle?: boolean) {
const styleId = styleNamespace(id);
- const prefixId = globalStyle ? id : `#${id}`
+ const prefixId = globalStyle ? id : `.${id}`;
let compiledCSS = "";
css.forEach((i) => {
if (!i.trim()) {
diff --git a/client/packages/lowcoder-design/src/components/Loading.tsx b/client/packages/lowcoder-design/src/components/Loading.tsx
index 414096e33..d5ffc6710 100644
--- a/client/packages/lowcoder-design/src/components/Loading.tsx
+++ b/client/packages/lowcoder-design/src/components/Loading.tsx
@@ -74,6 +74,7 @@ type LoadingProps = {
size?: number; // circle's size
className?: string;
style?: CSSProperties;
+ compHeight?: number;
};
export const Loading = (props: LoadingProps) => {
@@ -92,7 +93,11 @@ export const Loading = (props: LoadingProps) => {
*/}
-
+
);
};
diff --git a/client/packages/lowcoder-design/src/components/control.tsx b/client/packages/lowcoder-design/src/components/control.tsx
index a25f9df8b..cae47a3f3 100644
--- a/client/packages/lowcoder-design/src/components/control.tsx
+++ b/client/packages/lowcoder-design/src/components/control.tsx
@@ -159,7 +159,9 @@ export const ControlPropertyViewWrapper = (
)}
diff --git a/client/packages/lowcoder-design/src/components/iconSelect/index.tsx b/client/packages/lowcoder-design/src/components/iconSelect/index.tsx
index 6eac2f7b6..23c73b200 100644
--- a/client/packages/lowcoder-design/src/components/iconSelect/index.tsx
+++ b/client/packages/lowcoder-design/src/components/iconSelect/index.tsx
@@ -363,10 +363,12 @@ export const IconSelectBase = (props: {
onOpenChange={setVisible}
getPopupContainer={parent ? () => parent : undefined}
// hide the original background when dragging the popover is allowed
- overlayInnerStyle={{
- border: "none",
- boxShadow: "none",
- background: "transparent",
+ styles={{
+ body: {
+ border: "none",
+ boxShadow: "none",
+ background: "transparent",
+ }
}}
// when dragging is allowed, always re-location to avoid the popover exceeds the screen
destroyTooltipOnHide
diff --git a/client/packages/lowcoder-design/src/components/popover.tsx b/client/packages/lowcoder-design/src/components/popover.tsx
index c7e745d06..4a6d0cbb5 100644
--- a/client/packages/lowcoder-design/src/components/popover.tsx
+++ b/client/packages/lowcoder-design/src/components/popover.tsx
@@ -64,7 +64,6 @@ const SimplePopover = (props: {
);
return (
{props.children}
@@ -101,16 +103,18 @@ const CustomPopover = (props: {
);
return (
{props.children}
@@ -167,8 +171,10 @@ const EditPopover = (props: EditPopoverProps) => {
return (
(
<>
diff --git a/client/packages/lowcoder-design/src/components/shapeSelect/index.tsx b/client/packages/lowcoder-design/src/components/shapeSelect/index.tsx
index a4a71964b..060945977 100644
--- a/client/packages/lowcoder-design/src/components/shapeSelect/index.tsx
+++ b/client/packages/lowcoder-design/src/components/shapeSelect/index.tsx
@@ -444,10 +444,12 @@ export const ShapeSelectBase = (props: {
onOpenChange={setVisible}
getPopupContainer={parent ? () => parent : undefined}
// hide the original background when dragging the popover is allowed
- overlayInnerStyle={{
- border: "none",
- boxShadow: "none",
- background: "transparent",
+ styles={{
+ body: {
+ border: "none",
+ boxShadow: "none",
+ background: "transparent",
+ }
}}
// when dragging is allowed, always re-location to avoid the popover exceeds the screen
destroyTooltipOnHide
diff --git a/client/packages/lowcoder-design/src/components/toolTip.tsx b/client/packages/lowcoder-design/src/components/toolTip.tsx
index 9b5a624c2..3a6b53843 100644
--- a/client/packages/lowcoder-design/src/components/toolTip.tsx
+++ b/client/packages/lowcoder-design/src/components/toolTip.tsx
@@ -155,7 +155,7 @@ export const UnderlineCss = css`
`;
function Tooltip(props: TooltipProps) {
- return ;
+ return ;
}
const Label = styled.div<{ $border?: boolean }>`
@@ -181,7 +181,9 @@ function ToolTipLabel(
<>{title}>}
- overlayInnerStyle={{ maxWidth: "232px", whiteSpace: "break-spaces" }}
+ styles={{
+ body: { maxWidth: "232px", whiteSpace: "break-spaces" }
+ }}
arrow={{
pointAtCenter: true
}}
diff --git a/client/packages/lowcoder-design/src/icons/index.tsx b/client/packages/lowcoder-design/src/icons/index.tsx
index 12b14d6b5..02b0898f3 100644
--- a/client/packages/lowcoder-design/src/icons/index.tsx
+++ b/client/packages/lowcoder-design/src/icons/index.tsx
@@ -345,6 +345,7 @@ export { ReactComponent as VideoScreenshareCompIconSmall } from "./v2/screen-sha
export { ReactComponent as SignatureCompIconSmall } from "./v2/signature-s.svg";
export { ReactComponent as StepCompIconSmall } from "./v2/steps-s.svg";
+
export { ReactComponent as CandlestickChartCompIconSmall } from "./v2/candlestick-chart-s.svg"; // new
export { ReactComponent as FunnelChartCompIconSmall } from "./v2/funnel-chart-s.svg"; // new
export { ReactComponent as GaugeChartCompIconSmall } from "./v2/gauge-chart-s.svg"; // new
@@ -364,6 +365,10 @@ export { ReactComponent as PivotTableCompIconSmall } from "./v2/pivot-table-s.sv
export { ReactComponent as TurnstileCaptchaCompIconSmall } from "./v2/turnstile-captcha-s.svg"; // new
export { ReactComponent as GanttCompIconSmall } from "./v2/gantt-chart-s.svg"; // new
+export { ReactComponent as PieChartCompIconSmall } from "./v2/pie-chart-s.svg"; // new
+export { ReactComponent as BarChartCompIconSmall } from "./v2/bar-chart-s.svg"; // new
+export { ReactComponent as LineChartCompIconSmall } from "./v2/line-chart-s.svg"; // new
+export { ReactComponent as ScatterChartCompIconSmall } from "./v2/scatter-chart-s.svg"; // new
// medium
export { ReactComponent as AudioCompIcon } from "./v2/audio-player-m.svg";
@@ -465,6 +470,11 @@ export { ReactComponent as ThemeriverChartCompIcon } from "./v2/themeriver-chart
export { ReactComponent as TreeChartCompIcon } from "./v2/tree-chart-m.svg";
export { ReactComponent as TreemapChartCompIcon } from "./v2/treemap-chart-m.svg";
+export { ReactComponent as PieChartCompIcon } from "./v2/pie-chart-m.svg"; // new
+export { ReactComponent as BarChartCompIcon } from "./v2/bar-chart-m.svg"; // new
+export { ReactComponent as LineChartCompIcon } from "./v2/line-chart-m.svg"; // new
+export { ReactComponent as ScatterChartCompIcon } from "./v2/scatter-chart-m.svg"; // new
+
export { ReactComponent as BPMNEditorCompIcon } from "./v2/bpmn-editor-m.svg";
export { ReactComponent as GeoMapChartsCompIcon } from "./v2/geomap-charts-m.svg";
export { ReactComponent as GeoMapLayersCompIcon } from "./v2/geomap-layers-m.svg";
diff --git a/client/packages/lowcoder-design/src/icons/v2/line-chart-l.svg b/client/packages/lowcoder-design/src/icons/v2/line-chart-l.svg
new file mode 100644
index 000000000..2c1b9074b
--- /dev/null
+++ b/client/packages/lowcoder-design/src/icons/v2/line-chart-l.svg
@@ -0,0 +1,1264 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/client/packages/lowcoder-design/src/icons/v2/line-chart-m.svg b/client/packages/lowcoder-design/src/icons/v2/line-chart-m.svg
new file mode 100644
index 000000000..aa24cf53d
--- /dev/null
+++ b/client/packages/lowcoder-design/src/icons/v2/line-chart-m.svg
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/client/packages/lowcoder-design/src/icons/v2/line-chart-s.svg b/client/packages/lowcoder-design/src/icons/v2/line-chart-s.svg
new file mode 100644
index 000000000..a39612795
--- /dev/null
+++ b/client/packages/lowcoder-design/src/icons/v2/line-chart-s.svg
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/client/packages/lowcoder-design/src/icons/v2/scatter-chart-l.svg b/client/packages/lowcoder-design/src/icons/v2/scatter-chart-l.svg
new file mode 100644
index 000000000..8bf8071c8
--- /dev/null
+++ b/client/packages/lowcoder-design/src/icons/v2/scatter-chart-l.svg
@@ -0,0 +1,1269 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/client/packages/lowcoder-design/src/icons/v2/scatter-chart-m.svg b/client/packages/lowcoder-design/src/icons/v2/scatter-chart-m.svg
new file mode 100644
index 000000000..7c063a0cd
--- /dev/null
+++ b/client/packages/lowcoder-design/src/icons/v2/scatter-chart-m.svg
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/client/packages/lowcoder-design/src/icons/v2/scatter-chart-s.svg b/client/packages/lowcoder-design/src/icons/v2/scatter-chart-s.svg
new file mode 100644
index 000000000..42491c32c
--- /dev/null
+++ b/client/packages/lowcoder-design/src/icons/v2/scatter-chart-s.svg
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/client/packages/lowcoder-sdk/package.json b/client/packages/lowcoder-sdk/package.json
index f5df08715..4c57864a4 100644
--- a/client/packages/lowcoder-sdk/package.json
+++ b/client/packages/lowcoder-sdk/package.json
@@ -1,6 +1,6 @@
{
"name": "lowcoder-sdk",
- "version": "2.6.3",
+ "version": "2.6.6",
"type": "module",
"files": [
"src",
@@ -25,6 +25,9 @@
},
"./dist/style.css": {
"import": "./dist/style.css"
+ },
+ "./dist/chunks/": {
+ "import": "./dist/chunks/"
}
},
"scripts": {
diff --git a/client/packages/lowcoder-sdk/vite.config.mts b/client/packages/lowcoder-sdk/vite.config.mts
index 903b336f6..3cd7b5c45 100644
--- a/client/packages/lowcoder-sdk/vite.config.mts
+++ b/client/packages/lowcoder-sdk/vite.config.mts
@@ -36,17 +36,7 @@ export const viteConfig: UserConfig = {
},
base: ensureLastSlash(process.env.PUBLIC_URL),
build: {
- minify: "terser",
- terserOptions: {
- compress: {
- drop_console: true,
- drop_debugger: true,
- pure_funcs: ["console.info", "console.debug", "console.log"],
- },
- format: {
- comments: false,
- },
- },
+ minify: "terser",
chunkSizeWarningLimit: 500,
lib: {
formats: ["es"],
@@ -56,7 +46,7 @@ export const viteConfig: UserConfig = {
},
rollupOptions: {
treeshake: {
- moduleSideEffects: false,
+ moduleSideEffects: true,
propertyReadSideEffects: false,
tryCatchDeoptimization: false,
unknownGlobalSideEffects: false,
@@ -64,38 +54,23 @@ export const viteConfig: UserConfig = {
external: ["react", "react-dom"],
output: {
chunkFileNames: "chunks/[name]-[hash].js",
- entryFileNames: "entry/[name]-[hash].js",
- assetFileNames: "assets/[name]-[hash].[ext]",
+ entryFileNames: "lowcoder-sdk.js",
+ assetFileNames: "style.css",
manualChunks: (id) => {
if (id.includes("node_modules")) {
- // CORE FRAMEWORK CHUNKS
- if (id.includes("react")) return "react";
- if (id.includes("react-dom")) return "react-dom";
- if (id.includes("react-router")) return "react-router";
- if (id.includes("react-redux")) return "react-redux";
- if (id.includes("redux")) return "redux";
- if (id.includes("redux-saga")) return "redux-saga";
-
// UI LIBRARIES
if (id.includes("@ant-design/icons")) return "ant-design-icons";
- if (id.includes("antd")) return "antd";
+ if (id.includes("node_modules/antd")) return "antd";
if (id.includes("styled-components")) return "styled-components";
// 🔹 BARCODE & QR CODE PROCESSING
- if (id.includes("zxing") || id.includes("Barcode") || id.includes("QRCode") || id.includes("PDF417")) return "barcode";
-
- // CHARTING & DATA VISUALIZATION
- if (id.includes("echarts")) return "echarts";
- if (id.includes("echarts-wordcloud")) return "echarts-wordcloud";
- if (id.includes("d3")) return "d3";
+ if (id.includes("react-qr-barcode-scanner")) return "barcode";
// TEXT EDITORS & PARSERS
if (id.includes("codemirror")) return "codemirror";
if (id.includes("quill")) return "quill";
if (id.includes("react-json-view")) return "react-json-view";
- if (id.includes("react-markdown")) return "react-markdown";
if (id.includes("react-quill")) return "react-quill";
- if (id.includes("remark") || id.includes("rehype") || id.includes("markdown")) return "markdown-parsers";
if (id.includes("remark-gfm")) return "remark-gfm";
if (id.includes("rehype-raw")) return "rehype-raw";
if (id.includes("rehype-sanitize")) return "rehype-sanitize";
@@ -133,7 +108,6 @@ export const viteConfig: UserConfig = {
if (id.includes("xlsx")) return "xlsx";
if (id.includes("alasql")) return "alasql";
if (id.includes("sql-formatter")) return "sql-formatter";
- if (id.includes("tern")) return "tern";
// NETWORK & HTTP
if (id.includes("axios")) return "axios";
@@ -158,41 +132,38 @@ export const viteConfig: UserConfig = {
if (id.includes("cnchar")) return "cnchar";
if (id.includes("hotkeys-js")) return "hotkeys-js";
if (id.includes("loglevel")) return "loglevel";
- if (id.includes("qrcode-react")) return "qrcode-react";
+ if (id.includes("qrcode.react")) return "qrcode-react";
if (id.includes("react-joyride")) return "react-joyride";
if (id.includes("rc-trigger")) return "rc-trigger";
if (id.includes("really-relaxed-json")) return "really-relaxed-json";
if (id.includes("simplebar-react")) return "simplebar-react";
- return "vendor";
+ if (id.includes("react-documents")) return "react-documents";
+ if (id.includes("react-colorful")) return "react-colorful";
+ if (id.includes("react-best-gradient-color-picker")) return "react-best-gradient-color-picker";
+ if (id.includes("@supabase/supabase-js")) return "supabase";
+ return null;
}
- if (id.includes("src/api")) return "api";
- if (id.includes("src/appView")) return "appView";
- if (id.includes("src/base")) return "base";
- if (id.includes("src/constants")) return "constants";
- if (id.includes("src/i18n")) return "i18n";
- if (id.includes("src/ide")) return "ide";
- if (id.includes("src/layout")) return "layout";
- if (id.includes("src/pages")) return "pages";
- if (id.includes("src/redux")) return "app_redux";
- if (id.includes("src/comps")) return "comps";
- if (id.includes("comps/comps")) return "comps2";
- if (id.includes("comps/controls")) return "controls";
- if (id.includes("comps/queries")) return "queries";
- if (id.includes("comps/utils")) return "utils";
- if (id.includes("src/hooks")) return "hooks";
- if (id.includes("src/util")) return "util";
- return "common"; // 📦 Internal app shared code
- },
+ return null;
+ }
},
experimental: {
minChunkSize: 300000, // 📏 Force smaller chunks (~300KB)
},
plugins: [
- terser(),
+ terser({
+ compress: {
+ drop_console: true,
+ drop_debugger: true,
+ pure_funcs: ["console.info", "console.debug", "console.log"],
+ },
+ format: {
+ comments: /(@vite-ignore|webpackIgnore)/
+ },
+ }) as PluginOption,
strip({
functions: ["console.log", "debugger"], // ✅ Remove logs
sourceMap: true,
- }),
+ }) as PluginOption,
],
onwarn: (warning, warn) => {
if (warning.code === 'MODULE_LEVEL_DIRECTIVE') {
diff --git a/client/packages/lowcoder/index.html b/client/packages/lowcoder/index.html
index 0f69f0293..8bd8757bc 100644
--- a/client/packages/lowcoder/index.html
+++ b/client/packages/lowcoder/index.html
@@ -30,6 +30,7 @@
flex-direction: column;
top: 0;
z-index: 10000;
+ transition: opacity 0.25s linear;
}
#loading svg {
animation: breath 1s linear infinite;
diff --git a/client/packages/lowcoder/package.json b/client/packages/lowcoder/package.json
index 65146553a..f3f02092e 100644
--- a/client/packages/lowcoder/package.json
+++ b/client/packages/lowcoder/package.json
@@ -1,6 +1,6 @@
{
"name": "lowcoder",
- "version": "2.6.3",
+ "version": "2.6.4",
"private": true,
"type": "module",
"main": "src/index.sdk.ts",
@@ -127,6 +127,7 @@
"eslint-config-react-app": "^7.0.1",
"eslint-plugin-only-ascii": "^0.0.0",
"http-proxy-middleware": "^2.0.6",
+ "rollup-plugin-terser": "^7.0.2",
"rollup-plugin-visualizer": "^5.9.2",
"typescript": "^4.8.4",
"vite": "^4.5.5",
diff --git a/client/packages/lowcoder/src/api/subscriptionApi.ts b/client/packages/lowcoder/src/api/subscriptionApi.ts
index 02a3ff5f6..6bfcdb259 100644
--- a/client/packages/lowcoder/src/api/subscriptionApi.ts
+++ b/client/packages/lowcoder/src/api/subscriptionApi.ts
@@ -182,6 +182,22 @@ export const createCustomer = async (subscriptionCustomer: LowcoderNewCustomer)
}
};
+export const cleanupCustomer = async (subscriptionCustomer: LowcoderSearchCustomer) => {
+ const apiBody = {
+ path: "webhook/secure/cleanup-customer",
+ data: subscriptionCustomer,
+ method: "post",
+ headers: lcHeaders
+ };
+ try {
+ const result = await SubscriptionApi.secureRequest(apiBody, 15000);
+ return result?.data as any;
+ } catch (error) {
+ console.error("Error creating customer:", error);
+ throw error;
+ }
+};
+
export const getProduct = async (productId : string) => {
const apiBody = {
path: "webhook/secure/get-product",
diff --git a/client/packages/lowcoder/src/base/codeEditor/autoFormat.tsx b/client/packages/lowcoder/src/base/codeEditor/autoFormat.tsx
index 17b5820a3..8a1c63caa 100644
--- a/client/packages/lowcoder/src/base/codeEditor/autoFormat.tsx
+++ b/client/packages/lowcoder/src/base/codeEditor/autoFormat.tsx
@@ -2,30 +2,31 @@ import type { CodeType } from "lowcoder-core";
import { relaxedJSONToJSON } from "lowcoder-core";
import { getDynamicStringSegments, isDynamicSegment } from "lowcoder-core";
import { format as formatSQL } from "sql-formatter";
+import estree from "prettier/plugins/estree";
import type { Language } from "./codeEditorTypes";
export async function cssFormatter(text: string) {
- const prettier = await require("prettier/standalone");
- const parserPlugin = await require("prettier/parser-postcss");
+ const prettier = await import("prettier/standalone");
+ const parserPlugin = await import("prettier/plugins/postcss");
return (await prettier.format(text, { parser: "css", plugins: [parserPlugin], semi: false })).trim();
}
export async function htmlFormatter(text: string) {
- const prettier = await require("prettier/standalone");
- const parserPlugin = await require("prettier/parser-html");
+ const prettier = await import("prettier/standalone");
+ const parserPlugin = await import("prettier/plugins/html");
return (await prettier.format(text, { parser: "html", plugins: [parserPlugin], semi: false })).trim();
}
async function getJavascriptFormatter() {
- const prettier = await require("prettier/standalone");
- const parserBabel = await require("prettier/parser-babel");
+ const prettier = await import("prettier/standalone");
+ const parserBabel = await import("prettier/plugins/babel");
return async (text: string) =>
- (await prettier.format(text, { parser: "babel", plugins: [parserBabel], semi: false })).trim();
+ (await prettier.format(text, { parser: "babel", plugins: [parserBabel, estree], semi: false })).trim();
}
export async function getJsonFormatter() {
- const prettier = await require("prettier/standalone");
- const parserBabel = await require("prettier/parser-babel");
+ const prettier = await import("prettier/standalone");
+ const parserBabel = await import("prettier/plugins/babel");
return async (text: string) => (await prettier.format(text, { parser: "json", plugins: [parserBabel] })).trim();
}
@@ -46,15 +47,16 @@ async function formatJsSegment(formatter: (text: string) => Promise, scr
async function getJsSegmentFormatter() {
const formatter = await getJavascriptFormatter();
return async (segment: string) => {
- return "{{" + formatJsSegment(formatter, segment.slice(2, -2)) + "}}";
+ return "{{" + await formatJsSegment(formatter, segment.slice(2, -2)) + "}}";
};
}
export async function formatStringWithJsSnippets(text: string): Promise {
const jsSegmentFormatter = await getJsSegmentFormatter();
- return getDynamicStringSegments(text)
- .map((s) => (isDynamicSegment(s) ? jsSegmentFormatter(s) : s))
- .join("");
+ const formatedSegments = await Promise.all(
+ getDynamicStringSegments(text).map((s) => (isDynamicSegment(s) ? jsSegmentFormatter(s) : s))
+ );
+ return formatedSegments.join("");
}
export async function formatSqlWithJsSnippets(text: string) {
diff --git a/client/packages/lowcoder/src/comps/comps/avatar.tsx b/client/packages/lowcoder/src/comps/comps/avatar.tsx
index fc7f6f433..a1da4984a 100644
--- a/client/packages/lowcoder/src/comps/comps/avatar.tsx
+++ b/client/packages/lowcoder/src/comps/comps/avatar.tsx
@@ -41,12 +41,12 @@ const AvatarWrapper = styled(Avatar) props.$cursorPointer ? 'pointer' : ''};
`;
-const Wrapper = styled.div <{ iconSize: number, labelPosition: string,$style: AvatarContainerStyleType}>`
+const Wrapper = styled.div <{ $iconSize: number, $labelPosition: string,$style: AvatarContainerStyleType}>`
display: flex;
width: 100%;
height: 100%;
align-items: center;
-flex-direction: ${(props) => props.labelPosition === 'left' ? 'row' : 'row-reverse'};
+flex-direction: ${(props) => props.$labelPosition === 'left' ? 'row' : 'row-reverse'};
${(props) => {
return (
props.$style && {
@@ -57,14 +57,14 @@ ${(props) => {
}}
`
-const LabelWrapper = styled.div<{ iconSize: number, alignmentPosition: string }>`
-width: calc(100% - ${(props) => props.iconSize}px);
+const LabelWrapper = styled.div<{ $iconSize: number, $alignmentPosition: string }>`
+width: calc(100% - ${(props) => props.$iconSize}px);
display: flex;
padding-left: 5px;
padding-right: 5px;
flex-direction: column;
justify-content: flex-end;
-align-items: ${(props) => props.alignmentPosition === 'left' ? 'flex-start' : 'flex-end'};
+align-items: ${(props) => props.$alignmentPosition === 'left' ? 'flex-start' : 'flex-end'};
`
const LabelSpan = styled.span<{ $style:AvatarLabelStyleType }>`
max-width: 100%;
@@ -166,7 +166,7 @@ const AvatarView = (props: RecordConstructorToView) => {
disabled={!props.enableDropdownMenu}
dropdownRender={() => menu}
>
-
+
) => {
{title.value}
-
+
{props.avatarLabel.value}
{props.avatarCatption.value}
diff --git a/client/packages/lowcoder/src/comps/comps/avatarGroup.tsx b/client/packages/lowcoder/src/comps/comps/avatarGroup.tsx
index cba007ee1..4cc2567c6 100644
--- a/client/packages/lowcoder/src/comps/comps/avatarGroup.tsx
+++ b/client/packages/lowcoder/src/comps/comps/avatarGroup.tsx
@@ -111,11 +111,11 @@ const AvatarGroupView = (props: RecordConstructorToView & {
alignment={props.alignment}
>
{
-
+
{
props.avatars.map((item, index) => {
return (
-
+
+
{props.children}
);
@@ -350,9 +350,9 @@ export const InnerGrid = React.memo((props: ViewPropsWithSelect) => {
const [currentRowHeight, setRowHeight] = useState(positionParams.rowHeight || DEFAULT_ROW_HEIGHT);
const editorState = useContext(EditorContext);
const { readOnly } = useContext(ExternalEditorContext);
- const appSettingsComp = editorState.getAppSettingsComp().getView();
+ const appSettingsComp = editorState?.getAppSettingsComp().getView();
- const maxWidth = useMemo(() => appSettingsComp.maxWidth, [appSettingsComp.maxWidth]);
+ const maxWidth = useMemo(() => appSettingsComp?.maxWidth, [appSettingsComp?.maxWidth]);
// Falk: TODO: Here we can define the inner grid columns dynamically
const defaultGrid = useMemo(() => {
@@ -372,10 +372,10 @@ export const InnerGrid = React.memo((props: ViewPropsWithSelect) => {
getExtraLayout(
props.items,
props.layout,
- editorState.selectedCompNames,
+ editorState?.selectedCompNames,
props.dragSelectedComps
),
- [props.items, props.layout, editorState.selectedCompNames, props.dragSelectedComps]
+ [props.items, props.layout, editorState?.selectedCompNames, props.dragSelectedComps]
);
const [containerSelectNames, setContainerSelectNames] = useState>(new Set([]));
@@ -392,8 +392,8 @@ export const InnerGrid = React.memo((props: ViewPropsWithSelect) => {
}, [extraLayout, containerSelectNames]);
const canAddSelect = useMemo(
- () => _.size(containerSelectNames) === _.size(editorState.selectedCompNames),
- [containerSelectNames, editorState.selectedCompNames]
+ () => _.size(containerSelectNames) === _.size(editorState?.selectedCompNames),
+ [containerSelectNames, editorState?.selectedCompNames]
);
const dispatchPositionParamsTimerRef = useRef(0);
@@ -439,21 +439,23 @@ export const InnerGrid = React.memo((props: ViewPropsWithSelect) => {
isRowCountLocked,
onPositionParamsChange,
onRowCountChange,
- positionParams,
+ JSON.stringify(positionParams),
+ JSON.stringify(props.containerPadding),
props.dispatch,
- props.containerPadding,
]
);
const setSelectedNames = useCallback(
(names: Set) => {
- editorState.setSelectedCompNames(names);
+ editorState?.setSelectedCompNames(names);
},
- [editorState.setSelectedCompNames]
+ [editorState?.setSelectedCompNames]
);
const { width, ref } = useResizeDetector({
onResize,
handleHeight: isRowCountLocked,
+ refreshMode: 'debounce',
+ refreshRate: 100,
});
const itemViewRef = useRef({});
@@ -500,7 +502,7 @@ export const InnerGrid = React.memo((props: ViewPropsWithSelect) => {
style={props.style}
scrollContainerRef={props.scrollContainerRef}
width={width ?? 0}
- showGridLines={editorState.showGridLines() && (isDroppable || enableGridLines)}
+ showGridLines={editorState?.showGridLines() && (isDroppable || enableGridLines)}
isRowCountLocked={isRowCountLocked}
isDraggable={isDraggable}
isResizable={isResizable}
@@ -517,7 +519,7 @@ export const InnerGrid = React.memo((props: ViewPropsWithSelect) => {
: defaultLayout(compType);
return {
size: compLayout ?? defaultSize,
- positionParams: editorState.canvasPositionParams(),
+ positionParams: editorState?.canvasPositionParams(),
};
}
}}
@@ -533,18 +535,18 @@ export const InnerGrid = React.memo((props: ViewPropsWithSelect) => {
const items = _.pick(props.items, Object.keys(layoutItems));
draggingUtils.setData("sourceDispatch", props.dispatch);
draggingUtils.setData>("items", items);
- editorState.setDragging(true);
+ editorState?.setDragging(true);
const names = Object.values(items).map((item) => item.name);
- editorState.setSelectedCompNames(new Set(names));
+ editorState?.setSelectedCompNames(new Set(names));
}}
onFlyDrop={(layout, items) => {
onFlyDrop(layout, items, props.dispatch);
}}
onResizeStart={(_a, _b, _c, _d, event) => {
event.stopPropagation();
- editorState.setDragging(true);
+ editorState?.setDragging(true);
}}
- onResizeStop={() => editorState.setDragging(false)}
+ onResizeStop={() => editorState?.setDragging(false)}
margin={[0, 0]}
containerPadding={props.containerPadding}
fixedRowCount={props.emptyRows !== DEFAULT_ROW_COUNT}
@@ -558,12 +560,12 @@ export const InnerGrid = React.memo((props: ViewPropsWithSelect) => {
minHeight={props.minHeight}
bgColor={props.bgColor}
radius={props.radius}
- hintPlaceholder={!editorState.isDragging && !readOnly && props.hintPlaceholder}
+ hintPlaceholder={!editorState?.isDragging && !readOnly && props.hintPlaceholder}
selectedSize={_.size(containerSelectNames)}
clickItem={clickItem}
isCanvas={props.isCanvas}
showName={props.showName}
- disableDirectionKey={editorState.isDragging || readOnly}
+ disableDirectionKey={editorState?.isDragging || readOnly}
>
{itemViews}
diff --git a/client/packages/lowcoder/src/comps/comps/gridItemComp.tsx b/client/packages/lowcoder/src/comps/comps/gridItemComp.tsx
index 7ef5440cc..f6522d583 100644
--- a/client/packages/lowcoder/src/comps/comps/gridItemComp.tsx
+++ b/client/packages/lowcoder/src/comps/comps/gridItemComp.tsx
@@ -55,6 +55,7 @@ const TmpComp = withTypeAndChildren<
undefined,
undefined,
manifest.withoutLoading,
+ manifest.layoutInfo?.h,
)
}
const comp = manifest.withoutLoading ? manifest.comp : withIsLoading(manifest.comp!);
@@ -96,6 +97,7 @@ const CachedPropertyView = React.memo((props: {
useEffect(() => {
setSearchText("");
}, [props.name]);
+
return useMemo(() => {
return (
<>
diff --git a/client/packages/lowcoder/src/comps/comps/lazyLoadComp/lazyLoadComp.tsx b/client/packages/lowcoder/src/comps/comps/lazyLoadComp/lazyLoadComp.tsx
index 7a45714b3..0b2ac21f6 100644
--- a/client/packages/lowcoder/src/comps/comps/lazyLoadComp/lazyLoadComp.tsx
+++ b/client/packages/lowcoder/src/comps/comps/lazyLoadComp/lazyLoadComp.tsx
@@ -49,6 +49,7 @@ interface LazyCompViewProps {
loadComp: () => Promise;
loadingElement?: () => React.ReactNode;
errorElement?: (error: any) => React.ReactNode;
+ height?: number,
}
const LazyCompView = React.memo((props: React.PropsWithChildren) => {
@@ -82,7 +83,7 @@ const LazyCompView = React.memo((props: React.PropsWithChildren
+
);
});
@@ -94,6 +95,7 @@ export function lazyLoadComp(
loader?: LazyloadCompLoader,
loadingElement?: () => React.ReactNode,
withoutLoading?: boolean,
+ height?: number,
) {
class LazyLoadComp extends simpleMultiComp({}) {
compValue: any;
@@ -145,7 +147,12 @@ export function lazyLoadComp(
// const key = `${remoteInfo?.packageName}-${remoteInfo?.packageVersion}-${remoteInfo?.compName}`;
const key = `${compName}`;
return (
- this.load()} loadingElement={loadingElement} />
+ this.load()}
+ loadingElement={loadingElement}
+ height={height}
+ />
);
}
diff --git a/client/packages/lowcoder/src/comps/comps/listViewComp/listViewComp.tsx b/client/packages/lowcoder/src/comps/comps/listViewComp/listViewComp.tsx
index cd9644997..47da5c6f3 100644
--- a/client/packages/lowcoder/src/comps/comps/listViewComp/listViewComp.tsx
+++ b/client/packages/lowcoder/src/comps/comps/listViewComp/listViewComp.tsx
@@ -39,7 +39,7 @@ import { ListView } from "./listView";
import { listPropertyView } from "./listViewPropertyView";
import { getData } from "./listViewUtils";
import { withMethodExposing } from "comps/generators/withMethodExposing";
-import SliderControl from "@lowcoder-ee/comps/controls/sliderControl";
+import { SliderControl } from "@lowcoder-ee/comps/controls/sliderControl";
const childrenMap = {
noOfRows: withIsLoadingMethod(NumberOrJSONObjectArrayControl), // FIXME: migrate "noOfRows" to "data"
diff --git a/client/packages/lowcoder/src/comps/comps/pageLayoutComp/pageLayoutComp.tsx b/client/packages/lowcoder/src/comps/comps/pageLayoutComp/pageLayoutComp.tsx
index d4c890015..febeddabf 100644
--- a/client/packages/lowcoder/src/comps/comps/pageLayoutComp/pageLayoutComp.tsx
+++ b/client/packages/lowcoder/src/comps/comps/pageLayoutComp/pageLayoutComp.tsx
@@ -28,7 +28,7 @@ import { ContainerBodyChildComp } from "./containerBodyChildComp";
import { trans } from "i18n";
import { ControlNode } from "lowcoder-design";
import { StringControl } from "comps/controls/codeControl";
-import SliderControl from "@lowcoder-ee/comps/controls/sliderControl";
+import { SliderControl } from "@lowcoder-ee/comps/controls/sliderControl";
import { useMergeCompStyles } from "@lowcoder-ee/util/hooks";
const childrenMap = {
diff --git a/client/packages/lowcoder/src/comps/comps/responsiveLayout/responsiveLayout.tsx b/client/packages/lowcoder/src/comps/comps/responsiveLayout/responsiveLayout.tsx
index fc8e47536..13b3b8b5c 100644
--- a/client/packages/lowcoder/src/comps/comps/responsiveLayout/responsiveLayout.tsx
+++ b/client/packages/lowcoder/src/comps/comps/responsiveLayout/responsiveLayout.tsx
@@ -42,7 +42,7 @@ import { EditorContext } from "comps/editorState";
import { disabledPropertyView, hiddenPropertyView } from "comps/utils/propertyUtils";
import { DisabledContext } from "comps/generators/uiCompBuilder";
-import SliderControl from "@lowcoder-ee/comps/controls/sliderControl";
+import { SliderControl } from "@lowcoder-ee/comps/controls/sliderControl";
import { getBackgroundStyle } from "@lowcoder-ee/util/styleUtils";
import { useScreenInfo } from "../../hooks/screenInfoComp";
@@ -136,7 +136,7 @@ type ColumnContainerProps = Omit & {
style: ResponsiveLayoutColStyleType,
}
-const ColumnContainer = (props: ColumnContainerProps) => {
+const ColumnContainer = React.memo((props: ColumnContainerProps) => {
return (
{
style={props.style}
/>
);
-};
+});
const ResponsiveLayout = (props: ResponsiveLayoutProps) => {
const screenInfo = useScreenInfo();
diff --git a/client/packages/lowcoder/src/comps/comps/rootComp.tsx b/client/packages/lowcoder/src/comps/comps/rootComp.tsx
index b28e4c045..edf1f3a34 100644
--- a/client/packages/lowcoder/src/comps/comps/rootComp.tsx
+++ b/client/packages/lowcoder/src/comps/comps/rootComp.tsx
@@ -35,6 +35,7 @@ import { useUserViewMode } from "util/hooks";
import React from "react";
import { isEqual } from "lodash";
import {LoadingBarHideTrigger} from "@lowcoder-ee/util/hideLoading";
+import clsx from "clsx";
const EditorView = lazy(
() => import("pages/editor/editorView"),
);
@@ -130,7 +131,11 @@ const RootView = React.memo((props: RootViewProps) => {
}
return (
-
+
diff --git a/client/packages/lowcoder/src/comps/comps/splitLayout/splitLayout.tsx b/client/packages/lowcoder/src/comps/comps/splitLayout/splitLayout.tsx
index dfac3b4f8..b988eca54 100644
--- a/client/packages/lowcoder/src/comps/comps/splitLayout/splitLayout.tsx
+++ b/client/packages/lowcoder/src/comps/comps/splitLayout/splitLayout.tsx
@@ -28,7 +28,7 @@ import { NameGenerator } from "comps/utils";
import { AutoHeightControl } from "comps/controls/autoHeightControl";
import { messageInstance } from "lowcoder-design/src/components/GlobalInstances";
import { NameConfigHidden, withExposingConfigs } from "comps/generators/withExposing";
-import SliderControl from "@lowcoder-ee/comps/controls/sliderControl";
+import { SliderControl } from "@lowcoder-ee/comps/controls/sliderControl";
import { getBackgroundStyle } from "@lowcoder-ee/util/styleUtils";
import _ from "lodash";
diff --git a/client/packages/lowcoder/src/comps/comps/tableComp/column/columnTypeComp.tsx b/client/packages/lowcoder/src/comps/comps/tableComp/column/columnTypeComp.tsx
index 3757e6bc8..58e0b7df4 100644
--- a/client/packages/lowcoder/src/comps/comps/tableComp/column/columnTypeComp.tsx
+++ b/client/packages/lowcoder/src/comps/comps/tableComp/column/columnTypeComp.tsx
@@ -1,5 +1,6 @@
import { CellProps } from "components/table/EditableCell";
import { DateTimeComp } from "comps/comps/tableComp/column/columnTypeComps/columnDateTimeComp";
+import { TimeComp } from "./columnTypeComps/columnTimeComp";
import { ButtonComp } from "comps/comps/tableComp/column/simpleColumnTypeComps";
import { withType } from "comps/generators";
import { trans } from "i18n";
@@ -67,6 +68,11 @@ const actionOptions = [
label: trans("table.image"),
value: "image",
},
+ {
+ label: trans("table.time"),
+ value: "time",
+ },
+
{
label: trans("table.date"),
value: "date",
@@ -116,6 +122,7 @@ export const ColumnTypeCompMap = {
rating: RatingComp,
progress: ProgressComp,
date: DateComp,
+ time: TimeComp,
};
type ColumnTypeMapType = typeof ColumnTypeCompMap;
diff --git a/client/packages/lowcoder/src/comps/comps/tableComp/column/columnTypeComps/columnTimeComp.tsx b/client/packages/lowcoder/src/comps/comps/tableComp/column/columnTypeComps/columnTimeComp.tsx
new file mode 100644
index 000000000..b4ad2d73d
--- /dev/null
+++ b/client/packages/lowcoder/src/comps/comps/tableComp/column/columnTypeComps/columnTimeComp.tsx
@@ -0,0 +1,166 @@
+import { default as TimePicker } from "antd/es/time-picker";
+import {
+ ColumnTypeCompBuilder,
+ ColumnTypeViewFn,
+} from "comps/comps/tableComp/column/columnTypeCompBuilder";
+import { ColumnValueTooltip } from "comps/comps/tableComp/column/simpleColumnTypeComps";
+import { StringControl } from "comps/controls/codeControl";
+import { withDefault } from "comps/generators";
+import { formatPropertyView } from "comps/utils/propertyUtils";
+import { trans } from "i18n";
+import dayjs from "dayjs";
+import { useEffect, useRef, useState } from "react";
+import styled from "styled-components";
+import { TIME_FORMAT } from "util/dateTimeUtils";
+import { hasIcon } from "comps/utils";
+import { IconControl } from "comps/controls/iconControl";
+
+
+const TimePickerStyled = styled(TimePicker)<{ $open: boolean }>`
+ width: 100%;
+ height: 100%;
+ position: absolute;
+ top: 0;
+ padding: 0;
+ padding-left: 11px;
+ .ant-picker-input {
+ height: 100%;
+ }
+ input {
+ padding-right: 18px;
+ cursor: pointer;
+ }
+ &.ant-picker-focused .ant-picker-suffix svg g {
+ stroke: ${(props) => props.$open && "#315EFB"};
+ }
+ .ant-picker-suffix {
+ height: calc(100% - 1px);
+ position: absolute;
+ right: 0;
+ top: 0.5px;
+ display: flex;
+ align-items: center;
+ padding: 0 3px;
+ }
+`;
+
+const Wrapper = styled.div`
+ background: transparent !important;
+`;
+
+export function formatTime(time: string, format: string) {
+ const parsedTime = dayjs(time, TIME_FORMAT);
+ return parsedTime.isValid() ? parsedTime.format(format) : "";
+}
+
+const childrenMap = {
+ text: StringControl,
+ prefixIcon: IconControl,
+ suffixIcon: IconControl,
+ format: withDefault(StringControl, TIME_FORMAT),
+ inputFormat: withDefault(StringControl, TIME_FORMAT),
+};
+
+let inputFormat = TIME_FORMAT;
+
+const getBaseValue: ColumnTypeViewFn = (props) => props.text;
+
+type TimeEditProps = {
+ value: string;
+ onChange: (value: string) => void;
+ onChangeEnd: () => void;
+ inputFormat: string;
+};
+
+export const TimeEdit = (props: TimeEditProps) => {
+ const pickerRef = useRef();
+ const [panelOpen, setPanelOpen] = useState(true);
+ let value = dayjs(props.value, TIME_FORMAT);
+ if (!value.isValid()) {
+ value = dayjs("00:00:00", TIME_FORMAT);
+ }
+
+ const [tempValue, setTempValue] = useState(value);
+
+ useEffect(() => {
+ const value = props.value ? dayjs(props.value, TIME_FORMAT) : null;
+ setTempValue(value);
+ }, [props.value]);
+
+ return (
+ {
+ if (e.key === "Enter" && !panelOpen) {
+ props.onChangeEnd();
+ }
+ }}
+ onMouseDown={(e) => {
+ e.stopPropagation();
+ e.preventDefault();
+ }}
+ >
+ setPanelOpen(open)}
+ onChange={(value, timeString) => {
+ props.onChange(timeString as string);
+ }}
+ onBlur={() => props.onChangeEnd()}
+ />
+
+ );
+};
+
+export const TimeComp = (function () {
+ return new ColumnTypeCompBuilder(
+ childrenMap,
+ (props, dispatch) => {
+ inputFormat = props.inputFormat;
+ const value = props.changeValue ?? getBaseValue(props, dispatch);
+ return(
+ <>
+ {hasIcon(props.prefixIcon) && (
+ {props.prefixIcon}
+ )}
+ {value}
+ {hasIcon(props.suffixIcon) && (
+ {props.suffixIcon}
+ )}
+ >
+ );
+
+ },
+ (nodeValue) => formatTime(nodeValue.text.value, nodeValue.format.value),
+ getBaseValue
+ )
+ .setEditViewFn((props) => (
+
+ ))
+ .setPropertyViewFn((children) => (
+ <>
+ {children.text.propertyView({
+ label: trans("table.columnValue"),
+ tooltip: ColumnValueTooltip,
+ })}
+ {children.prefixIcon.propertyView({
+ label: trans("button.prefixIcon"),
+ })}
+ {children.suffixIcon.propertyView({
+ label: trans("button.suffixIcon"),
+ })}
+ {formatPropertyView({ children, placeholder: TIME_FORMAT })}
+ >
+ ))
+ .build();
+})();
diff --git a/client/packages/lowcoder/src/comps/comps/tableComp/column/tableColumnComp.tsx b/client/packages/lowcoder/src/comps/comps/tableComp/column/tableColumnComp.tsx
index 440d6f1e0..3e7a8df61 100644
--- a/client/packages/lowcoder/src/comps/comps/tableComp/column/tableColumnComp.tsx
+++ b/client/packages/lowcoder/src/comps/comps/tableComp/column/tableColumnComp.tsx
@@ -219,6 +219,7 @@ export class ColumnComp extends ColumnInitComp {
const columnType = this.children.render.getSelectedComp().getComp().children.compType.getView();
return {
...superView,
+ columnType,
editable: ColumnTypeCompMap[columnType].canBeEditable() && superView.editable,
};
}
diff --git a/client/packages/lowcoder/src/comps/comps/tableComp/tableToolbarComp.tsx b/client/packages/lowcoder/src/comps/comps/tableComp/tableToolbarComp.tsx
index 85703fd11..64d0b6fae 100644
--- a/client/packages/lowcoder/src/comps/comps/tableComp/tableToolbarComp.tsx
+++ b/client/packages/lowcoder/src/comps/comps/tableComp/tableToolbarComp.tsx
@@ -686,8 +686,10 @@ function ToolbarPopover(props: {
return (
{
+ return dayjs(a[column.dataIndex] as string).unix() - dayjs(b[column.dataIndex] as string).unix();
+ }
+ : undefined
+ },
sortOrder: sortMap.get(column.dataIndex),
showSorterTooltip: false,
}
diff --git a/client/packages/lowcoder/src/comps/comps/tabs/tabbedContainerComp.tsx b/client/packages/lowcoder/src/comps/comps/tabs/tabbedContainerComp.tsx
index e062ba3bb..2d930fbf4 100644
--- a/client/packages/lowcoder/src/comps/comps/tabs/tabbedContainerComp.tsx
+++ b/client/packages/lowcoder/src/comps/comps/tabs/tabbedContainerComp.tsx
@@ -35,7 +35,7 @@ import { checkIsMobile } from "util/commonUtils";
import { messageInstance } from "lowcoder-design/src/components/GlobalInstances";
import { BoolControl } from "comps/controls/boolControl";
import { PositionControl } from "comps/controls/dropdownControl";
-import SliderControl from "@lowcoder-ee/comps/controls/sliderControl";
+import { SliderControl } from "@lowcoder-ee/comps/controls/sliderControl";
import { getBackgroundStyle } from "@lowcoder-ee/util/styleUtils";
const EVENT_OPTIONS = [
diff --git a/client/packages/lowcoder/src/comps/comps/textInputComp/textAreaComp.tsx b/client/packages/lowcoder/src/comps/comps/textInputComp/textAreaComp.tsx
index a41fed3a2..b631d65fb 100644
--- a/client/packages/lowcoder/src/comps/comps/textInputComp/textAreaComp.tsx
+++ b/client/packages/lowcoder/src/comps/comps/textInputComp/textAreaComp.tsx
@@ -54,6 +54,9 @@ const Wrapper = styled.div<{
.ant-input {
height:100% !important;
}
+ .ant-input-affix-wrapper {
+ height:100% !important;
+ }
.ant-input-clear-icon {
opacity: 0.75;
diff --git a/client/packages/lowcoder/src/comps/comps/timerComp.tsx b/client/packages/lowcoder/src/comps/comps/timerComp.tsx
index 907566e12..a749cb068 100644
--- a/client/packages/lowcoder/src/comps/comps/timerComp.tsx
+++ b/client/packages/lowcoder/src/comps/comps/timerComp.tsx
@@ -1,7 +1,7 @@
-import { CompAction, RecordConstructorToView, changeChildAction } from "lowcoder-core";
+import { CompAction, RecordConstructorToComp, RecordConstructorToView, changeChildAction } from "lowcoder-core";
import { styleControl } from "comps/controls/styleControl";
import { AnimationStyle, AnimationStyleType, startButtonStyle, StartButtonStyleType, timerStyle, timerStyleType } from "comps/controls/styleControlConstants";
-import { UICompBuilder } from "comps/generators/uiCompBuilder";
+import { NewChildren, UICompBuilder } from "comps/generators/uiCompBuilder";
import { NameConfig, NameConfigHidden, withExposingConfigs } from "comps/generators/withExposing";
import { Section, sectionNames } from "lowcoder-design";
import { hiddenPropertyView, showDataLoadingIndicatorsPropertyView } from "comps/utils/propertyUtils";
@@ -15,6 +15,7 @@ import { EditorContext } from "comps/editorState";
import { dropdownControl } from "../controls/dropdownControl";
import { stringExposingStateControl } from "comps/controls/codeStateControl";
import { BoolControl } from "comps/controls/boolControl";
+import React from "react";
const Container = styled.div<{
$style: timerStyleType | undefined;
@@ -113,7 +114,9 @@ const childrenMap = {
hideButton: BoolControl,
};
-const AvatarGroupView = (props: RecordConstructorToView & { dispatch: (action: CompAction) => void; }) => {
+type ChildrenType = NewChildren>;
+
+const TimerCompView = React.memo((props: RecordConstructorToView & { dispatch: (action: CompAction) => void; }) => {
const [startTime, setStartTime] = useState(0)
const [timerState, setTimerState] = useState('stoped')
const [elapsedTime, setElapsedTime] = useState(0)
@@ -219,51 +222,57 @@ const AvatarGroupView = (props: RecordConstructorToView & {
);
-};
+});
-let AvatarGroupBasicComp = (function () {
- return new UICompBuilder(childrenMap, (props, dispatch) => )
- .setPropertyViewFn((children) => (
- <>
- {["logic", "both"].includes(useContext(EditorContext).editorModeStatus) && (
- <>
-
- {children.timerType.propertyView({
- label: trans('timer.timerType')
- })}
- {children.defaultValue.propertyView({
- label: trans('timer.defaultValue')
- })}
- {children.hideButton.propertyView({
- label: trans('timer.hideButton')
- })}
-
-
- {children.onEvent.propertyView()}
- {hiddenPropertyView(children)}
- {showDataLoadingIndicatorsPropertyView(children)}
-
- >
- )}
-
- {["layout", "both"].includes(useContext(EditorContext).editorModeStatus) && (
- <>
-
- {children.style.getPropertyView()}
-
-
- {children.animationStyle.getPropertyView()}
-
-
- {children.startButtonStyle.getPropertyView()}
+const TimerCompPropertyView = React.memo((props: {
+ children: ChildrenType
+}) => {
+ return (
+ <>
+ {["logic", "both"].includes(useContext(EditorContext).editorModeStatus) && (
+ <>
+
+ {props.children.timerType.propertyView({
+ label: trans('timer.timerType')
+ })}
+ {props.children.defaultValue.propertyView({
+ label: trans('timer.defaultValue')
+ })}
+ {props.children.hideButton.propertyView({
+ label: trans('timer.hideButton')
+ })}
-
- {children.resetButtonStyle.getPropertyView()}
+
+ {props.children.onEvent.propertyView()}
+ {hiddenPropertyView(props.children)}
+ {showDataLoadingIndicatorsPropertyView(props.children)}
- >
- )}
- >
- ))
+ >
+ )}
+
+ {["layout", "both"].includes(useContext(EditorContext).editorModeStatus) && (
+ <>
+
+ {props.children.style.getPropertyView()}
+
+
+ {props.children.animationStyle.getPropertyView()}
+
+
+ {props.children.startButtonStyle.getPropertyView()}
+
+
+ {props.children.resetButtonStyle.getPropertyView()}
+
+ >
+ )}
+ >
+ )
+});
+
+let TimerCompBasic = (function () {
+ return new UICompBuilder(childrenMap, (props, dispatch) => )
+ .setPropertyViewFn((children) => )
.setExposeMethodConfigs([
{
method: {
@@ -294,7 +303,7 @@ let AvatarGroupBasicComp = (function () {
.build();
})();
-export const TimerComp = withExposingConfigs(AvatarGroupBasicComp, [
+export const TimerComp = withExposingConfigs(TimerCompBasic, [
new NameConfig("defaultValue", trans("timer.defaultValue")),
new NameConfig("elapsedTime", trans("timer.elapsedTime")),
new NameConfig("timerState", trans("timer.timerState")),
diff --git a/client/packages/lowcoder/src/comps/comps/transferComp.tsx b/client/packages/lowcoder/src/comps/comps/transferComp.tsx
index 300020bd7..56a20d064 100644
--- a/client/packages/lowcoder/src/comps/comps/transferComp.tsx
+++ b/client/packages/lowcoder/src/comps/comps/transferComp.tsx
@@ -1,9 +1,9 @@
-import { CompAction, RecordConstructorToView, changeChildAction } from "lowcoder-core";
+import { CompAction, RecordConstructorToComp, RecordConstructorToView, changeChildAction } from "lowcoder-core";
import { BoolControl } from "comps/controls/boolControl";
import { arrayObjectExposingStateControl, arrayStringExposingStateControl } from "comps/controls/codeStateControl";
import { styleControl } from "comps/controls/styleControl";
import { TransferStyle, TransferStyleType, heightCalculator, widthCalculator } from "comps/controls/styleControlConstants";
-import { UICompBuilder } from "comps/generators/uiCompBuilder";
+import { NewChildren, UICompBuilder } from "comps/generators/uiCompBuilder";
import { NameConfig, NameConfigHidden, withExposingConfigs } from "comps/generators/withExposing";
import { Section, sectionNames } from "lowcoder-design";
import { hiddenPropertyView, showDataLoadingIndicatorsPropertyView } from "comps/utils/propertyUtils";
@@ -17,6 +17,7 @@ import styled, { css } from "styled-components";
import { useContext, useEffect, useRef, useState } from "react";
import { valueComp, withDefault } from "../generators";
import type { TransferDirection } from 'antd/es/transfer';
+import React from "react";
const Container = styled.div<{ $style: TransferStyleType }>`
height: 100%;
@@ -71,7 +72,9 @@ const childrenMap = {
searchInfo: valueComp(['', '']),
};
-const TransferView = (props: RecordConstructorToView & {
+type ChildrenType = NewChildren>;
+
+const TransferView = React.memo((props: RecordConstructorToView & {
dispatch: (action: CompAction) => void;
}) => {
const conRef = useRef(null);
@@ -136,48 +139,54 @@ const TransferView = (props: RecordConstructorToView & {
);
-};
+});
+
+const TransferCompPropertyView = React.memo((props: {
+ children: ChildrenType
+}) => {
+ return (
+ <>
+
+ {props.children.items.propertyView({
+ label: trans("transfer.items"),
+ })}
+ {props.children.targetKeys.propertyView({
+ label: trans("transfer.targetKeys"),
+ })}
+ {props.children.sourceTitle.propertyView({
+ label: trans("transfer.sourceTitle"),
+ })}
+ {props.children.targetTitle.propertyView({
+ label: trans("transfer.targetTitle"),
+ })}
+ {props.children.showSearch.propertyView({
+ label: trans("transfer.allowSearch"),
+ })}
+ {props.children.oneWay.propertyView({
+ label: trans("transfer.oneWay"),
+ })}
+ {props.children.pagination.propertyView({
+ label: trans("transfer.pagination"),
+ })}
+ {props.children.pagination.getView() && props.children.pageSize.propertyView({
+ label: trans("transfer.pageSize"),
+ })}
+
+
+ {props.children.onEvent.propertyView()}
+ {hiddenPropertyView(props.children)}
+ {showDataLoadingIndicatorsPropertyView(props.children)}
+
+ {props.children.style.getPropertyView()}
+ >
+ )
+});
let TransferBasicComp = (function () {
return new UICompBuilder(childrenMap, (props, dispatch) => {
return (
)})
- .setPropertyViewFn((children) => (
- <>
-
- {children.items.propertyView({
- label: trans("transfer.items"),
- })}
- {children.targetKeys.propertyView({
- label: trans("transfer.targetKeys"),
- })}
- {children.sourceTitle.propertyView({
- label: trans("transfer.sourceTitle"),
- })}
- {children.targetTitle.propertyView({
- label: trans("transfer.targetTitle"),
- })}
- {children.showSearch.propertyView({
- label: trans("transfer.allowSearch"),
- })}
- {children.oneWay.propertyView({
- label: trans("transfer.oneWay"),
- })}
- {children.pagination.propertyView({
- label: trans("transfer.pagination"),
- })}
- {children.pagination.getView() && children.pageSize.propertyView({
- label: trans("transfer.pageSize"),
- })}
-
-
- {children.onEvent.propertyView()}
- {hiddenPropertyView(children)}
- {showDataLoadingIndicatorsPropertyView(children)}
-
- {children.style.getPropertyView()}
- >
- ))
+ .setPropertyViewFn((children) => )
.build();
})();
diff --git a/client/packages/lowcoder/src/comps/comps/triContainerComp/triContainerComp.tsx b/client/packages/lowcoder/src/comps/comps/triContainerComp/triContainerComp.tsx
index 307531ccf..0af8dbe95 100644
--- a/client/packages/lowcoder/src/comps/comps/triContainerComp/triContainerComp.tsx
+++ b/client/packages/lowcoder/src/comps/comps/triContainerComp/triContainerComp.tsx
@@ -27,7 +27,7 @@ import { SimpleContainerComp } from "../containerBase/simpleContainerComp";
import { ContainerBodyChildComp } from "./containerBodyChildComp";
import { trans } from "i18n";
import { ControlNode } from "lowcoder-design";
-import SliderControl from "@lowcoder-ee/comps/controls/sliderControl";
+import { SliderControl } from "@lowcoder-ee/comps/controls/sliderControl";
import { useMergeCompStyles } from "@lowcoder-ee/util/hooks";
const childrenMap = {
diff --git a/client/packages/lowcoder/src/comps/controls/actionSelector/executeQueryAction.tsx b/client/packages/lowcoder/src/comps/controls/actionSelector/executeQueryAction.tsx
index 5febe82ff..a368e73db 100644
--- a/client/packages/lowcoder/src/comps/controls/actionSelector/executeQueryAction.tsx
+++ b/client/packages/lowcoder/src/comps/controls/actionSelector/executeQueryAction.tsx
@@ -56,6 +56,9 @@ const ExecuteQueryPropertyView = ({
}, [placement]);
const getVariableOptions = useCallback((editorState?: EditorState) => {
+ const queryVariables = comp.children.queryVariables.getView();
+ if (!queryVariables.length) return null;
+
return comp.children.queryVariables.propertyView({
label: trans("eventHandler.queryVariables"),
layout: "vertical",
@@ -121,6 +124,7 @@ export class ExecuteQueryAction extends ExecuteQueryTmpAction {
if (!queryName) {
return () => Promise.resolve();
}
+
return () =>
getPromiseAfterDispatch(
this.dispatch,
diff --git a/client/packages/lowcoder/src/comps/controls/eventHandlerControl.tsx b/client/packages/lowcoder/src/comps/controls/eventHandlerControl.tsx
index 70bf77962..11f81b569 100644
--- a/client/packages/lowcoder/src/comps/controls/eventHandlerControl.tsx
+++ b/client/packages/lowcoder/src/comps/controls/eventHandlerControl.tsx
@@ -170,7 +170,7 @@ const EventHandlerControlPropertyView = (props: {
const queryVariables = editorState
?.selectedOrFirstQueryComp()
- ?.children.variables.children.variables.toJsonValue();
+ ?.children.variables.toJsonValue();
const queryExecHandler = {
compType: "executeQuery",
diff --git a/client/packages/lowcoder/src/comps/controls/keyValueControl.tsx b/client/packages/lowcoder/src/comps/controls/keyValueControl.tsx
index 319d8ac0a..6b9018cc3 100644
--- a/client/packages/lowcoder/src/comps/controls/keyValueControl.tsx
+++ b/client/packages/lowcoder/src/comps/controls/keyValueControl.tsx
@@ -6,7 +6,7 @@ import { StringControl } from "./codeControl";
import { ControlParams } from "./controlParams";
import { dropdownControl } from "./dropdownControl";
import { ParamsStringControl } from "./paramsControl";
-import { SimpleVariableHeaderComp } from "../comps/simpleVariableHeaderComp";
+import { SimpleNameComp } from "../comps/simpleNameComp";
const KeyValueWrapper = styled.div`
display: flex;
@@ -68,8 +68,8 @@ export function keyValueControl(
};
if(controlType === "variable") {
childrenMap = {
- key: SimpleVariableHeaderComp(true) as any,
- value: SimpleVariableHeaderComp() as any,
+ key: SimpleNameComp as any,
+ value: StringControl,
type: dropdownControl(types, types[0]?.value),
};
}
diff --git a/client/packages/lowcoder/src/comps/controls/sliderControl.tsx b/client/packages/lowcoder/src/comps/controls/sliderControl.tsx
index 4161667a8..a02562887 100644
--- a/client/packages/lowcoder/src/comps/controls/sliderControl.tsx
+++ b/client/packages/lowcoder/src/comps/controls/sliderControl.tsx
@@ -31,4 +31,4 @@ class SliderControl extends SimpleComp {
}
}
-export default SliderControl;
+export { SliderControl };
diff --git a/client/packages/lowcoder/src/comps/editorState.tsx b/client/packages/lowcoder/src/comps/editorState.tsx
index 02f2d200a..ff928f6f6 100644
--- a/client/packages/lowcoder/src/comps/editorState.tsx
+++ b/client/packages/lowcoder/src/comps/editorState.tsx
@@ -509,7 +509,7 @@ export class EditorState {
//Check query variable name duplication
const queryComInfoList:string[] = [].concat(...(this.getQueriesComp()
- .toJsonValue().map((item: any) => item.variables.variables.map((v: any) => v.key))));
+ .toJsonValue().map((item: any) => item.variables.map((v: any) => v.key))));
if (name !== oldName && queryComInfoList.includes(name)) {
return trans("comp.nameExists", { name: name });
diff --git a/client/packages/lowcoder/src/comps/generators/hookToComp.tsx b/client/packages/lowcoder/src/comps/generators/hookToComp.tsx
index 40e92bf4b..68dce72cd 100644
--- a/client/packages/lowcoder/src/comps/generators/hookToComp.tsx
+++ b/client/packages/lowcoder/src/comps/generators/hookToComp.tsx
@@ -36,9 +36,11 @@ export function hookToStateComp(useHookFn: () => JSONObject) {
const hookValue = useHookFn();
const stateValue = useMemo(() => comp.children.stateValue.getView(), [comp.children.stateValue]);
- if (!isEqual(hookValue, stateValue)) {
- comp.children.stateValue.dispatchChangeValueAction(hookValue);
- }
+ useEffect(() => {
+ if (!isEqual(hookValue, stateValue)) {
+ comp.children.stateValue.dispatchChangeValueAction(hookValue);
+ }
+ }, [hookValue, stateValue]);
return null;
}
);
diff --git a/client/packages/lowcoder/src/comps/generators/withMultiContext.tsx b/client/packages/lowcoder/src/comps/generators/withMultiContext.tsx
index a8bcd8f44..ec843eb91 100644
--- a/client/packages/lowcoder/src/comps/generators/withMultiContext.tsx
+++ b/client/packages/lowcoder/src/comps/generators/withMultiContext.tsx
@@ -125,7 +125,11 @@ export function withMultiContext(VariantComp
const params = this.cacheParamsMap.get(key);
if (_.isNil(comp) && !_.isNil(params)) {
const mapComps = this.getMap();
- if (mapComps.hasOwnProperty(key) && !paramsEqual(params, mapComps[key].getParams())) {
+ if (
+ Object.keys(mapComps).length === Object.keys(this.cacheParamsMap.getMap()).length
+ && mapComps.hasOwnProperty(key)
+ && !paramsEqual(params, mapComps[key].getParams())
+ ) {
// refresh the item, since params changed
// this.dispatch(deferAction(wrapChildAction(MAP_KEY, MapCtor.batchDeleteAction([key]))));
this.dispatch(wrapChildAction(MAP_KEY, MapCtor.batchDeleteAction([key])));
@@ -177,16 +181,18 @@ export function withMultiContext(VariantComp
const params = comp.cacheParamsMap.get(key);
if (params) {
const childComp = comp
- .getComp(key)!
+ .getOriginalComp()
.setParams(params)
.changeDispatch(wrapDispatch(wrapDispatch(comp.dispatch, MAP_KEY), key));
const newChildComp = childComp.reduce(childAction);
- const comps = { [key]: newChildComp };
- comp = comp.setChild(
- MAP_KEY,
- comp.children[MAP_KEY].reduce(MapCtor.batchSetCompAction(comps))
- );
+ if (childComp !== newChildComp) {
+ const comps = { [key]: newChildComp };
+ comp = comp.setChild(
+ MAP_KEY,
+ comp.children[MAP_KEY].reduce(MapCtor.batchSetCompAction(comps))
+ );
+ }
}
} else {
comp = super.reduce(action);
diff --git a/client/packages/lowcoder/src/comps/hooks/drawerComp.tsx b/client/packages/lowcoder/src/comps/hooks/drawerComp.tsx
index 9d52075e9..d607c3211 100644
--- a/client/packages/lowcoder/src/comps/hooks/drawerComp.tsx
+++ b/client/packages/lowcoder/src/comps/hooks/drawerComp.tsx
@@ -25,7 +25,9 @@ import { useUserViewMode } from "util/hooks";
import { isNumeric } from "util/stringUtils";
import { NameConfig, withExposingConfigs } from "../generators/withExposing";
import { title } from "process";
-import SliderControl from "../controls/sliderControl";
+import { SliderControl } from "../controls/sliderControl";
+import clsx from "clsx";
+import { useApplicationId } from "util/hooks";
const EventOptions = [closeEvent] as const;
@@ -119,6 +121,7 @@ let TmpDrawerComp = (function () {
const isTopBom = ["top", "bottom"].includes(props.placement);
const { items, ...otherContainerProps } = props.container;
const userViewMode = useUserViewMode();
+ const appID = useApplicationId();
const resizable = !userViewMode && (!isTopBom || !props.autoHeight);
const onResizeStop = useCallback(
(
@@ -172,7 +175,7 @@ let TmpDrawerComp = (function () {
zIndex={Layers.drawer}
maskClosable={props.maskClosable}
mask={props.showMask}
- className={props.className as string}
+ className={clsx(`app-${appID}`, props.className)}
data-testid={props.dataTestId as string}
>
{props.toggleClose && (
diff --git a/client/packages/lowcoder/src/comps/hooks/modalComp.tsx b/client/packages/lowcoder/src/comps/hooks/modalComp.tsx
index 2a3235f9d..7cdcbe4fd 100644
--- a/client/packages/lowcoder/src/comps/hooks/modalComp.tsx
+++ b/client/packages/lowcoder/src/comps/hooks/modalComp.tsx
@@ -22,8 +22,10 @@ import { isNumeric } from "util/stringUtils";
import { NameConfig, withExposingConfigs } from "../generators/withExposing";
import { BoolControl } from "comps/controls/boolControl";
import { withDefault } from "comps/generators";
-import SliderControl from "../controls/sliderControl";
+import { SliderControl } from "../controls/sliderControl";
import { getBackgroundStyle } from "@lowcoder-ee/util/styleUtils";
+import clsx from "clsx";
+import { useApplicationId } from "util/hooks";
const EventOptions = [
{ label: trans("modalComp.open"), value: "open", description: trans("modalComp.openDesc") },
@@ -113,6 +115,7 @@ let TmpModalComp = (function () {
},
(props, dispatch) => {
const userViewMode = useUserViewMode();
+ const appID = useApplicationId();
const bodyStyle: CSSProperties = { padding: 0 };
const width = transToPxSize(props.width || DEFAULT_WIDTH);
let height = undefined;
@@ -177,7 +180,7 @@ let TmpModalComp = (function () {
zIndex={Layers.modal}
modalRender={(node) => {node} }
mask={props.showMask}
- className={props.className as string}
+ className={clsx(`app-${appID}`, props.className)}
data-testid={props.dataTestId as string}
>
{
+ return canvasContainer?.clientWidth || canvas?.clientWidth;
+ }, [canvasContainer?.clientWidth, canvas?.clientWidth]);
const getDeviceType = (width: number) => {
if (width < 768) return ScreenTypes.Mobile;
@@ -71,7 +73,9 @@ export function useScreenInfo() {
}, [ updateScreenInfo ])
useEffect(() => {
- updateScreenInfo();
+ if (canvasWidth) {
+ updateScreenInfo();
+ }
}, [canvasWidth]);
return screenInfo;
diff --git a/client/packages/lowcoder/src/comps/hooks/themeComp.tsx b/client/packages/lowcoder/src/comps/hooks/themeComp.tsx
index 7fdff5ed0..8e11723fa 100644
--- a/client/packages/lowcoder/src/comps/hooks/themeComp.tsx
+++ b/client/packages/lowcoder/src/comps/hooks/themeComp.tsx
@@ -64,12 +64,15 @@ let ThemeTempComp = withViewFn(
return stateValue;
}, [themeList, currentTheme, stateValue])
- if (!isEqual(themeValue, stateValue)) {
- comp.children.stateValue.dispatchChangeValueAction({
- ...exposingTheme(currentTheme),
- allThemes: themeList.map((t) => exposingTheme(t)),
- })
- }
+ useEffect(() => {
+ if (!isEqual(themeValue, stateValue)) {
+ comp.children.stateValue.dispatchChangeValueAction({
+ ...exposingTheme(currentTheme),
+ allThemes: themeList.map((t) => exposingTheme(t)),
+ })
+ }
+ }, [themeValue, stateValue]);
+
return null;
}
);
diff --git a/client/packages/lowcoder/src/comps/hooks/utilsComp.ts b/client/packages/lowcoder/src/comps/hooks/utilsComp.ts
index 7824b1439..f91bae194 100644
--- a/client/packages/lowcoder/src/comps/hooks/utilsComp.ts
+++ b/client/packages/lowcoder/src/comps/hooks/utilsComp.ts
@@ -8,6 +8,8 @@ import { openApp, recordToSearchStr } from "../../util/appUtils";
import { trans } from "i18n";
import { logoutAction } from "redux/reduxActions/userActions";
import StoreRegistry from "@lowcoder-ee/redux/store/storeRegistry";
+import UserApi from "@lowcoder-ee/api/userApi";
+import { messageInstance } from "components/GlobalInstances";
const UtilsCompBase = simpleMultiComp({});
export let UtilsComp = withExposingConfigs(UtilsCompBase, []);
@@ -121,4 +123,33 @@ UtilsComp = withMethodExposing(UtilsComp, [
);
},
},
+ {
+ method: {
+ name: "resetPassword",
+ description: trans("utilsComp.resetPassword"),
+ params: [
+ { name: "oldPassword", type: "string" },
+ { name: "newPassword", type: "string" },
+ ],
+ },
+ execute: async (comp, params) => {
+ const oldPassword = params?.[0];
+ const newPassword = params?.[1];
+ try {
+ if (Boolean(oldPassword) && Boolean(newPassword)) {
+ const response = await UserApi.updatePassword({
+ oldPassword: oldPassword as string,
+ newPassword: newPassword as string,
+ });
+ if (!response.data.success) {
+ throw (new Error(response.data.message));
+ }
+ } else {
+ throw(new Error('Reset password requires both old and new passwords'))
+ }
+ } catch(e: any) {
+ messageInstance.error(e.message)
+ }
+ },
+ }
]);
diff --git a/client/packages/lowcoder/src/comps/index.tsx b/client/packages/lowcoder/src/comps/index.tsx
index 4acecfd14..f6ce3e1c3 100644
--- a/client/packages/lowcoder/src/comps/index.tsx
+++ b/client/packages/lowcoder/src/comps/index.tsx
@@ -97,7 +97,6 @@ import {
CandlestickChartCompIcon,
FunnelChartCompIcon,
- // GraphChartCompIcon,
HeatmapChartCompIcon,
GaugeChartCompIcon,
RadarChartCompIcon,
@@ -115,7 +114,10 @@ import {
GraphChartCompIcon,
GanttCompIcon,
KanbanCompIcon,
-
+ PieChartCompIcon,
+ BarChartCompIcon,
+ LineChartCompIcon,
+ ScatterChartCompIcon
} from "lowcoder-design";
import { ModuleComp } from "./comps/moduleComp/moduleComp";
import { TableComp } from "./comps/tableComp/tableComp";
@@ -128,6 +130,68 @@ import { TextComp } from "./comps/textComp";
import { SelectComp } from "./comps/selectInputComp/selectComp";
import { InputComp } from "./comps/textInputComp/inputComp";
import { TextAreaComp } from "./comps/textInputComp/textAreaComp";
+import { AutoCompleteComp } from "./comps/autoCompleteComp/autoCompleteComp";
+import { AvatarComp } from "./comps/avatar";
+import { AvatarGroupComp } from "./comps/avatarGroup";
+import { DropdownComp } from "./comps/buttonComp/dropdownComp";
+import { FloatButtonComp } from "./comps/buttonComp/floatButtonComp";
+import { LinkComp } from "./comps/buttonComp/linkComp";
+import { ScannerComp } from "./comps/buttonComp/scannerComp";
+import { ToggleButtonComp } from "./comps/buttonComp/toggleButtonComp";
+import { CarouselComp } from "./comps/carouselComp";
+import { CommentComp } from "./comps/commentComp/commentComp";
+import { CardComp } from "./comps/containerComp/cardComp";
+import { CustomComp } from "./comps/customComp/customComp";
+import { DatePickerComp, DateRangeComp } from "./comps/dateComp/dateComp";
+import { TimePickerComp, TimeRangeComp } from "./comps/dateComp/timeComp";
+import { DividerComp } from "./comps/dividerComp";
+import { FileComp } from "./comps/fileComp/fileComp";
+import { FileViewerComp } from "./comps/fileViewerComp";
+import { defaultFormData, FormComp } from "./comps/formComp/formComp";
+import { IconComp } from "./comps/iconComp";
+import { IFrameComp } from "./comps/iframeComp";
+import { ImageComp } from "./comps/imageComp";
+import { JsonEditorComp } from "./comps/jsonComp/jsonEditorComp";
+import { JsonExplorerComp } from "./comps/jsonComp/jsonExplorerComp";
+import { JsonLottieComp } from "./comps/jsonComp/jsonLottieComp";
+import { JsonSchemaFormComp } from "./comps/jsonSchemaFormComp/jsonSchemaFormComp";
+import { ListViewComp, GridComp, defaultListViewData, defaultGridData } from "./comps/listViewComp";
+import { AudioComp } from "./comps/mediaComp/audioComp";
+import { ColorPickerComp } from "./comps/mediaComp/colorPickerComp";
+import { VideoComp } from "./comps/mediaComp/videoComp";
+import { ControlButton } from "./comps/meetingComp/controlButton";
+import { NavComp } from "./comps/navComp/navComp";
+import { NumberInputComp } from "./comps/numberInputComp/numberInputComp";
+import { RangeSliderComp } from "./comps/numberInputComp/rangeSliderComp";
+import { SliderComp } from "./comps/numberInputComp/sliderComp";
+import { defaultPageLayoutData, PageLayoutComp } from "./comps/containerComp/pageLayoutComp";
+import { ProgressCircleComp } from "./comps/progressCircleComp";
+import { ProgressComp } from "./comps/progressComp";
+import { QRCodeComp } from "./comps/qrCodeComp";
+import { RatingComp } from "./comps/ratingComp";
+import { ResponsiveLayoutComp } from "./comps/responsiveLayout";
+import { RichTextEditorComp } from "./comps/richTextEditorComp";
+import { CascaderWithDefault } from "./comps/selectInputComp/cascaderComp";
+import { CheckboxComp } from "./comps/selectInputComp/checkboxComp";
+import { MultiSelectComp } from "./comps/selectInputComp/multiSelectComp";
+import { RadioComp } from "./comps/selectInputComp/radioComp";
+import { SegmentedControlComp } from "./comps/selectInputComp/segmentedControl";
+import { StepComp } from "./comps/selectInputComp/stepControl";
+import { ShapeComp } from "./comps/shapeComp/shapeComp";
+import { SignatureComp } from "./comps/signatureComp";
+import { SplitLayoutComp } from "./comps/splitLayout";
+import { SwitchComp } from "./comps/switchComp";
+import { MentionComp } from "./comps/textInputComp/mentionComp";
+import { PasswordComp } from "./comps/textInputComp/passwordComp";
+import { TimeLineComp } from "./comps/timelineComp/timelineComp";
+import { TimerComp } from "./comps/timerComp";
+import { TourComp } from "./comps/tourComp/tourComp";
+import { transferComp } from "./comps/transferComp";
+import { TreeComp } from "./comps/treeComp/treeComp";
+import { TreeSelectComp } from "./comps/treeComp/treeSelectComp";
+import { DrawerComp } from "./hooks/drawerComp";
+import { ModalComp } from "./hooks/modalComp";
+import { defaultCollapsibleContainerData } from "./comps/containerComp/collapsibleContainerComp";
type Registry = {
[key in UICompType]?: UICompManifest;
@@ -145,10 +209,10 @@ export var uiCompMap: Registry = {
// charts
chart: {
- name: trans("uiComp.chartCompName") + " (legacy)",
+ name: trans("uiComp.chartCompName"),
enName: "Chart",
description: trans("uiComp.chartCompDesc"),
- categories: ["dashboards"],
+ categories: ["legacy"],
icon: ChartCompIcon,
comp: remoteComp({ ...builtInRemoteComps, compName: "chart" }),
keywords: trans("uiComp.chartCompKeywords"),
@@ -162,7 +226,7 @@ export var uiCompMap: Registry = {
name: trans("uiComp.basicChartCompName"),
enName: "Basic Chart",
description: trans("uiComp.basicChartCompDesc"),
- categories: ["dashboards"],
+ categories: ["legacy"],
icon: ChartCompIcon,
comp: remoteComp({ ...builtInRemoteComps, compName: "basicChart" }),
keywords: trans("uiComp.basicChartCompKeywords"),
@@ -172,6 +236,62 @@ export var uiCompMap: Registry = {
},
},
+ barChart: {
+ name: trans("uiComp.barChartCompName"),
+ enName: "Bar Chart",
+ description: trans("uiComp.barChartCompDesc"),
+ categories: ["dashboards"],
+ icon: BarChartCompIcon,
+ comp: remoteComp({ ...builtInRemoteComps, compName: "barChart" }),
+ keywords: trans("uiComp.barChartCompKeywords"),
+ layoutInfo: {
+ w: 12,
+ h: 40,
+ },
+ },
+
+ lineChart: {
+ name: trans("uiComp.lineChartCompName"),
+ enName: "Line Chart",
+ description: trans("uiComp.lineChartCompDesc"),
+ categories: ["dashboards"],
+ icon: LineChartCompIcon,
+ comp: remoteComp({ ...builtInRemoteComps, compName: "lineChart" }),
+ keywords: trans("uiComp.lineChartCompKeywords"),
+ layoutInfo: {
+ w: 12,
+ h: 40,
+ },
+ },
+
+ pieChart: {
+ name: trans("uiComp.pieChartCompName"),
+ enName: "Pie Chart",
+ description: trans("uiComp.piehartCompDesc"),
+ categories: ["dashboards"],
+ icon: PieChartCompIcon,
+ comp: remoteComp({ ...builtInRemoteComps, compName: "pieChart" }),
+ keywords: trans("uiComp.pieChartCompKeywords"),
+ layoutInfo: {
+ w: 12,
+ h: 40,
+ },
+ },
+
+ scatterChart: {
+ name: trans("uiComp.scatterChartCompName"),
+ enName: "Scatter Chart",
+ description: trans("uiComp.scatterChartCompDesc"),
+ categories: ["dashboards"],
+ icon: ScatterChartCompIcon,
+ comp: remoteComp({ ...builtInRemoteComps, compName: "scatterChart" }),
+ keywords: trans("uiComp.scatterChartCompKeywords"),
+ layoutInfo: {
+ w: 12,
+ h: 40,
+ },
+ },
+
candleStickChart: {
name: trans("uiComp.candleStickChartCompName"),
enName: "Candlestick Chart",
@@ -407,9 +527,7 @@ export var uiCompMap: Registry = {
categories: ["dashboards"],
icon: TimeLineCompIcon,
keywords: trans("uiComp.timelineCompKeywords"),
- lazyLoad: true,
- compName: "TimeLineComp",
- compPath: "comps/timelineComp/timelineComp",
+ comp: TimeLineComp,
layoutInfo: {
w: 12,
h: 40,
@@ -425,9 +543,7 @@ export var uiCompMap: Registry = {
categories: ["layout"],
icon: ResponsiveLayoutCompIcon,
keywords: trans("uiComp.responsiveLayoutCompKeywords"),
- lazyLoad: true,
- compName: "ResponsiveLayoutComp",
- compPath: "comps/responsiveLayout/index",
+ comp: ResponsiveLayoutComp,
withoutLoading: true,
layoutInfo: {
w: 24,
@@ -442,9 +558,7 @@ export var uiCompMap: Registry = {
categories: ["layout"],
icon: PageLayoutCompIcon,
keywords: trans("uiComp.pageLayoutCompKeywords"),
- lazyLoad: true,
- compName: "PageLayoutComp",
- compPath: "comps/containerComp/pageLayoutComp",
+ comp: PageLayoutComp,
withoutLoading: true,
layoutInfo: {
w: 12,
@@ -452,8 +566,7 @@ export var uiCompMap: Registry = {
// static: true,
delayCollision: true,
},
- defaultDataFnName: "defaultPageLayoutData",
- defaultDataFnPath: "comps/tableComp/mockTableComp",
+ defaultDataFn: defaultPageLayoutData,
},
columnLayout: {
name: "Column Layout",
@@ -477,9 +590,7 @@ export var uiCompMap: Registry = {
categories: ["layout"],
icon: SplitLayoutCompIcon,
keywords: trans("uiComp.splitLayoutCompKeywords"),
- lazyLoad: true,
- compName: "SplitLayoutComp",
- compPath: "comps/splitLayout/index",
+ comp: SplitLayoutComp,
withoutLoading: true,
layoutInfo: {
w: 24,
@@ -494,9 +605,7 @@ export var uiCompMap: Registry = {
categories: ["layout"],
icon: FloatingTextCompIcon,
keywords: trans("uiComp.floatTextContainerCompKeywords"),
- lazyLoad: true,
- compName: "ContainerComp",
- compPath: "comps/containerComp/textContainerComp",
+ comp: ContainerComp,
withoutLoading: true,
layoutInfo: {
w: 12,
@@ -504,8 +613,7 @@ export var uiCompMap: Registry = {
// static: true,
delayCollision: true,
},
- defaultDataFnName: "defaultContainerData",
- defaultDataFnPath: "comps/containerComp/containerComp",
+ defaultDataFn: defaultContainerData,
},
card: {
name: trans("uiComp.cardCompName"),
@@ -514,9 +622,7 @@ export var uiCompMap: Registry = {
description: trans("uiComp.cardCompDesc"),
categories: ["layout"],
keywords: trans("uiComp.cardCompKeywords"),
- lazyLoad: true,
- compName: "CardComp",
- compPath: "comps/containerComp/cardComp",
+ comp: CardComp,
layoutInfo: {
h: 44,
w: 6,
@@ -545,9 +651,7 @@ export var uiCompMap: Registry = {
categories: ["layout"],
icon: CollapsibleContainerCompIcon,
keywords: trans("uiComp.collapsibleContainerCompKeywords"),
- lazyLoad: true,
- compName: "ContainerComp",
- compPath: "comps/containerComp/containerComp",
+ comp: ContainerComp,
withoutLoading: true,
layoutInfo: {
w: 12,
@@ -555,8 +659,7 @@ export var uiCompMap: Registry = {
// static: true,
delayCollision: true,
},
- defaultDataFnName: "defaultCollapsibleContainerData",
- defaultDataFnPath: "comps/containerComp/collapsibleContainerComp",
+ defaultDataFn: defaultCollapsibleContainerData,
},
container: {
name: trans("uiComp.containerCompName"),
@@ -582,16 +685,13 @@ export var uiCompMap: Registry = {
description: trans("uiComp.listViewCompDesc"),
categories: ["layout"],
keywords: trans("uiComp.listViewCompKeywords"),
- lazyLoad: true,
- compName: "ListViewComp",
- compPath: "comps/listViewComp/index",
+ comp: ListViewComp,
layoutInfo: {
w: 12,
h: 40,
delayCollision: true,
},
- defaultDataFnName: "defaultListViewData",
- defaultDataFnPath: "comps/listViewComp/index",
+ defaultDataFn: defaultListViewData,
},
grid: {
name: trans("uiComp.gridCompName"),
@@ -600,16 +700,13 @@ export var uiCompMap: Registry = {
description: trans("uiComp.gridCompDesc"),
categories: ["layout"],
keywords: trans("uiComp.gridCompKeywords"),
- lazyLoad: true,
- compName: "GridComp",
- compPath: "comps/listViewComp/index",
+ comp: GridComp,
layoutInfo: {
w: 12,
h: 40,
delayCollision: true,
},
- defaultDataFnName: "defaultGridData",
- defaultDataFnPath: "comps/listViewComp/index",
+ defaultDataFn: defaultGridData,
},
modal: {
name: trans("uiComp.modalCompName"),
@@ -618,9 +715,7 @@ export var uiCompMap: Registry = {
description: trans("uiComp.modalCompDesc"),
categories: ["layout"],
keywords: trans("uiComp.modalCompKeywords"),
- lazyLoad: true,
- compName: "ModalComp",
- compPath: "hooks/modalComp",
+ comp: ModalComp,
withoutLoading: true,
},
drawer: {
@@ -630,9 +725,7 @@ export var uiCompMap: Registry = {
categories: ["layout"],
icon: DrawerCompIcon,
keywords: trans("uiComp.drawerCompKeywords"),
- lazyLoad: true,
- compName: "DrawerComp",
- compPath: "hooks/drawerComp",
+ comp: DrawerComp,
withoutLoading: true,
},
divider: {
@@ -642,9 +735,7 @@ export var uiCompMap: Registry = {
categories: ["layout"],
icon: DividerCompIcon,
keywords: trans("uiComp.dividerCompKeywords"),
- lazyLoad: true,
- compName: "DividerComp",
- compPath: "comps/dividerComp",
+ comp: DividerComp,
layoutInfo: {
w: 12,
h: 1,
@@ -657,9 +748,7 @@ export var uiCompMap: Registry = {
icon: NavComIcon,
categories: ["layout"],
keywords: trans("uiComp.navigationCompKeywords"),
- lazyLoad: true,
- compName: "NavComp",
- compPath: "comps/navComp/navComp",
+ comp: NavComp,
layoutInfo: {
w: 24,
h: 5,
@@ -672,9 +761,7 @@ export var uiCompMap: Registry = {
categories: ["layout"],
icon: StepCompIcon,
keywords: trans("uiComp.stepControlCompKeywords"),
- lazyLoad: true,
- compName: "StepComp",
- compPath: "comps/selectInputComp/stepControl",
+ comp: StepComp,
layoutInfo: {
w: 19,
h: 6,
@@ -687,9 +774,7 @@ export var uiCompMap: Registry = {
categories: ["layout"],
icon: CascaderCompIcon,
keywords: trans("uiComp.cascaderCompKeywords"),
- lazyLoad: true,
- compName: "CascaderWithDefault",
- compPath: "comps/selectInputComp/cascaderComp",
+ comp: CascaderWithDefault,
layoutInfo: {
w: 9,
h: 5,
@@ -702,9 +787,7 @@ export var uiCompMap: Registry = {
categories: ["layout"],
icon: LinkCompIcon,
keywords: trans("uiComp.linkCompKeywords"),
- lazyLoad: true,
- compName: "LinkComp",
- compPath: "comps/buttonComp/linkComp",
+ comp: LinkComp,
layoutInfo: {
w: 6,
h: 5,
@@ -717,9 +800,7 @@ export var uiCompMap: Registry = {
categories: ["layout"],
icon: FloatingButtonCompIcon,
keywords: trans("uiComp.floatButtonCompKeywords"),
- lazyLoad: true,
- compName: "FloatButtonComp",
- compPath: "comps/buttonComp/floatButtonComp",
+ comp: FloatButtonComp,
layoutInfo: {
w: 1,
h: 1,
@@ -749,9 +830,7 @@ export var uiCompMap: Registry = {
description: trans("uiComp.timerCompDesc"),
categories: ["scheduling", "projectmanagement"],
keywords: trans("uiComp.timerCompKeywords"),
- lazyLoad: true,
- compName: "TimerComp",
- compPath: "comps/timerComp",
+ comp: TimerComp,
layoutInfo: {
h: 14,
w: 6,
@@ -807,9 +886,7 @@ export var uiCompMap: Registry = {
categories: ["collaboration"],
icon: AvatarCompIcon,
keywords: trans("uiComp.avatarCompKeywords"),
- lazyLoad: true,
- compName: "AvatarComp",
- compPath: "comps/avatar",
+ comp: AvatarComp,
layoutInfo: {
w: 6,
h: 6,
@@ -823,9 +900,7 @@ export var uiCompMap: Registry = {
description: trans("uiComp.avatarGroupCompDesc"),
categories: ["collaboration"],
keywords: trans("uiComp.avatarGroupCompKeywords"),
- lazyLoad: true,
- compName: "AvatarGroupComp",
- compPath: "comps/avatarGroup",
+ comp: AvatarGroupComp,
withoutLoading: true,
layoutInfo: {
w: 6,
@@ -840,9 +915,7 @@ export var uiCompMap: Registry = {
categories: ["collaboration"],
icon: CommentCompIcon,
keywords: trans("uiComp.commentCompKeywords"),
- lazyLoad: true,
- compName: "CommentComp",
- compPath: "comps/commentComp/commentComp",
+ comp: CommentComp,
layoutInfo: {
w: 12,
h: 55,
@@ -855,9 +928,7 @@ export var uiCompMap: Registry = {
categories: ["collaboration"],
icon: MentionCompIcon,
keywords: trans("uiComp.mentionCompKeywords"),
- lazyLoad: true,
- compName: "MentionComp",
- compPath: "comps/textInputComp/mentionComp",
+ comp: MentionComp,
},
// Forms
@@ -869,9 +940,7 @@ export var uiCompMap: Registry = {
categories: ["forms"],
icon: FormCompIcon,
keywords: trans("uiComp.formCompKeywords"),
- lazyLoad: true,
- compName: "FormComp",
- compPath: "comps/formComp/formComp",
+ comp: FormComp,
withoutLoading: true,
layoutInfo: {
w: 12,
@@ -879,8 +948,7 @@ export var uiCompMap: Registry = {
// static: true,
delayCollision: true,
},
- defaultDataFnName: "defaultFormData",
- defaultDataFnPath: "comps/formComp/formComp",
+ defaultDataFn: defaultFormData,
},
jsonSchemaForm: {
name: trans("uiComp.jsonSchemaFormCompName"),
@@ -889,9 +957,7 @@ export var uiCompMap: Registry = {
categories: ["forms"],
icon: JsonFormCompIcon,
keywords: trans("uiComp.jsonSchemaFormCompKeywords"),
- lazyLoad: true,
- compName: "JsonSchemaFormComp",
- compPath: "comps/jsonSchemaFormComp/jsonSchemaFormComp",
+ comp: JsonSchemaFormComp,
layoutInfo: {
w: 12,
h: 50,
@@ -904,9 +970,7 @@ export var uiCompMap: Registry = {
categories: ["forms"],
icon: JsonEditorCompIcon,
keywords: trans("uiComp.jsonEditorCompKeywords"),
- lazyLoad: true,
- compName: "JsonEditorComp",
- compPath: "comps/jsonComp/jsonEditorComp",
+ comp: JsonEditorComp,
layoutInfo: {
w: 12,
h: 50,
@@ -919,9 +983,7 @@ export var uiCompMap: Registry = {
categories: ["forms"],
icon: JsonExplorerCompIcon,
keywords: trans("uiComp.jsonExplorerCompKeywords"),
- lazyLoad: true,
- compName: "JsonExplorerComp",
- compPath: "comps/jsonComp/jsonExplorerComp",
+ comp: JsonExplorerComp,
layoutInfo: {
w: 12,
h: 50,
@@ -934,9 +996,7 @@ export var uiCompMap: Registry = {
description: trans("uiComp.richTextEditorCompDesc"),
icon: RichTextEditorCompIcon,
keywords: trans("uiComp.richTextEditorCompKeywords"),
- lazyLoad: true,
- compName: "RichTextEditorComp",
- compPath: "comps/richTextEditorComp",
+ comp: RichTextEditorComp,
layoutInfo: {
w: 12,
h: 50,
@@ -962,9 +1022,7 @@ export var uiCompMap: Registry = {
categories: ["forms"],
icon: PasswordCompIcon,
keywords: trans("uiComp.passwordCompKeywords"),
- lazyLoad: true,
- compName: "PasswordComp",
- compPath: "comps/textInputComp/passwordComp",
+ comp: PasswordComp,
layoutInfo: {
w: 6,
h: 6,
@@ -977,9 +1035,7 @@ export var uiCompMap: Registry = {
categories: ["forms"],
icon: NumberInputCompIcon,
keywords: trans("uiComp.numberInputCompKeywords"),
- lazyLoad: true,
- compName: "NumberInputComp",
- compPath: "comps/numberInputComp/numberInputComp",
+ comp: NumberInputComp,
layoutInfo: {
w: 6,
h: 6,
@@ -1007,9 +1063,10 @@ export var uiCompMap: Registry = {
keywords: cnchar
.spell(trans("uiComp.autoCompleteCompName"), "first", "low")
.toString(),
- lazyLoad: true,
- compName: "AutoCompleteComp",
- compPath: "comps/autoCompleteComp/autoCompleteComp",
+ comp: AutoCompleteComp,
+ // lazyLoad: true,
+ // compName: "AutoCompleteComp",
+ // compPath: "comps/autoCompleteComp/autoCompleteComp",
layoutInfo: {
w: 6,
h: 5,
@@ -1022,9 +1079,7 @@ export var uiCompMap: Registry = {
categories: ["forms"],
icon: SwitchCompIcon,
keywords: trans("uiComp.switchCompKeywords"),
- lazyLoad: true,
- compName: "SwitchComp",
- compPath: "comps/switchComp",
+ comp: SwitchComp,
layoutInfo: {
w: 6,
h: 6,
@@ -1037,9 +1092,7 @@ export var uiCompMap: Registry = {
categories: ["forms"],
icon: CheckboxCompIcon,
keywords: trans("uiComp.checkboxCompKeywords"),
- lazyLoad: true,
- compName: "CheckboxComp",
- compPath: "comps/selectInputComp/checkboxComp",
+ comp: CheckboxComp,
layoutInfo: {
w: 6,
h: 6,
@@ -1052,9 +1105,7 @@ export var uiCompMap: Registry = {
categories: ["forms"],
icon: RadioCompIcon,
keywords: trans("uiComp.radioCompKeywords"),
- lazyLoad: true,
- compName: "RadioComp",
- compPath: "comps/selectInputComp/radioComp",
+ comp: RadioComp,
layoutInfo: {
w: 6,
h: 6,
@@ -1067,9 +1118,7 @@ export var uiCompMap: Registry = {
categories: ["forms", "scheduling"],
icon: DateCompIcon,
keywords: trans("uiComp.dateCompKeywords"),
- lazyLoad: true,
- compName: "DatePickerComp",
- compPath: "comps/dateComp/dateComp",
+ comp: DatePickerComp,
layoutInfo: {
w: 6,
h: 6,
@@ -1082,9 +1131,7 @@ export var uiCompMap: Registry = {
categories: ["forms", "scheduling"],
icon: DateRangeCompIcon,
keywords: trans("uiComp.dateRangeCompKeywords"),
- lazyLoad: true,
- compName: "DateRangeComp",
- compPath: "comps/dateComp/dateComp",
+ comp: DateRangeComp,
layoutInfo: {
w: 12,
h: 6,
@@ -1097,9 +1144,7 @@ export var uiCompMap: Registry = {
categories: ["forms", "scheduling"],
icon: TimeCompIcon,
keywords: trans("uiComp.timeCompKeywords"),
- lazyLoad: true,
- compName: "TimePickerComp",
- compPath: "comps/dateComp/timeComp",
+ comp: TimePickerComp,
layoutInfo: {
w: 6,
h: 6,
@@ -1112,9 +1157,7 @@ export var uiCompMap: Registry = {
description: trans("uiComp.timeRangeCompDesc"),
icon: TimeRangeCompIcon,
keywords: trans("uiComp.timeRangeCompKeywords"),
- lazyLoad: true,
- compName: "TimeRangeComp",
- compPath: "comps/dateComp/timeComp",
+ comp: TimeRangeComp,
layoutInfo: {
w: 12,
h: 6,
@@ -1128,9 +1171,7 @@ export var uiCompMap: Registry = {
categories: ["forms"],
icon: SliderCompIcon,
keywords: trans("uiComp.sliderCompKeywords"),
- lazyLoad: true,
- compName: "SliderComp",
- compPath: "comps/numberInputComp/sliderComp",
+ comp: SliderComp,
layoutInfo: {
w: 6,
h: 5,
@@ -1143,9 +1184,7 @@ export var uiCompMap: Registry = {
categories: ["forms"],
icon: RangeSliderCompIcon,
keywords: trans("uiComp.rangeSliderCompKeywords"),
- lazyLoad: true,
- compName: "RangeSliderComp",
- compPath: "comps/numberInputComp/rangeSliderComp",
+ comp: RangeSliderComp,
layoutInfo: {
w: 6,
h: 5,
@@ -1173,9 +1212,7 @@ export var uiCompMap: Registry = {
categories: ["forms", "collaboration"],
icon: IconButtonCompIcon,
keywords: trans("uiComp.meetingCompKeywords"),
- lazyLoad: true,
- compName: "ControlButton",
- compPath: "comps/meetingComp/controlButton",
+ comp: ControlButton,
withoutLoading: true,
layoutInfo: {
w: 3,
@@ -1189,9 +1226,7 @@ export var uiCompMap: Registry = {
categories: ["forms"],
icon: DropdownCompIcon,
keywords: trans("uiComp.dropdownCompKeywords"),
- lazyLoad: true,
- compName: "DropdownComp",
- compPath: "comps/buttonComp/dropdownComp",
+ comp: DropdownComp,
layoutInfo: {
w: 6,
h: 6,
@@ -1204,9 +1239,7 @@ export var uiCompMap: Registry = {
categories: ["forms"],
icon: ToggleButtonCompIcon,
keywords: trans("uiComp.toggleButtonCompKeywords"),
- lazyLoad: true,
- compName: "ToggleButtonComp",
- compPath: "comps/buttonComp/toggleButtonComp",
+ comp: ToggleButtonComp,
layoutInfo: {
w: 3,
h: 6,
@@ -1219,9 +1252,7 @@ export var uiCompMap: Registry = {
categories: ["forms"],
icon: SegmentedCompIcon,
keywords: trans("uiComp.segmentedControlCompKeywords"),
- lazyLoad: true,
- compName: "SegmentedControlComp",
- compPath: "comps/selectInputComp/segmentedControl",
+ comp: SegmentedControlComp,
layoutInfo: {
w: 6,
h: 6,
@@ -1235,9 +1266,7 @@ export var uiCompMap: Registry = {
categories: ["forms"],
icon: RatingCompIcon,
keywords: trans("uiComp.ratingCompKeywords"),
- lazyLoad: true,
- compName: "RatingComp",
- compPath: "comps/ratingComp",
+ comp: RatingComp,
layoutInfo: {
w: 6,
h: 6,
@@ -1331,9 +1360,7 @@ export var uiCompMap: Registry = {
categories: ["dashboards", "projectmanagement"],
icon: ProgressCompIcon,
keywords: trans("uiComp.progressCompKeywords"),
- lazyLoad: true,
- compName: "ProgressComp",
- compPath: "comps/progressComp",
+ comp: ProgressComp,
layoutInfo: {
w: 6,
h: 5,
@@ -1346,9 +1373,7 @@ export var uiCompMap: Registry = {
categories: ["dashboards", "projectmanagement"],
icon: ProcessCircleCompIcon,
keywords: trans("uiComp.progressCircleCompKeywords"),
- lazyLoad: true,
- compName: "ProgressCircleComp",
- compPath: "comps/progressCircleComp",
+ comp: ProgressCircleComp,
layoutInfo: {
w: 6,
h: 20,
@@ -1364,9 +1389,7 @@ export var uiCompMap: Registry = {
categories: ["documents"],
icon: UploadCompIcon,
keywords: trans("uiComp.fileUploadCompKeywords"),
- lazyLoad: true,
- compName: "FileComp",
- compPath: "comps/fileComp/fileComp",
+ comp: FileComp,
layoutInfo: {
w: 6,
h: 5,
@@ -1379,9 +1402,7 @@ export var uiCompMap: Registry = {
categories: ["documents"],
icon: FileViewerCompIcon,
keywords: trans("uiComp.fileViewerCompKeywords"),
- lazyLoad: true,
- compName: "FileViewerComp",
- compPath: "comps/fileViewerComp",
+ comp: FileViewerComp,
layoutInfo: {
w: 12,
h: 40,
@@ -1397,9 +1418,7 @@ export var uiCompMap: Registry = {
categories: ["multimedia"],
icon: ImageCompIcon,
keywords: trans("uiComp.imageCompKeywords"),
- lazyLoad: true,
- compName: "ImageComp",
- compPath: "comps/imageComp",
+ comp: ImageComp,
layoutInfo: {
w: 12,
h: 40,
@@ -1412,9 +1431,7 @@ export var uiCompMap: Registry = {
categories: ["multimedia"],
icon: CarouselCompIcon,
keywords: trans("uiComp.drawerCompKeywords"),
- lazyLoad: true,
- compName: "CarouselComp",
- compPath: "comps/carouselComp",
+ comp: CarouselComp,
withoutLoading: true,
layoutInfo: {
w: 12,
@@ -1428,9 +1445,7 @@ export var uiCompMap: Registry = {
categories: ["multimedia"],
icon: AudioCompIcon,
keywords: trans("uiComp.audioCompKeywords"),
- lazyLoad: true,
- compName: "AudioComp",
- compPath: "comps/mediaComp/audioComp",
+ comp: AudioComp,
layoutInfo: {
w: 6,
h: 5,
@@ -1443,9 +1458,7 @@ export var uiCompMap: Registry = {
categories: ["multimedia"],
icon: VideoCompIcon,
keywords: trans("uiComp.videoCompKeywords"),
- lazyLoad: true,
- compName: "VideoComp",
- compPath: "comps/mediaComp/videoComp",
+ comp: VideoComp,
layoutInfo: {
w: 12,
h: 40,
@@ -1459,9 +1472,7 @@ export var uiCompMap: Registry = {
categories: ["multimedia", "dashboards"],
icon: ShapesCompIcon,
keywords: trans("uiComp.shapeCompKeywords"),
- lazyLoad: true,
- compName: "ShapeComp",
- compPath: "comps/shapeComp/shapeComp",
+ comp: ShapeComp,
layoutInfo: {
w: 12,
h: 40,
@@ -1475,9 +1486,7 @@ export var uiCompMap: Registry = {
categories: ["multimedia"],
icon: LottieAnimationCompIcon,
keywords: trans("uiComp.jsonLottieCompKeywords"),
- lazyLoad: true,
- compName: "JsonLottieComp",
- compPath: "comps/jsonComp/jsonLottieComp",
+ comp: JsonLottieComp,
layoutInfo: {
w: 12,
h: 40,
@@ -1490,9 +1499,7 @@ export var uiCompMap: Registry = {
categories: ["multimedia"],
icon: IconCompIcon,
keywords: trans("uiComp.iconCompKeywords"),
- lazyLoad: true,
- compName: "IconComp",
- compPath: "comps/iconComp",
+ comp: IconComp,
layoutInfo: {
w: 2,
h: 10,
@@ -1520,9 +1527,7 @@ export var uiCompMap: Registry = {
categories: ["multimedia"],
icon: ColorPickerCompIcon,
keywords: trans("uiComp.colorPickerCompKeywords"),
- lazyLoad: true,
- compName: "ColorPickerComp",
- compPath: "comps/mediaComp/colorPickerComp",
+ comp: ColorPickerComp,
},
// item Handling
@@ -1534,9 +1539,7 @@ export var uiCompMap: Registry = {
categories: ["itemHandling", "documents"],
icon: QRCodeCompIcon,
keywords: trans("uiComp.qrCodeCompKeywords"),
- lazyLoad: true,
- compName: "QRCodeComp",
- compPath: "comps/qrCodeComp",
+ comp: QRCodeComp,
layoutInfo: {
w: 6,
h: 32,
@@ -1549,9 +1552,7 @@ export var uiCompMap: Registry = {
categories: ["itemHandling"],
icon: ScannerCompIcon,
keywords: trans("uiComp.scannerCompKeywords"),
- lazyLoad: true,
- compName: "ScannerComp",
- compPath: "comps/buttonComp/scannerComp",
+ comp: ScannerComp,
layoutInfo: {
w: 6,
h: 5,
@@ -1564,9 +1565,7 @@ export var uiCompMap: Registry = {
categories: ["itemHandling"],
icon: SignatureCompIcon,
keywords: trans("uiComp.signatureCompKeywords"),
- lazyLoad: true,
- compName: "SignatureComp",
- compPath: "comps/signatureComp",
+ comp: SignatureComp,
layoutInfo: {
w: 12,
h: 40,
@@ -1592,9 +1591,7 @@ export var uiCompMap: Registry = {
categories: ["multimedia", "itemHandling"],
icon: TourCompIcon,
keywords: trans("uiComp.tourCompKeywords"),
- lazyLoad: true,
- compName: "TourComp",
- compPath: "comps/tourComp/tourComp",
+ comp: TourComp,
layoutInfo: {
w: 1,
h: 1,
@@ -1607,9 +1604,7 @@ export var uiCompMap: Registry = {
categories: ["forms", "itemHandling"],
icon: MultiSelectCompIcon,
keywords: trans("uiComp.multiSelectCompKeywords"),
- lazyLoad: true,
- compName: "MultiSelectComp",
- compPath: "comps/selectInputComp/multiSelectComp",
+ comp: MultiSelectComp,
layoutInfo: {
w: 6,
h: 5,
@@ -1622,9 +1617,7 @@ export var uiCompMap: Registry = {
categories: ["layout", "itemHandling", "documents"],
icon: TreeDisplayCompIcon,
keywords: trans("uiComp.treeCompKeywords"),
- lazyLoad: true,
- compName: "TreeComp",
- compPath: "comps/treeComp/treeComp",
+ comp: TreeComp,
layoutInfo: {
w: 12,
h: 40,
@@ -1637,9 +1630,7 @@ export var uiCompMap: Registry = {
categories: ["layout", "itemHandling", "documents"],
icon: TreeSelectCompIcon,
keywords: trans("uiComp.treeSelectCompKeywords"),
- lazyLoad: true,
- compName: "TreeSelectComp",
- compPath: "comps/treeComp/treeSelectComp",
+ comp: TreeSelectComp,
layoutInfo: {
w: 12,
h: 5,
@@ -1652,9 +1643,7 @@ export var uiCompMap: Registry = {
description: trans("uiComp.transferDesc"),
categories: ["itemHandling", "documents"],
keywords: trans("uiComp.transferKeywords"),
- lazyLoad: true,
- compName: "transferComp",
- compPath: "comps/transferComp",
+ comp: transferComp,
layoutInfo: {
w: 12,
h: 50,
@@ -1689,9 +1678,7 @@ export var uiCompMap: Registry = {
icon: IFrameCompIcon,
categories: ["integration"],
keywords: trans("uiComp.iframeCompKeywords"),
- lazyLoad: true,
- compName: "IFrameComp",
- compPath: "comps/iframeComp",
+ comp: IFrameComp,
layoutInfo: {
w: 12,
h: 40,
@@ -1704,9 +1691,7 @@ export var uiCompMap: Registry = {
icon: CustomCompIcon,
categories: ["integration"],
keywords: trans("uiComp.customCompKeywords"),
- lazyLoad: true,
- compName: "CustomComp",
- compPath: "comps/customComp/customComp",
+ comp: CustomComp,
layoutInfo: {
w: 12,
h: 40,
diff --git a/client/packages/lowcoder/src/comps/queries/httpQuery/graphqlQuery.tsx b/client/packages/lowcoder/src/comps/queries/httpQuery/graphqlQuery.tsx
index aca0e742b..2ccba0539 100644
--- a/client/packages/lowcoder/src/comps/queries/httpQuery/graphqlQuery.tsx
+++ b/client/packages/lowcoder/src/comps/queries/httpQuery/graphqlQuery.tsx
@@ -15,6 +15,7 @@ import {
HttpParametersPropertyView,
HttpPathPropertyView,
} from "./httpQueryConstants";
+import { SimpleNameComp } from "@lowcoder-ee/comps/comps/simpleNameComp";
interface VariablesControlParams {
// variables: string[]; todo support parse variables
diff --git a/client/packages/lowcoder/src/comps/queries/queryComp.tsx b/client/packages/lowcoder/src/comps/queries/queryComp.tsx
index 066b351fe..c8ac3032e 100644
--- a/client/packages/lowcoder/src/comps/queries/queryComp.tsx
+++ b/client/packages/lowcoder/src/comps/queries/queryComp.tsx
@@ -37,6 +37,7 @@ import {
FetchCheckNode,
FetchInfo,
fromRecord,
+ fromValue,
isCustomAction,
MultiBaseComp,
multiChangeAction,
@@ -67,7 +68,7 @@ import { JSONObject, JSONValue } from "../../util/jsonTypes";
import { BoolPureControl } from "../controls/boolControl";
import { millisecondsControl } from "../controls/millisecondControl";
import { paramsMillisecondsControl } from "../controls/paramsControl";
-import { DepsConfig, NameConfig, withExposingConfigs } from "../generators/withExposing";
+import { NameConfig, withExposingConfigs } from "../generators/withExposing";
import { HttpQuery } from "./httpQuery/httpQuery";
import { StreamQuery } from "./httpQuery/streamQuery";
import { QueryConfirmationModal } from "./queryComp/queryConfirmationModal";
@@ -76,6 +77,7 @@ import { QueryPropertyView } from "./queryComp/queryPropertyView";
import { getTriggerType, onlyManualTrigger } from "./queryCompUtils";
import { messageInstance } from "lowcoder-design/src/components/GlobalInstances";
import {VariablesComp} from "@lowcoder-ee/comps/queries/queryComp/variablesComp";
+import { migrateOldData } from "../generators/simpleGenerators";
const latestExecution: Record = {};
@@ -257,7 +259,11 @@ QueryCompTmp = class extends QueryCompTmp {
|| isInputChangeTrigger
|| (isPageLoadTrigger && notExecuted)
)
- // && (!isJsQuery || (isJsQuery && notExecuted)) // query which has deps can be executed on page load(first time)
+ && (
+ !isJsQuery
+ || (isJsQuery && !isAutomatic)
+ || (isJsQuery && isAutomatic && notExecuted)
+ ) // query which has deps can be executed on page load(first time)
) {
const next = super.reduce(action);
const depends = this.children.comp.node()?.dependValues();
@@ -363,7 +369,7 @@ QueryCompTmp = class extends QueryCompTmp {
}
if (action.type === CompActionTypes.EXECUTE_QUERY) {
if (getReduceContext().disableUpdateState) return this;
- if(!action.args) action.args = this.children.variables.children.variables.toJsonValue().reduce((acc, curr) => Object.assign(acc, {[curr.key as string]:curr.value}), {});
+ if(!action.args) action.args = this.children.variables.toJsonValue().filter(kv => kv.key).reduce((acc, curr) => Object.assign(acc, {[curr.key as string]:curr.value}), {});
action.args.$queryName = this.children.name.getView();
return this.executeQuery(action);
@@ -655,6 +661,13 @@ QueryCompTmp = withMethodExposing(QueryCompTmp, [
},
]);
+QueryCompTmp = migrateOldData(QueryCompTmp, (oldData: any) => {
+ if (oldData?.variables?.variables) {
+ oldData.variables = oldData.variables.variables;
+ }
+ return oldData;
+});
+
export const QueryComp = withExposingConfigs(QueryCompTmp, [
new NameConfig("data", trans("query.dataExportDesc")),
new NameConfig("code", trans("query.codeExportDesc")),
@@ -664,23 +677,6 @@ export const QueryComp = withExposingConfigs(QueryCompTmp, [
new NameConfig("isFetching", trans("query.isFetchingExportDesc")),
new NameConfig("runTime", trans("query.runTimeExportDesc")),
new NameConfig("latestEndTime", trans("query.latestEndTimeExportDesc")),
- new DepsConfig(
- "variables",
- (children: any) => {
- return {data: children.variables.children.variables.node()};
- },
- (input) => {
- if (!input.data) {
- return undefined;
- }
- const newNode = Object.values(input.data)
- .filter((kvNode: any) => kvNode.key)
- .map((kvNode: any) => ({[kvNode.key]: kvNode.value}))
- .reduce((prev, obj) => ({...prev, ...obj}), {});
- return newNode;
- },
- trans("query.variables")
- ),
new NameConfig("triggerType", trans("query.triggerTypeExportDesc")),
]);
@@ -718,7 +714,22 @@ class QueryListComp extends QueryListTmpComp implements BottomResListComp {
const result: NameAndExposingInfo = {};
Object.values(this.children).forEach((comp) => {
result[comp.children.name.getView()] = comp.exposingInfo();
+
+ const variables = comp.children.variables.toJsonValue();
+ variables.forEach((variable: Record) => {
+ result[variable.key] = {
+ property: fromRecord({
+ value: fromValue(variable.value),
+ }),
+ propertyValue: {
+ value: variable.value,
+ },
+ propertyDesc: {},
+ methods: {},
+ };
+ })
});
+
return result;
}
@@ -777,13 +788,15 @@ class QueryListComp extends QueryListTmpComp implements BottomResListComp {
const jsonData = originQuery.toJsonValue();
//Regenerate variable header
- jsonData.variables?.variables?.forEach(kv => {
+ const newKeys:string[] = [];
+ jsonData.variables?.forEach(kv => {
const [prefix, _] = (kv.key as string).split(/(?=\d+$)/);
let i=1, newName = "";
do {
newName = prefix + (i++);
- } while(editorState.checkRename("", newName));
+ } while(editorState.checkRename("", newName) || newKeys.includes(newName));
kv.key = newName;
+ newKeys.push(newName);
})
const newQueryName = this.genNewName(editorState);
diff --git a/client/packages/lowcoder/src/comps/queries/queryComp/queryPropertyView.tsx b/client/packages/lowcoder/src/comps/queries/queryComp/queryPropertyView.tsx
index 3a818f72e..a6d56e430 100644
--- a/client/packages/lowcoder/src/comps/queries/queryComp/queryPropertyView.tsx
+++ b/client/packages/lowcoder/src/comps/queries/queryComp/queryPropertyView.tsx
@@ -177,7 +177,7 @@ export function QueryPropertyView(props: { comp: InstanceType
children: (
- {children.variables.getPropertyView()}
+ {children.variables.propertyView({})}
),
diff --git a/client/packages/lowcoder/src/comps/queries/queryComp/variablesComp.tsx b/client/packages/lowcoder/src/comps/queries/queryComp/variablesComp.tsx
index ec271e28f..337a2df61 100644
--- a/client/packages/lowcoder/src/comps/queries/queryComp/variablesComp.tsx
+++ b/client/packages/lowcoder/src/comps/queries/queryComp/variablesComp.tsx
@@ -1,15 +1,110 @@
-import {MultiCompBuilder, withDefault} from "../../generators";
-import { keyValueListControl } from "../../controls/keyValueListControl";
-
-export const VariablesComp = new MultiCompBuilder(
- {
- variables: withDefault(keyValueListControl(false, [], "variable"), [{ key: "", value: "" }]),
- },
- (props) => props //props.variables
- )
- .setPropertyViewFn((children) => (
+import { simpleMultiComp } from "../../generators";
+import { SimpleNameComp } from "@lowcoder-ee/comps/comps/simpleNameComp";
+import { StringControl } from "@lowcoder-ee/comps/controls/codeControl";
+import { list } from "@lowcoder-ee/comps/generators/list";
+import { Input } from "components/Input";
+import { ControlPropertyViewWrapper } from "components/control";
+import { ReactNode, useContext, useState } from "react";
+import { KeyValueList } from "components/keyValueList";
+import { trans } from "i18n";
+import { PopupCard } from "components/popupCard";
+import { EditorContext, EditorState } from "@lowcoder-ee/comps/editorState";
+import { migrateOldData } from "@lowcoder-ee/comps/generators/simpleGenerators";
+
+interface VariablesParams {
+ // variables: string[]; todo support parse variables
+}
+
+const VariableKey = ({children, dispatch}: any) => {
+ const [editing, setEditing] = useState(false);
+ const [error, setError] = useState(undefined);
+ const editorState = useContext(EditorContext);
+
+ return (
<>
- {children.variables.propertyView({})}
+
+
{
+ const { value } = e.target;
+ value !== children.key.getView() &&
+ editorState.rename(children.key.getView(), value)
+ }}
+ onPressEnter={(e) => {
+ const { value } = e.target as HTMLInputElement;
+ value !== children.key.getView() &&
+ editorState.rename(children.key.getView(), value)
+ }}
+ onChange={(e) => {
+ const nextName = e.target.value;
+ setError(editorState.checkRename(children.key.getView(), nextName));
+ }}
+ />
+
+
>
- ))
- .build();
+ )
+}
+const VariableItem = class extends simpleMultiComp({
+ key: SimpleNameComp,
+ value: StringControl,
+}) {
+ propertyView(params: VariablesParams): ReactNode {
+ return (
+ <>
+
+
+
+ {this.children.value.propertyView({ placeholder: "value" })}
+
+
+ >
+ )
+ }
+}
+
+const VariableListPropertyViewWrapper = ({children}: any) => {
+ const editorState = useContext(EditorContext);
+ return children(editorState);
+}
+
+export const VariablesComp = class extends list(VariableItem) {
+ genNewName(editorState: EditorState) {
+ const name = editorState.getNameGenerator().genItemName("variable");
+ return name;
+ }
+
+ add(editorState: EditorState, extraInfo?: any) {
+ const name = this.genNewName(editorState);
+
+ this.dispatch(
+ this.pushAction({
+ key: name,
+ value: '',
+ })
+ );
+ }
+ propertyView(params: VariablesParams): ReactNode {
+ return (
+
+ {(editorState: EditorState) => (
+
+ child.propertyView(params))}
+ onAdd={() => this.add(editorState)}
+ onDelete={(item, index) => this.dispatch(this.deleteAction(index))}
+ />
+
+ )}
+
+ );
+ }
+};
diff --git a/client/packages/lowcoder/src/comps/queries/queryCompUtils.tsx b/client/packages/lowcoder/src/comps/queries/queryCompUtils.tsx
index d319689e7..bb518fcad 100644
--- a/client/packages/lowcoder/src/comps/queries/queryCompUtils.tsx
+++ b/client/packages/lowcoder/src/comps/queries/queryCompUtils.tsx
@@ -28,10 +28,22 @@ export function toQueryView(params: FunctionProperty[]) {
variables?: any;
timeout: InstanceType;
}): Promise => {
- console.log("toQueryView props", props, params);
const { applicationId, isViewMode } = getGlobalSettings();
- const mappedVariables = Object.keys(props.variables).map(key => ({key: `${props.args?.$queryName}.variables.${key}`, value: props.variables[key]}));
+ let mappedVariables: Array<{key: string, value: string}> = [];
+ Object.keys(props.variables)
+ .filter(k => k !== "$queryName")
+ .forEach(key => {
+ mappedVariables.push({
+ key: `${key}.value`,
+ value: props.variables[key] || ""
+ })
+ mappedVariables.push({
+ key: `${props.args?.$queryName}.variables.${key}`,
+ value: props.variables[key] || ""
+ })
+ })
+
let request: QueryExecuteRequest = {
path: props.applicationPath,
params: [
diff --git a/client/packages/lowcoder/src/comps/uiCompRegistry.ts b/client/packages/lowcoder/src/comps/uiCompRegistry.ts
index fb766807a..4c320de47 100644
--- a/client/packages/lowcoder/src/comps/uiCompRegistry.ts
+++ b/client/packages/lowcoder/src/comps/uiCompRegistry.ts
@@ -33,6 +33,7 @@ export const uiCompCategoryNames = {
itemHandling: trans("uiCompCategory.itemHandling"),
multimedia: trans("uiCompCategory.multimedia"),
integration: trans("uiCompCategory.integration"),
+ legacy: trans("uiCompCategory.legacy"),
};
export type UICompCategory = keyof typeof uiCompCategoryNames;
@@ -149,6 +150,10 @@ export type UICompType =
| "responsiveLayout"
| "splitLayout"
| "tour"
+ | "barChart"
+ | "lineChart"
+ | "pieChart"
+ | "scatterChart"
| "funnelChart"
| "gaugeChart"
| "sankeyChart"
diff --git a/client/packages/lowcoder/src/comps/utils/useCompInstance.tsx b/client/packages/lowcoder/src/comps/utils/useCompInstance.tsx
index 812ae7389..c15e7c0db 100644
--- a/client/packages/lowcoder/src/comps/utils/useCompInstance.tsx
+++ b/client/packages/lowcoder/src/comps/utils/useCompInstance.tsx
@@ -304,11 +304,11 @@ export function useCompInstance(
let updateHandler = () => setComp(container.comp);
- if (UPDATE_ROOT_VIEW_DEBOUNCE > 0) {
+ // if (UPDATE_ROOT_VIEW_DEBOUNCE > 0) {
updateHandler = debounce(() => {
setComp(container.comp);
- }, UPDATE_ROOT_VIEW_DEBOUNCE);
- }
+ }, 50 /* UPDATE_ROOT_VIEW_DEBOUNCE */);
+ // }
const finalHandlers = [...(handlers || []), updateHandler];
finalHandlers.forEach((handler) => container.addChangeListener(handler));
diff --git a/client/packages/lowcoder/src/i18n/locales/de.ts b/client/packages/lowcoder/src/i18n/locales/de.ts
index d6f234f61..33c894090 100644
--- a/client/packages/lowcoder/src/i18n/locales/de.ts
+++ b/client/packages/lowcoder/src/i18n/locales/de.ts
@@ -989,6 +989,7 @@ export const de = {
"itemHandling": "Handhabung von Inventar",
"multimedia": "Multimedia und Animation",
"integration": "Integration & Erweiterung",
+ "legacy" : "Älter & Auslaufend"
},
"uiComp": {
...en.uiComp,
diff --git a/client/packages/lowcoder/src/i18n/locales/en.ts b/client/packages/lowcoder/src/i18n/locales/en.ts
index 48d4cbdc4..735b797d4 100644
--- a/client/packages/lowcoder/src/i18n/locales/en.ts
+++ b/client/packages/lowcoder/src/i18n/locales/en.ts
@@ -979,7 +979,8 @@ export const en = {
"documents": "Document & File Management",
"itemHandling": "Item & Signature Handling",
"multimedia": "Multimedia & Animation",
- "integration": "Integration & Extension"
+ "integration": "Integration & Extension",
+ "legacy" : "Legacy & Deprecated"
},
"uiComp": {
"autoCompleteCompName": "Auto Complete",
@@ -1210,7 +1211,7 @@ export const en = {
"drawerCompDesc": "A sliding panel component that can be used for additional navigation or content display, typically emerging from the edge of the screen.",
"drawerCompKeywords": "drawer, sliding, panel, navigation",
- "chartCompName": "Chart",
+ "chartCompName": "Chart (deprecated)",
"chartCompDesc": "A versatile component for visualizing data through various types of charts and graphs.",
"chartCompKeywords": "chart, graph, data, visualization",
@@ -1334,7 +1335,7 @@ export const en = {
"themeriverChartCompDesc": "A visualization resembling a stream graph that shows changes in a data set over time across categories.",
"themeriverChartCompKeywords": "theme river, time series, trends",
- "basicChartCompName": "Basic Chart",
+ "basicChartCompName": "Multitype Chart",
"basicChartCompDesc": "A versatile component for visualizing data through various types of charts and graphs.",
"basicChartCompKeywords": "chart, graph, data, visualization",
@@ -1350,6 +1351,22 @@ export const en = {
"kanbanCompDesc" : "A board for visualizing workflow, with columns representing stages of work and cards representing tasks.",
"kanbanCompKeywords" : "kanban, board, workflow, tasks",
+ "pieChartCompName": "Pie Chart",
+ "pieChartCompDesc": "A versatile component for visualizing data with Pie Charts.",
+ "pieChartCompKeywords": "chart, data, visualization",
+
+ "lineChartCompName": "Line Chart",
+ "lineChartCompDesc": "A versatile component for visualizing data with Line Charts.",
+ "lineChartCompKeywords": "chart, data, visualization",
+
+ "barChartCompName": "Bar Chart",
+ "barChartCompDesc": "A versatile component for visualizing data with Bar Charts.",
+ "barChartCompKeywords": "chart, data, visualization",
+
+ "scatterChartCompName": "Scatter Chart",
+ "scatterChartCompDesc": "A versatile component for visualizing data with Scatter Charts.",
+ "scatterChartCompKeywords": "chart, data, visualization",
+
// by mousheng
"colorPickerCompName": "Color Picker",
@@ -2029,6 +2046,7 @@ export const en = {
"tag": "Tag",
"select": "Select",
"dropdown": "Dropdown",
+ "time" : "Time",
"date": "Date",
"dateTime": "Date Time",
"badgeStatus": "Status",
@@ -2629,6 +2647,7 @@ export const en = {
"copyToClipboard": "Copy to Clipboard",
"downloadFile": "Download File",
"logoutUser" : "Logout User",
+ "resetPassword" : "Reset Password",
},
"messageComp": {
"info": "Send a Notification",
@@ -3376,6 +3395,7 @@ export const en = {
},
"support" : {
+ "selfUser" : "You",
"supportTitle": "Lowcoder Support",
"supportContent": "If you have any questions or need help, please use the ticket system get your issue solved fast.",
"newSupportTicket": "New Support Ticket",
diff --git a/client/packages/lowcoder/src/index.sdk.ts b/client/packages/lowcoder/src/index.sdk.ts
index db8d14daa..b51d016e3 100644
--- a/client/packages/lowcoder/src/index.sdk.ts
+++ b/client/packages/lowcoder/src/index.sdk.ts
@@ -105,6 +105,7 @@ export * from "comps/controls/stringSimpleControl";
export * from "comps/controls/styleControl";
export * from "comps/controls/styleControlConstants";
export * from "comps/controls/slotControl";
+export * from "comps/controls/sliderControl";
// generators
export * from "comps/generators/changeDataType";
diff --git a/client/packages/lowcoder/src/layout/calculateUtils.tsx b/client/packages/lowcoder/src/layout/calculateUtils.tsx
index 1d919bd1b..44a661e00 100644
--- a/client/packages/lowcoder/src/layout/calculateUtils.tsx
+++ b/client/packages/lowcoder/src/layout/calculateUtils.tsx
@@ -93,7 +93,6 @@ export function calcGridItemSizePx(
const width = calcGridItemWHPx(w, colWidth, margin[0], false);
const isTouchSBound = top ? isTouchBound(maxRows, rowHeight, h, top) : false;
- // console.log('positionParams',positionParams);
const height = calcGridItemWHPx(h, rowHeight, margin[1], isTouchSBound);
return { width, height };
}
diff --git a/client/packages/lowcoder/src/layout/compSelectionWrapper.tsx b/client/packages/lowcoder/src/layout/compSelectionWrapper.tsx
index 4b347907e..d9eb475d4 100644
--- a/client/packages/lowcoder/src/layout/compSelectionWrapper.tsx
+++ b/client/packages/lowcoder/src/layout/compSelectionWrapper.tsx
@@ -11,6 +11,7 @@ import React, {
MouseEventHandler,
useCallback,
useContext,
+ useMemo,
useRef,
useState,
} from "react";
@@ -18,7 +19,8 @@ import ReactResizeDetector, { useResizeDetector } from "react-resize-detector";
import styled, { css } from "styled-components";
import { EllipsisTextCss } from "lowcoder-design";
import { draggingUtils } from "./draggingUtils";
-import { ResizeHandleAxis } from "./gridLayoutPropTypes";
+import type { ResizeHandleAxis } from "./gridLayoutPropTypes";
+import { isEqual } from "lodash";
export type DragHandleName = "w" | "e" | "nw" | "ne" | "sw" | "se";
type NamePos = "top" | "bottom" | "bottomInside";
@@ -273,7 +275,7 @@ export const CompSelectionWrapper = React.memo((props: {
}
setHover(true);
},
- [setHover]
+ [nameDivRef.current, setHover]
);
const onMouseOut = useCallback(
(e: MouseEvent) => {
@@ -287,42 +289,61 @@ export const CompSelectionWrapper = React.memo((props: {
}
setHover(false);
},
- [setHover]
+ [nameDivRef.current, setHover]
);
- const selectableDivProps = props.isSelectable
- ? {
- onMouseOver,
- onMouseOut,
- onClick: props.onClick,
- $hover: hover || undefined,
- $showDashLine: editorState.showGridLines() || props.hidden,
- $isSelected: props.isSelected,
- $isHidden: props.hidden,
- }
- : {
- $hover: undefined,
- $showDashLine: false,
- $isSelected: false,
- $isHidden: false,
- };
+ const selectableDivProps = useMemo(() => {
+ return props.isSelectable
+ ? {
+ onMouseOver,
+ onMouseOut,
+ onClick: props.onClick,
+ $hover: hover || undefined,
+ $showDashLine: editorState.showGridLines() || props.hidden,
+ $isSelected: props.isSelected,
+ $isHidden: props.hidden,
+ }
+ : {
+ $hover: undefined,
+ $showDashLine: false,
+ $isSelected: false,
+ $isHidden: false,
+ };
+ }, [
+ hover,
+ props.hidden,
+ props.isSelected,
+ props.isSelectable,
+ ]);
+
+ const zIndex = useMemo(() => {
+ return props.isSelected
+ ? Layers.compSelected
+ : hover
+ ? Layers.compHover
+ : props.hidden
+ ? Layers.compHidden
+ : undefined;
+ }, [
+ hover,
+ props.hidden,
+ props.isSelected
+ ]);
- const zIndex = props.isSelected
- ? Layers.compSelected
- : hover
- ? Layers.compHover
- : props.hidden
- ? Layers.compHidden
- : undefined;
+ const needResizeDetector = useMemo(() => {
+ return props.autoHeight && !props.placeholder;
+ }, [props.autoHeight, props.placeholder]);
- const needResizeDetector = props.autoHeight && !props.placeholder;
const { ref: wrapperRef } = useResizeDetector({
onResize: props.onWrapperResize,
handleHeight: needResizeDetector,
handleWidth: false,
+ refreshMode: 'debounce',
+ refreshRate: 100,
});
// log.debug("CompSelectionWrapper. name: ", props.name, " zIndex: ", zIndex);
const { nameConfig, resizeIconSize } = props;
+
return (
@@ -380,4 +411,4 @@ export const CompSelectionWrapper = React.memo((props: {
);
-});
+}, (prev, next) => isEqual(prev, next));
diff --git a/client/packages/lowcoder/src/layout/gridItem.tsx b/client/packages/lowcoder/src/layout/gridItem.tsx
index 963c1c056..3594f3acd 100644
--- a/client/packages/lowcoder/src/layout/gridItem.tsx
+++ b/client/packages/lowcoder/src/layout/gridItem.tsx
@@ -113,8 +113,8 @@ export const GridItem = React.memo((props: GridItemProps) => {
maxRows: props.maxRows,
}, props.x, props.y, props.w, props.h)},
[
- props.margin,
- props.containerPadding,
+ JSON.stringify(props.margin),
+ JSON.stringify(props.containerPadding),
props.containerWidth,
props.cols,
props.rowHeight,
@@ -123,7 +123,6 @@ export const GridItem = React.memo((props: GridItemProps) => {
props.y,
props.w,
props.h,
- calcGridItemPosition,
]
);
@@ -230,8 +229,8 @@ export const GridItem = React.memo((props: GridItemProps) => {
y: yy,
});
}, [
- resizing,
- dragging,
+ JSON.stringify(resizing),
+ JSON.stringify(dragging),
props.cols,
props.maxRows,
props.x,
@@ -417,7 +416,7 @@ export const GridItem = React.memo((props: GridItemProps) => {
itemHeightRef.current = height;
}
adjustWrapperHeight(width, height);
- }, [itemHeightRef, adjustWrapperHeight]);
+ }, [itemHeightRef.current, adjustWrapperHeight]);
/**
* re-calculate the occupied gird-cells.
@@ -427,7 +426,7 @@ export const GridItem = React.memo((props: GridItemProps) => {
*/
const onWrapperSizeChange = useCallback(() => {
adjustWrapperHeight(undefined, itemHeightRef.current);
- }, [itemHeightRef, adjustWrapperHeight]);
+ }, [itemHeightRef.current, adjustWrapperHeight]);
const mixinChildWrapper = useCallback((child: React.ReactElement): React.ReactElement => {
const {
@@ -535,6 +534,21 @@ export const GridItem = React.memo((props: GridItemProps) => {
const pos = useMemo(calcPosition, [calcPosition]);
+ const transform = useMemo(() => {
+ return setTransform(
+ pos,
+ props.name,
+ props.autoHeight,
+ props.hidden,
+ Boolean(draggingUtils.isDragging())
+ )
+ }, [
+ JSON.stringify(pos),
+ props.name,
+ props.autoHeight,
+ props.hidden
+ ]);
+
const render = useMemo(() => {
let child = React.Children.only(children);
// Create the child element. We clone the existing element but modify its className and style.
@@ -563,13 +577,7 @@ export const GridItem = React.memo((props: GridItemProps) => {
cssTransforms: true,
}),
style: {
- ...setTransform(
- pos,
- props.name,
- props.autoHeight,
- props.hidden,
- Boolean(draggingUtils.isDragging())
- ),
+ ...transform,
opacity: layoutHide ? 0 : undefined,
pointerEvents: layoutHide ? "none" : "auto",
},
@@ -580,11 +588,12 @@ export const GridItem = React.memo((props: GridItemProps) => {
newChild = mixinDraggable(newChild, isDraggable);
return newChild;
}, [
- pos,
+ JSON.stringify(transform),
+ JSON.stringify(pos),
children,
elementRef,
- resizing,
- dragging,
+ Boolean(resizing),
+ Boolean(dragging),
isDraggable,
layoutHide,
zIndex,
@@ -593,8 +602,6 @@ export const GridItem = React.memo((props: GridItemProps) => {
props.className,
props.style,
props.static,
- props.autoHeight,
- props.hidden,
setTransform,
mixinChildWrapper,
mixinResizable,
diff --git a/client/packages/lowcoder/src/layout/gridLayout.tsx b/client/packages/lowcoder/src/layout/gridLayout.tsx
index 0b88786c2..0b25763b7 100644
--- a/client/packages/lowcoder/src/layout/gridLayout.tsx
+++ b/client/packages/lowcoder/src/layout/gridLayout.tsx
@@ -1,8 +1,8 @@
import clsx from "clsx";
import { colord } from "colord";
-import { UICompType } from "comps/uiCompRegistry";
+import type { UICompType } from "comps/uiCompRegistry";
import { ModulePrimaryColor, PrimaryColor } from "constants/style";
-import _ from "lodash";
+import _, { isEqual } from "lodash";
import log from "loglevel";
import React, { DragEvent, DragEventHandler, MouseEventHandler, ReactElement } from "react";
import ReactResizeDetector from "react-resize-detector";
@@ -21,7 +21,7 @@ import {
import { draggingUtils } from "./draggingUtils";
import { FlyOverInfo, FlyStartInfo } from "./flyInfo";
import { GridItem } from "./gridItem";
-import { GridLayoutProps } from "./gridLayoutPropTypes";
+import type { GridLayoutProps } from "./gridLayoutPropTypes";
import { GridLines } from "./gridLines";
import { changeItemOp, deleteItemOp, LayoutOp, renameItemOp } from "./layoutOp";
import { getUILayout, LayoutOps, layoutOpUtils } from "./layoutOpUtils";
@@ -1102,7 +1102,7 @@ const LayoutContainer = styled.div<{
}`}
`;
-export const ReactGridLayout = React.memo(GridLayout);
+export const ReactGridLayout = React.memo(GridLayout, (prev, next) => isEqual(prev, next));
function moveOrResize(
e: React.KeyboardEvent,
diff --git a/client/packages/lowcoder/src/layout/gridLines.tsx b/client/packages/lowcoder/src/layout/gridLines.tsx
index c7cfc1366..33b5eefec 100644
--- a/client/packages/lowcoder/src/layout/gridLines.tsx
+++ b/client/packages/lowcoder/src/layout/gridLines.tsx
@@ -1,6 +1,7 @@
import { CSSProperties } from "react";
import { calcGridColWidth, PositionParams } from "./calculateUtils";
import { Position, setTransform } from "./utils";
+import React from "react";
interface GridLineProps {
position: Position;
@@ -19,10 +20,10 @@ function setBackgroundProps(positionParams: PositionParams, lineColor: string):
};
}
-export function GridLines(props: GridLineProps) {
+export const GridLines = React.memo((props: GridLineProps) => {
const style = {
...setTransform(props.position),
...setBackgroundProps(props.positionParams, props.lineColor),
};
return
;
-}
+})
diff --git a/client/packages/lowcoder/src/pages/ApplicationV2/components/CreateApiKeyModal.tsx b/client/packages/lowcoder/src/pages/ApplicationV2/components/CreateApiKeyModal.tsx
index 0a174c0c5..4a2d48508 100644
--- a/client/packages/lowcoder/src/pages/ApplicationV2/components/CreateApiKeyModal.tsx
+++ b/client/packages/lowcoder/src/pages/ApplicationV2/components/CreateApiKeyModal.tsx
@@ -134,6 +134,8 @@ function CreateApiKeyModal(props: CreateApiKeyModalProps) {
width="500px"
title={"Create API Key"}
open={modalVisible}
+ showOkButton
+ showCancelButton
okText={"Save"}
okButtonProps={{
loading: saveLoading
diff --git a/client/packages/lowcoder/src/pages/ApplicationV2/index.tsx b/client/packages/lowcoder/src/pages/ApplicationV2/index.tsx
index ccbdf1a78..71c13d039 100644
--- a/client/packages/lowcoder/src/pages/ApplicationV2/index.tsx
+++ b/client/packages/lowcoder/src/pages/ApplicationV2/index.tsx
@@ -10,6 +10,7 @@ import {
TRASH_URL,
NEWS_URL,
ORG_HOME_URL,
+ SUBSCRIPTION_SETTING,
} from "constants/routesURL";
import { getUser, isFetchingUser } from "redux/selectors/usersSelectors";
import { useDispatch, useSelector } from "react-redux";
@@ -57,6 +58,7 @@ import { trans } from "../../i18n";
import { foldersSelector } from "../../redux/selectors/folderSelector";
import Setting from "pages/setting";
import { Support } from "pages/support";
+import { Subscription } from "pages/setting/subscriptions"
// import { TypographyText } from "../../components/TypographyText";
// import { messageInstance } from "lowcoder-design/src/components/GlobalInstances";
import { isEE } from "util/envUtils";
@@ -248,6 +250,19 @@ export default function ApplicationHome() {
],
} : { items: [] },
+ !supportSubscription && user.orgDev ? {
+ items: [
+ {
+ text: {trans("home.support")} ,
+ routePath: SUBSCRIPTION_SETTING,
+ routeComp: Subscription,
+ routePathExact: false,
+ icon: ({ selected, ...otherProps }) => selected ? : ,
+ mobileVisible: true,
+ },
+ ],
+ } : { items: [] },
+
supportSubscription && user.orgDev ? {
items: [
{
diff --git a/client/packages/lowcoder/src/pages/ComponentDoc/examples/ButtonComp/Button.tsx b/client/packages/lowcoder/src/pages/ComponentDoc/examples/ButtonComp/Button.tsx
index 115ea9122..a68074d32 100644
--- a/client/packages/lowcoder/src/pages/ComponentDoc/examples/ButtonComp/Button.tsx
+++ b/client/packages/lowcoder/src/pages/ComponentDoc/examples/ButtonComp/Button.tsx
@@ -28,6 +28,24 @@ export default function ButtonExample() {
config={{ type: "default", text: trans("componentDoc.submit"), disabled: true }}
compFactory={ButtonComp}
/>
+
+
+
@@ -55,6 +73,28 @@ export default function ButtonExample() {
}}
compFactory={ButtonComp}
/>
+
>
);
diff --git a/client/packages/lowcoder/src/pages/ComponentDoc/examples/ButtonComp/DropDownButton.tsx b/client/packages/lowcoder/src/pages/ComponentDoc/examples/ButtonComp/DropDownButton.tsx
index 57bb20afe..2986d3336 100644
--- a/client/packages/lowcoder/src/pages/ComponentDoc/examples/ButtonComp/DropDownButton.tsx
+++ b/client/packages/lowcoder/src/pages/ComponentDoc/examples/ButtonComp/DropDownButton.tsx
@@ -32,9 +32,11 @@ export default function DropdownExample() {
};
return (
<>
+
+
-
+
+
+
+
+
+
+
+
+
+
diff --git a/client/packages/lowcoder/src/pages/ComponentDoc/examples/ButtonComp/FloatButton.tsx b/client/packages/lowcoder/src/pages/ComponentDoc/examples/ButtonComp/FloatButton.tsx
index 252e3d782..df7351b7a 100644
--- a/client/packages/lowcoder/src/pages/ComponentDoc/examples/ButtonComp/FloatButton.tsx
+++ b/client/packages/lowcoder/src/pages/ComponentDoc/examples/ButtonComp/FloatButton.tsx
@@ -31,6 +31,7 @@ export default function FloatButtonExample() {
>
+
+
+
+
+
+
+
+
+
+
+
+
+
>
diff --git a/client/packages/lowcoder/src/pages/ComponentDoc/examples/ButtonComp/IconButton.tsx b/client/packages/lowcoder/src/pages/ComponentDoc/examples/ButtonComp/IconButton.tsx
index 67a3fad0d..e5eb0784f 100644
--- a/client/packages/lowcoder/src/pages/ComponentDoc/examples/ButtonComp/IconButton.tsx
+++ b/client/packages/lowcoder/src/pages/ComponentDoc/examples/ButtonComp/IconButton.tsx
@@ -90,6 +90,7 @@ export default function IconButtonExample() {
+
>
);
diff --git a/client/packages/lowcoder/src/pages/ComponentDoc/examples/ButtonComp/ToggleButton.tsx b/client/packages/lowcoder/src/pages/ComponentDoc/examples/ButtonComp/ToggleButton.tsx
index e9e65cf74..00fef73f9 100644
--- a/client/packages/lowcoder/src/pages/ComponentDoc/examples/ButtonComp/ToggleButton.tsx
+++ b/client/packages/lowcoder/src/pages/ComponentDoc/examples/ButtonComp/ToggleButton.tsx
@@ -36,9 +36,18 @@ export default function ToggleButtonExample() {
}}
compFactory={ToggleButtonComp}
/>
+
-
+
+
+
+
+
+
+
+
>
);
diff --git a/client/packages/lowcoder/src/pages/ComponentDoc/examples/CalendarInputComp/Calendar.tsx b/client/packages/lowcoder/src/pages/ComponentDoc/examples/CalendarInputComp/Calendar.tsx
index 6370df675..22375e860 100644
--- a/client/packages/lowcoder/src/pages/ComponentDoc/examples/CalendarInputComp/Calendar.tsx
+++ b/client/packages/lowcoder/src/pages/ComponentDoc/examples/CalendarInputComp/Calendar.tsx
@@ -11,14 +11,163 @@ export default function CalendarExample() {
<>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
>
);
diff --git a/client/packages/lowcoder/src/pages/ComponentDoc/examples/CalendarInputComp/Date.tsx b/client/packages/lowcoder/src/pages/ComponentDoc/examples/CalendarInputComp/Date.tsx
index c58a54332..b146a2f4b 100644
--- a/client/packages/lowcoder/src/pages/ComponentDoc/examples/CalendarInputComp/Date.tsx
+++ b/client/packages/lowcoder/src/pages/ComponentDoc/examples/CalendarInputComp/Date.tsx
@@ -53,6 +53,67 @@ export default function DateExample() {
/>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
>
);
}
diff --git a/client/packages/lowcoder/src/pages/ComponentDoc/examples/CalendarInputComp/DateRange.tsx b/client/packages/lowcoder/src/pages/ComponentDoc/examples/CalendarInputComp/DateRange.tsx
index ff2821dcb..b287c7bba 100644
--- a/client/packages/lowcoder/src/pages/ComponentDoc/examples/CalendarInputComp/DateRange.tsx
+++ b/client/packages/lowcoder/src/pages/ComponentDoc/examples/CalendarInputComp/DateRange.tsx
@@ -23,6 +23,7 @@ export default function DateRangeExample() {
>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
>
);
}
diff --git a/client/packages/lowcoder/src/pages/ComponentDoc/examples/CalendarInputComp/Time.tsx b/client/packages/lowcoder/src/pages/ComponentDoc/examples/CalendarInputComp/Time.tsx
index efb8b6b30..dc39976b9 100644
--- a/client/packages/lowcoder/src/pages/ComponentDoc/examples/CalendarInputComp/Time.tsx
+++ b/client/packages/lowcoder/src/pages/ComponentDoc/examples/CalendarInputComp/Time.tsx
@@ -51,6 +51,31 @@ export default function TimeExample() {
blackListConfig={blackListConfig}
compFactory={TimePickerComp}
/>
+
+
@@ -117,11 +142,11 @@ export default function TimeExample() {
compFactory={TimePickerComp}
/>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
>
);
diff --git a/client/packages/lowcoder/src/pages/ComponentDoc/examples/CalendarInputComp/TimeRange.tsx b/client/packages/lowcoder/src/pages/ComponentDoc/examples/CalendarInputComp/TimeRange.tsx
index 93d319b0e..de6df7cab 100644
--- a/client/packages/lowcoder/src/pages/ComponentDoc/examples/CalendarInputComp/TimeRange.tsx
+++ b/client/packages/lowcoder/src/pages/ComponentDoc/examples/CalendarInputComp/TimeRange.tsx
@@ -64,6 +64,19 @@ export default function TimeRangeExample() {
blackListConfig={blackListConfig}
compFactory={TimeRangeComp}
/>
+
@@ -140,10 +153,8 @@ export default function TimeRangeExample() {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
>
);
diff --git a/client/packages/lowcoder/src/pages/ComponentDoc/examples/CalendarInputComp/Timer.tsx b/client/packages/lowcoder/src/pages/ComponentDoc/examples/CalendarInputComp/Timer.tsx
index 50b2f2d39..54fba64d2 100644
--- a/client/packages/lowcoder/src/pages/ComponentDoc/examples/CalendarInputComp/Timer.tsx
+++ b/client/packages/lowcoder/src/pages/ComponentDoc/examples/CalendarInputComp/Timer.tsx
@@ -1,12 +1,14 @@
import { TimerComp } from "comps/comps/timerComp";
import Example from "../../common/Example";
import ExampleGroup from "../../common/ExampleGroup";
+import { startButtonStyle } from "@lowcoder-ee/index.sdk";
export default function TimerExample() {
return (
<>
+
+
+
+
+
+
+
+
+
+
+
+
+
>
);
diff --git a/client/packages/lowcoder/src/pages/ComponentDoc/examples/ChartsComp/CandleStickChart.tsx b/client/packages/lowcoder/src/pages/ComponentDoc/examples/ChartsComp/CandleStickChart.tsx
index 544055abe..943c651a7 100644
--- a/client/packages/lowcoder/src/pages/ComponentDoc/examples/ChartsComp/CandleStickChart.tsx
+++ b/client/packages/lowcoder/src/pages/ComponentDoc/examples/ChartsComp/CandleStickChart.tsx
@@ -6,54 +6,45 @@ import ExampleGroup from "../../common/ExampleGroup";
const ChartCompWithDefault = uiCompRegistry["candleStickChart"].comp;
-const defaultEchartsJsonOption = {
- "xAxis": {
- "data": [
- "Day 1",
- "Day 2",
- "Day 3",
- "Day 4",
- "Day 5"
- ]
- },
- "data": [
- [
- 150,
- 100,
- 50,
- 200
- ],
- [
- 120,
- 220,
- 80,
- 180
- ],
- [
- 80,
- 150,
- 60,
- 130
- ],
- [
- 230,
- 130,
- 110,
- 190
- ],
- [
- 90,
- 180,
- 70,
- 160
- ]
- ]
-};
+const chartStyle= {
+ background: "linear-gradient(135deg, #72afd3 0%, #96e6a1 100%)",
+ chartBorderColor: "#FDFAFA",
+ chartBorderStyle: "solid",
+ chartBorderWidth: "2",
+ chartBoxShadow: "200",
+ chartShadowColor: "#3377FF"
+}
-const echartsOption = JSON.stringify(defaultEchartsJsonOption);
+const titleStyle = {
+ chartBoxShadow: "9",
+ chartFontStyle: "Italic",
+ chartShadowColor: "#FFBD01",
+ chartTextColor: "#36B389",
+ chartTextSize: "30",
+ chartTextWeight: "Bold"
+}
+
+const xAxisStyle = {
+ chartBoxShadow: "5",
+ chartFontFamily: "serif",
+ chartFontStyle: "Italic",
+ chartShadowColor: "#020101",
+ chartTextColor: "#971827",
+ chartTextSize: "20",
+ chartTextWeight: "bold"
+}
+
+const yAxisStyle = {
+ chartBoxShadow: "5",
+ chartFontFamily: "serif",
+ chartFontStyle: "Italic",
+ chartShadowColor: "#FFD701",
+ chartTextColor: "#7A7A7B",
+ chartTextSize: "20",
+ chartTextWeight: "bold"
+}
export default function CandleStickChartExample() {
- const blackListConfig: string[] = ["echartsOption"];
return (
<>
@@ -74,7 +64,6 @@ export default function CandleStickChartExample() {
width={500}
height={300}
config={{
- echartsOption: echartsOption,
tooltip: false,
}}
compFactory={ChartCompWithDefault}
@@ -90,7 +79,6 @@ export default function CandleStickChartExample() {
width={500}
height={300}
config={{
- echartsOption: echartsOption,
top: 20,
right: 20,
bottom: 20,
@@ -109,7 +97,6 @@ export default function CandleStickChartExample() {
width={500}
height={300}
config={{
- echartsOption: echartsOption,
echartsTitleConfig: {
"position": "left",
},
@@ -121,7 +108,6 @@ export default function CandleStickChartExample() {
width={500}
height={300}
config={{
- echartsOption: echartsOption,
echartsTitleConfig: {
"position": "center",
},
@@ -133,7 +119,6 @@ export default function CandleStickChartExample() {
width={500}
height={300}
config={{
- echartsOption: echartsOption,
echartsTitleConfig: {
"position": "right",
},
@@ -145,7 +130,6 @@ export default function CandleStickChartExample() {
width={500}
height={300}
config={{
- echartsOption: echartsOption,
echartsLegendConfig: {
"position": "bottom",
},
@@ -157,7 +141,6 @@ export default function CandleStickChartExample() {
width={500}
height={300}
config={{
- echartsOption: echartsOption,
echartsLegendConfig: {
"position": "top",
},
@@ -165,6 +148,52 @@ export default function CandleStickChartExample() {
compFactory={ChartCompWithDefault}
/>
+
+
+
+
+
+
+
>
);
}
diff --git a/client/packages/lowcoder/src/pages/ComponentDoc/examples/ChartsComp/FunnelChart.tsx b/client/packages/lowcoder/src/pages/ComponentDoc/examples/ChartsComp/FunnelChart.tsx
index 424b8a102..777f9dcfe 100644
--- a/client/packages/lowcoder/src/pages/ComponentDoc/examples/ChartsComp/FunnelChart.tsx
+++ b/client/packages/lowcoder/src/pages/ComponentDoc/examples/ChartsComp/FunnelChart.tsx
@@ -5,6 +5,43 @@ import Example from "../../common/Example";
import ExampleGroup from "../../common/ExampleGroup";
const ChartCompWithDefault = uiCompRegistry["funnelChart"].comp;
+const chartStyle= {
+ background: "linear-gradient(135deg, #72afd3 0%, #96e6a1 100%)",
+ chartBorderColor: "#FDFAFA",
+ chartBorderStyle: "solid",
+ chartBorderWidth: "2",
+ chartBoxShadow: "200",
+ chartShadowColor: "#3377FF"
+}
+
+const titleStyle = {
+ chartBoxShadow: "9",
+ chartFontStyle: "Italic",
+ chartShadowColor: "#FFBD01",
+ chartTextColor: "#36B389",
+ chartTextSize: "30",
+ chartTextWeight: "Bold"
+}
+
+const labelStyle = {
+ chartBoxShadow: "5",
+ chartFontFamily: "serif",
+ chartFontStyle: "Italic",
+ chartShadowColor: "#020101",
+ chartTextColor: "#FFFFFF",
+ chartTextSize: "20",
+ chartTextWeight: "bold"
+}
+
+const legendStyle = {
+ chartBoxShadow: "5",
+ chartFontFamily: "serif",
+ chartFontStyle: "Italic",
+ chartShadowColor: "#FFD701",
+ chartTextColor: "#7A7A7B",
+ chartTextSize: "20",
+ chartTextWeight: "bold"
+}
export default function FunnelChartExample() {
return (
@@ -301,6 +338,52 @@ export default function FunnelChartExample() {
compFactory={ChartCompWithDefault}
/>
+
+
+
+
+
+
+
>
);
}
diff --git a/client/packages/lowcoder/src/pages/ComponentDoc/examples/ChartsComp/GanttChart.tsx b/client/packages/lowcoder/src/pages/ComponentDoc/examples/ChartsComp/GanttChart.tsx
index 5107be785..eac134170 100644
--- a/client/packages/lowcoder/src/pages/ComponentDoc/examples/ChartsComp/GanttChart.tsx
+++ b/client/packages/lowcoder/src/pages/ComponentDoc/examples/ChartsComp/GanttChart.tsx
@@ -11,15 +11,138 @@ export default function GanttChartExample() {
<>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
>
);
}
\ No newline at end of file
diff --git a/client/packages/lowcoder/src/pages/ComponentDoc/examples/ChartsComp/GaugeChart.tsx b/client/packages/lowcoder/src/pages/ComponentDoc/examples/ChartsComp/GaugeChart.tsx
index 7a57ee549..43d87a45d 100644
--- a/client/packages/lowcoder/src/pages/ComponentDoc/examples/ChartsComp/GaugeChart.tsx
+++ b/client/packages/lowcoder/src/pages/ComponentDoc/examples/ChartsComp/GaugeChart.tsx
@@ -6,6 +6,170 @@ import ExampleGroup from "../../common/ExampleGroup";
const ChartCompWithDefault = uiCompRegistry["gaugeChart"].comp;
+const barometerGuageOption = {
+ "data": [
+ {
+ "formatter": "{value}%",
+ "value": 58.46,
+ "name": "PLP",
+ "outline": {
+ "color": "#c80707",
+ "period": [
+ 0,
+ 100
+ ],
+ "splitNumber": 10,
+ "progressBarWidth": 2,
+ "axisTickLength": 6,
+ "axisTickWidth": 2,
+ "radius": "70%"
+ },
+ "inline": {
+ "color": "#000000",
+ "period": [
+ 0,
+ 60
+ ],
+ "progressBarWidth": 2,
+ "splitNumber": 6,
+ "axisTickLength": 6,
+ "axisTickWidth": 2,
+ "radius": "60%"
+ }
+ }
+ ]
+};
+
+const clockGuageOption = {
+ "data": [
+ {
+ "outlineColor": "#aa2a2a",
+ "anchor": {
+ "color": "#cfae09",
+ "size": 10
+ },
+ "hour": {
+ "color": "#cfae09",
+ "width": 4,
+ "length": 50,
+ "value": 4
+ },
+ "minute": {
+ "color": "#cfae09",
+ "width": 2.5,
+ "length": 65,
+ "value": 30
+ },
+ "second": {
+ "color": "#cfae09",
+ "width": 1,
+ "length": 90,
+ "value": 45
+ }
+ }
+ ]
+};
+
+const gradeGuageOption = {
+ "data": [
+ {
+ "value": 80,
+ "name": "Grade Rating",
+ "formatter": "{value} %",
+ "color": [
+ [
+ 0.25,
+ "#FF6E76"
+ ],
+ [
+ 0.5,
+ "#FDDD60"
+ ],
+ [
+ 0.75,
+ "#58D9F9"
+ ],
+ [
+ 1,
+ "#7CFFB2"
+ ]
+ ]
+ }
+ ]
+};
+
+const multiTitleGuageOption = {
+ "data": [
+ {
+ "formatter": "{value}%",
+ "value": [
+ {
+ "color": "#19b1e6",
+ "title": "Perfect",
+ "value": 20,
+ "titlePosition": [
+ "-60%",
+ "60%"
+ ],
+ "valuePosition": [
+ "-60%",
+ "80%"
+ ]
+ },
+ {
+ "color": "#fac858",
+ "title": "Good",
+ "value": 40,
+ "titlePosition": [
+ "0%",
+ "60%"
+ ],
+ "valuePosition": [
+ "0%",
+ "80%"
+ ]
+ },
+ {
+ "color": "#09f64d",
+ "title": "Commonly",
+ "value": 60,
+ "titlePosition": [
+ "60%",
+ "60%"
+ ],
+ "valuePosition": [
+ "60%",
+ "80%"
+ ]
+ }
+ ]
+ }
+ ]
+};
+
+const stageGuageOption = {
+ "data": [
+ {
+ "value": 80,
+ "formatter": "{value} Km/h",
+ "color": [
+ [
+ 0.3,
+ "#67e0e3"
+ ],
+ [
+ 0.7,
+ "#37a2da"
+ ],
+ [
+ 1,
+ "#fd666d"
+ ]
+ ]
+ }
+ ]
+};
+
export default function GaugeChartExample() {
return (
<>
@@ -26,7 +190,8 @@ export default function GaugeChartExample() {
width={500}
height={300}
config={{
- chartType: "stageGuage",
+ chartType: "stageGauge",
+ echartsTitle: "Stage Speed Gauge",
}}
compFactory={ChartCompWithDefault}
/>
@@ -35,7 +200,8 @@ export default function GaugeChartExample() {
width={500}
height={300}
config={{
- chartType: "gradeGuage",
+ chartType: "gradeGauge",
+ echartsTitle: "Grade Gauge",
}}
compFactory={ChartCompWithDefault}
/>
@@ -44,25 +210,230 @@ export default function GaugeChartExample() {
width={500}
height={300}
config={{
- chartType: "temperatureGuage",
+ chartType: "temperatureGauge",
+ echartsTitle: "Temperature Gauge Chart",
}}
compFactory={ChartCompWithDefault}
/>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/client/packages/lowcoder/src/pages/ComponentDoc/examples/ChartsComp/GeoMapChart.tsx b/client/packages/lowcoder/src/pages/ComponentDoc/examples/ChartsComp/GeoMapChart.tsx
index dd6bf3fb5..7ce9f66db 100644
--- a/client/packages/lowcoder/src/pages/ComponentDoc/examples/ChartsComp/GeoMapChart.tsx
+++ b/client/packages/lowcoder/src/pages/ComponentDoc/examples/ChartsComp/GeoMapChart.tsx
@@ -6,27 +6,7 @@ import ExampleGroup from "../../common/ExampleGroup";
const ChartCompWithDefault = uiCompRegistry["chartsGeoMap"].comp;
-const defaultDataSource = "[\n {\n \"date\": \"2021-09\",\n \"department\": \"Administration\",\n \"spending\": 9003,\n \"budget\": 8000\n },\n {\n \"date\": \"2021-09\",\n \"department\": \"Finance\",\n \"spending\": 3033,\n \"budget\": 4000\n },\n {\n \"date\": \"2021-09\",\n \"department\": \"Sales\",\n \"spending\": 9230,\n \"budget\": 8000\n },\n {\n \"date\": \"2021-10\",\n \"department\": \"Administration\",\n \"spending\": 13032,\n \"budget\": 15000\n },\n {\n \"date\": \"2021-10\",\n \"department\": \"Finance\",\n \"spending\": 2300,\n \"budget\": 5000\n },\n {\n \"date\": \"2021-10\",\n \"department\": \"Sales\",\n \"spending\": 7323.5,\n \"budget\": 8000\n },\n {\n \"date\": \"2021-11\",\n \"department\": \"Administration\",\n \"spending\": 13000,\n \"budget\": 16023\n },\n {\n \"date\": \"2021-11\",\n \"department\": \"Finance\",\n \"spending\": 3569.5,\n \"budget\": 3000\n },\n {\n \"date\": \"2021-11\",\n \"department\": \"Sales\",\n \"spending\": 10000,\n \"budget\": 9932\n },\n {\n \"date\": \"2021-12\",\n \"department\": \"Administration\",\n \"spending\": 18033,\n \"budget\": 20000\n },\n {\n \"date\": \"2021-12\",\n \"department\": \"Finance\",\n \"spending\": 4890,\n \"budget\": 4500\n },\n {\n \"date\": \"2021-12\",\n \"department\": \"Sales\",\n \"spending\": 9322,\n \"budget\": 8000\n }\n]";
-
-const defaultEchartsJsonOption = "{\n \"xAxis\": {\n \"data\": [\n \"Day 1\",\n \"Day 2\",\n \"Day 3\",\n \"Day 4\",\n \"Day 5\"\n ]\n },\n \"data\": [\n [\n 100,\n 200,\n 50,\n 150\n ],\n [\n 120,\n 220,\n 80,\n 180\n ],\n [\n 80,\n 150,\n 60,\n 130\n ],\n [\n 130,\n 230,\n 110,\n 190\n ],\n [\n 90,\n 180,\n 70,\n 160\n ]\n ]\n}";
-
-const data = JSON.stringify(defaultDataSource);
-const echartsOption = JSON.stringify(defaultEchartsJsonOption);
-
export default function GeoMapChartExample() {
- const blackListConfig: string[] = ["data", "echartsOption", "series"];
- const series = [
- {
- "columnName": "spending",
- "seriesName": "Spending",
- "dataIndex": "f011b34c"
- },
- {
- "columnName": "budget",
- "seriesName": "Budget",
- "dataIndex": "30e02269"
- }
-];
return (
<>
+
+
+
+
+
+
+
+
+
diff --git a/client/packages/lowcoder/src/pages/ComponentDoc/examples/ChartsComp/GraphChart.tsx b/client/packages/lowcoder/src/pages/ComponentDoc/examples/ChartsComp/GraphChart.tsx
index 3024a613b..b19bf5f6e 100644
--- a/client/packages/lowcoder/src/pages/ComponentDoc/examples/ChartsComp/GraphChart.tsx
+++ b/client/packages/lowcoder/src/pages/ComponentDoc/examples/ChartsComp/GraphChart.tsx
@@ -6,27 +6,25 @@ import ExampleGroup from "../../common/ExampleGroup";
const ChartCompWithDefault = uiCompRegistry["graphChart"].comp;
-const defaultDataSource = "[\n {\n \"date\": \"2021-09\",\n \"department\": \"Administration\",\n \"spending\": 9003,\n \"budget\": 8000\n },\n {\n \"date\": \"2021-09\",\n \"department\": \"Finance\",\n \"spending\": 3033,\n \"budget\": 4000\n },\n {\n \"date\": \"2021-09\",\n \"department\": \"Sales\",\n \"spending\": 9230,\n \"budget\": 8000\n },\n {\n \"date\": \"2021-10\",\n \"department\": \"Administration\",\n \"spending\": 13032,\n \"budget\": 15000\n },\n {\n \"date\": \"2021-10\",\n \"department\": \"Finance\",\n \"spending\": 2300,\n \"budget\": 5000\n },\n {\n \"date\": \"2021-10\",\n \"department\": \"Sales\",\n \"spending\": 7323.5,\n \"budget\": 8000\n },\n {\n \"date\": \"2021-11\",\n \"department\": \"Administration\",\n \"spending\": 13000,\n \"budget\": 16023\n },\n {\n \"date\": \"2021-11\",\n \"department\": \"Finance\",\n \"spending\": 3569.5,\n \"budget\": 3000\n },\n {\n \"date\": \"2021-11\",\n \"department\": \"Sales\",\n \"spending\": 10000,\n \"budget\": 9932\n },\n {\n \"date\": \"2021-12\",\n \"department\": \"Administration\",\n \"spending\": 18033,\n \"budget\": 20000\n },\n {\n \"date\": \"2021-12\",\n \"department\": \"Finance\",\n \"spending\": 4890,\n \"budget\": 4500\n },\n {\n \"date\": \"2021-12\",\n \"department\": \"Sales\",\n \"spending\": 9322,\n \"budget\": 8000\n }\n]";
-
-const defaultEchartsJsonOption = "{\n \"xAxis\": {\n \"data\": [\n \"Day 1\",\n \"Day 2\",\n \"Day 3\",\n \"Day 4\",\n \"Day 5\"\n ]\n },\n \"data\": [\n [\n 100,\n 200,\n 50,\n 150\n ],\n [\n 120,\n 220,\n 80,\n 180\n ],\n [\n 80,\n 150,\n 60,\n 130\n ],\n [\n 130,\n 230,\n 110,\n 190\n ],\n [\n 90,\n 180,\n 70,\n 160\n ]\n ]\n}";
+const chartStyle= {
+ background: "linear-gradient(135deg, #72afd3 0%, #96e6a1 100%)",
+ chartBorderColor: "#FDFAFA",
+ chartBorderStyle: "solid",
+ chartBorderWidth: "2",
+ chartBoxShadow: "200",
+ chartShadowColor: "#3377FF"
+}
-const data = JSON.stringify(defaultDataSource);
-const echartsOption = JSON.stringify(defaultEchartsJsonOption);
+const titleStyle = {
+ chartBoxShadow: "9",
+ chartFontStyle: "Italic",
+ chartShadowColor: "#FFBD01",
+ chartTextColor: "#36B389",
+ chartTextSize: "30",
+ chartTextWeight: "Bold"
+}
export default function GraphChartExample() {
- const blackListConfig: string[] = ["data", "echartsOption", "series"];
- const series = [
- {
- "columnName": "spending",
- "seriesName": "Spending",
- "dataIndex": "f011b34c"
- },
- {
- "columnName": "budget",
- "seriesName": "Budget",
- "dataIndex": "30e02269"
- }
-];
return (
<>
+
+
+
+
+
diff --git a/client/packages/lowcoder/src/pages/ComponentDoc/examples/ChartsComp/HeatmapChart.tsx b/client/packages/lowcoder/src/pages/ComponentDoc/examples/ChartsComp/HeatmapChart.tsx
index c2a60b7eb..0c82cdd08 100644
--- a/client/packages/lowcoder/src/pages/ComponentDoc/examples/ChartsComp/HeatmapChart.tsx
+++ b/client/packages/lowcoder/src/pages/ComponentDoc/examples/ChartsComp/HeatmapChart.tsx
@@ -6,27 +6,45 @@ import ExampleGroup from "../../common/ExampleGroup";
const ChartCompWithDefault = uiCompRegistry["heatmapChart"].comp;
-const defaultDataSource = "[\n {\n \"date\": \"2021-09\",\n \"department\": \"Administration\",\n \"spending\": 9003,\n \"budget\": 8000\n },\n {\n \"date\": \"2021-09\",\n \"department\": \"Finance\",\n \"spending\": 3033,\n \"budget\": 4000\n },\n {\n \"date\": \"2021-09\",\n \"department\": \"Sales\",\n \"spending\": 9230,\n \"budget\": 8000\n },\n {\n \"date\": \"2021-10\",\n \"department\": \"Administration\",\n \"spending\": 13032,\n \"budget\": 15000\n },\n {\n \"date\": \"2021-10\",\n \"department\": \"Finance\",\n \"spending\": 2300,\n \"budget\": 5000\n },\n {\n \"date\": \"2021-10\",\n \"department\": \"Sales\",\n \"spending\": 7323.5,\n \"budget\": 8000\n },\n {\n \"date\": \"2021-11\",\n \"department\": \"Administration\",\n \"spending\": 13000,\n \"budget\": 16023\n },\n {\n \"date\": \"2021-11\",\n \"department\": \"Finance\",\n \"spending\": 3569.5,\n \"budget\": 3000\n },\n {\n \"date\": \"2021-11\",\n \"department\": \"Sales\",\n \"spending\": 10000,\n \"budget\": 9932\n },\n {\n \"date\": \"2021-12\",\n \"department\": \"Administration\",\n \"spending\": 18033,\n \"budget\": 20000\n },\n {\n \"date\": \"2021-12\",\n \"department\": \"Finance\",\n \"spending\": 4890,\n \"budget\": 4500\n },\n {\n \"date\": \"2021-12\",\n \"department\": \"Sales\",\n \"spending\": 9322,\n \"budget\": 8000\n }\n]";
+const chartStyle= {
+ background: "linear-gradient(135deg, #72afd3 0%, #96e6a1 100%)",
+ chartBorderColor: "#FDFAFA",
+ chartBorderStyle: "solid",
+ chartBorderWidth: "2",
+ chartBoxShadow: "200",
+ chartShadowColor: "#3377FF"
+}
-const defaultEchartsJsonOption = "{\n \"xAxis\": {\n \"data\": [\n \"Day 1\",\n \"Day 2\",\n \"Day 3\",\n \"Day 4\",\n \"Day 5\"\n ]\n },\n \"data\": [\n [\n 100,\n 200,\n 50,\n 150\n ],\n [\n 120,\n 220,\n 80,\n 180\n ],\n [\n 80,\n 150,\n 60,\n 130\n ],\n [\n 130,\n 230,\n 110,\n 190\n ],\n [\n 90,\n 180,\n 70,\n 160\n ]\n ]\n}";
+const titleStyle = {
+ chartBoxShadow: "9",
+ chartFontStyle: "Italic",
+ chartShadowColor: "#FFBD01",
+ chartTextColor: "#36B389",
+ chartTextSize: "30",
+ chartTextWeight: "Bold"
+}
-const data = JSON.stringify(defaultDataSource);
-const echartsOption = JSON.stringify(defaultEchartsJsonOption);
+const xAxisStyle = {
+ chartBoxShadow: "5",
+ chartFontFamily: "serif",
+ chartFontStyle: "Italic",
+ chartShadowColor: "#020101",
+ chartTextColor: "#971827",
+ chartTextSize: "20",
+ chartTextWeight: "bold"
+}
+
+const yAxisStyle = {
+ chartBoxShadow: "5",
+ chartFontFamily: "serif",
+ chartFontStyle: "Italic",
+ chartShadowColor: "#FFD701",
+ chartTextColor: "#7A7A7B",
+ chartTextSize: "20",
+ chartTextWeight: "bold"
+}
export default function HeatmapChartExample() {
- const blackListConfig: string[] = ["data", "echartsOption", "series"];
- const series = [
- {
- "columnName": "spending",
- "seriesName": "Spending",
- "dataIndex": "f011b34c"
- },
- {
- "columnName": "budget",
- "seriesName": "Budget",
- "dataIndex": "30e02269"
- }
-];
return (
<>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
>
);
diff --git a/client/packages/lowcoder/src/pages/ComponentDoc/examples/ChartsComp/HillChart.tsx b/client/packages/lowcoder/src/pages/ComponentDoc/examples/ChartsComp/HillChart.tsx
index 09d371666..f7fd46951 100644
--- a/client/packages/lowcoder/src/pages/ComponentDoc/examples/ChartsComp/HillChart.tsx
+++ b/client/packages/lowcoder/src/pages/ComponentDoc/examples/ChartsComp/HillChart.tsx
@@ -11,10 +11,12 @@ export default function HillChartExample() {
<>
+ Defining --> Designing --> Building --> Testing --> Deployment --> Planning",
}}
compFactory={ChartCompWithDefault}
/>
diff --git a/client/packages/lowcoder/src/pages/ComponentDoc/examples/ChartsComp/OpenLayersGeoMap.tsx b/client/packages/lowcoder/src/pages/ComponentDoc/examples/ChartsComp/OpenLayersGeoMap.tsx
index 306871822..ac8287742 100644
--- a/client/packages/lowcoder/src/pages/ComponentDoc/examples/ChartsComp/OpenLayersGeoMap.tsx
+++ b/client/packages/lowcoder/src/pages/ComponentDoc/examples/ChartsComp/OpenLayersGeoMap.tsx
@@ -6,27 +6,7 @@ import ExampleGroup from "../../common/ExampleGroup";
const ChartCompWithDefault = uiCompRegistry["openLayersGeoMap"].comp;
-const defaultDataSource = "[\n {\n \"date\": \"2021-09\",\n \"department\": \"Administration\",\n \"spending\": 9003,\n \"budget\": 8000\n },\n {\n \"date\": \"2021-09\",\n \"department\": \"Finance\",\n \"spending\": 3033,\n \"budget\": 4000\n },\n {\n \"date\": \"2021-09\",\n \"department\": \"Sales\",\n \"spending\": 9230,\n \"budget\": 8000\n },\n {\n \"date\": \"2021-10\",\n \"department\": \"Administration\",\n \"spending\": 13032,\n \"budget\": 15000\n },\n {\n \"date\": \"2021-10\",\n \"department\": \"Finance\",\n \"spending\": 2300,\n \"budget\": 5000\n },\n {\n \"date\": \"2021-10\",\n \"department\": \"Sales\",\n \"spending\": 7323.5,\n \"budget\": 8000\n },\n {\n \"date\": \"2021-11\",\n \"department\": \"Administration\",\n \"spending\": 13000,\n \"budget\": 16023\n },\n {\n \"date\": \"2021-11\",\n \"department\": \"Finance\",\n \"spending\": 3569.5,\n \"budget\": 3000\n },\n {\n \"date\": \"2021-11\",\n \"department\": \"Sales\",\n \"spending\": 10000,\n \"budget\": 9932\n },\n {\n \"date\": \"2021-12\",\n \"department\": \"Administration\",\n \"spending\": 18033,\n \"budget\": 20000\n },\n {\n \"date\": \"2021-12\",\n \"department\": \"Finance\",\n \"spending\": 4890,\n \"budget\": 4500\n },\n {\n \"date\": \"2021-12\",\n \"department\": \"Sales\",\n \"spending\": 9322,\n \"budget\": 8000\n }\n]";
-
-const defaultEchartsJsonOption = "{\n \"xAxis\": {\n \"data\": [\n \"Day 1\",\n \"Day 2\",\n \"Day 3\",\n \"Day 4\",\n \"Day 5\"\n ]\n },\n \"data\": [\n [\n 100,\n 200,\n 50,\n 150\n ],\n [\n 120,\n 220,\n 80,\n 180\n ],\n [\n 80,\n 150,\n 60,\n 130\n ],\n [\n 130,\n 230,\n 110,\n 190\n ],\n [\n 90,\n 180,\n 70,\n 160\n ]\n ]\n}";
-
-const data = JSON.stringify(defaultDataSource);
-const echartsOption = JSON.stringify(defaultEchartsJsonOption);
-
export default function OpenLayersGeoMapChartExample() {
- const blackListConfig: string[] = ["data", "echartsOption", "series"];
- const series = [
- {
- "columnName": "spending",
- "seriesName": "Spending",
- "dataIndex": "f011b34c"
- },
- {
- "columnName": "budget",
- "seriesName": "Budget",
- "dataIndex": "30e02269"
- }
-];
return (
<>
+
+
+
+
diff --git a/client/packages/lowcoder/src/pages/ComponentDoc/examples/ChartsComp/RadarChart.tsx b/client/packages/lowcoder/src/pages/ComponentDoc/examples/ChartsComp/RadarChart.tsx
index 662ece815..5a211eea9 100644
--- a/client/packages/lowcoder/src/pages/ComponentDoc/examples/ChartsComp/RadarChart.tsx
+++ b/client/packages/lowcoder/src/pages/ComponentDoc/examples/ChartsComp/RadarChart.tsx
@@ -6,27 +6,45 @@ import ExampleGroup from "../../common/ExampleGroup";
const ChartCompWithDefault = uiCompRegistry["radarChart"].comp;
-const defaultDataSource = "[\n {\n \"date\": \"2021-09\",\n \"department\": \"Administration\",\n \"spending\": 9003,\n \"budget\": 8000\n },\n {\n \"date\": \"2021-09\",\n \"department\": \"Finance\",\n \"spending\": 3033,\n \"budget\": 4000\n },\n {\n \"date\": \"2021-09\",\n \"department\": \"Sales\",\n \"spending\": 9230,\n \"budget\": 8000\n },\n {\n \"date\": \"2021-10\",\n \"department\": \"Administration\",\n \"spending\": 13032,\n \"budget\": 15000\n },\n {\n \"date\": \"2021-10\",\n \"department\": \"Finance\",\n \"spending\": 2300,\n \"budget\": 5000\n },\n {\n \"date\": \"2021-10\",\n \"department\": \"Sales\",\n \"spending\": 7323.5,\n \"budget\": 8000\n },\n {\n \"date\": \"2021-11\",\n \"department\": \"Administration\",\n \"spending\": 13000,\n \"budget\": 16023\n },\n {\n \"date\": \"2021-11\",\n \"department\": \"Finance\",\n \"spending\": 3569.5,\n \"budget\": 3000\n },\n {\n \"date\": \"2021-11\",\n \"department\": \"Sales\",\n \"spending\": 10000,\n \"budget\": 9932\n },\n {\n \"date\": \"2021-12\",\n \"department\": \"Administration\",\n \"spending\": 18033,\n \"budget\": 20000\n },\n {\n \"date\": \"2021-12\",\n \"department\": \"Finance\",\n \"spending\": 4890,\n \"budget\": 4500\n },\n {\n \"date\": \"2021-12\",\n \"department\": \"Sales\",\n \"spending\": 9322,\n \"budget\": 8000\n }\n]";
+const chartStyle= {
+ background: "linear-gradient(135deg, #72afd3 0%, #96e6a1 100%)",
+ chartBorderColor: "#FDFAFA",
+ chartBorderStyle: "solid",
+ chartBorderWidth: "2",
+ chartBoxShadow: "200",
+ chartShadowColor: "#3377FF"
+}
+
+const titleStyle = {
+ chartBoxShadow: "9",
+ chartFontStyle: "Italic",
+ chartShadowColor: "#FFBD01",
+ chartTextColor: "#36B389",
+ chartTextSize: "30",
+ chartTextWeight: "Bold"
+}
-const defaultEchartsJsonOption = "{\n \"xAxis\": {\n \"data\": [\n \"Day 1\",\n \"Day 2\",\n \"Day 3\",\n \"Day 4\",\n \"Day 5\"\n ]\n },\n \"data\": [\n [\n 100,\n 200,\n 50,\n 150\n ],\n [\n 120,\n 220,\n 80,\n 180\n ],\n [\n 80,\n 150,\n 60,\n 130\n ],\n [\n 130,\n 230,\n 110,\n 190\n ],\n [\n 90,\n 180,\n 70,\n 160\n ]\n ]\n}";
+const labelStyle = {
+ chartBoxShadow: "5",
+ chartFontFamily: "serif",
+ chartFontStyle: "Italic",
+ chartShadowColor: "#020101",
+ chartTextColor: "#FFFFFF",
+ chartTextSize: "20",
+ chartTextWeight: "bold"
+}
-const data = JSON.stringify(defaultDataSource);
-const echartsOption = JSON.stringify(defaultEchartsJsonOption);
+const legendStyle = {
+ chartBoxShadow: "5",
+ chartFontFamily: "serif",
+ chartFontStyle: "Italic",
+ chartShadowColor: "#FFD701",
+ chartTextColor: "#7A7A7B",
+ chartTextSize: "20",
+ chartTextWeight: "bold"
+}
export default function RadarChartExample() {
- const blackListConfig: string[] = ["data", "echartsOption", "series"];
- const series = [
- {
- "columnName": "spending",
- "seriesName": "Spending",
- "dataIndex": "f011b34c"
- },
- {
- "columnName": "budget",
- "seriesName": "Budget",
- "dataIndex": "30e02269"
- }
-];
return (
<>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
>
);
}
diff --git a/client/packages/lowcoder/src/pages/ComponentDoc/examples/ChartsComp/SankeyChart.tsx b/client/packages/lowcoder/src/pages/ComponentDoc/examples/ChartsComp/SankeyChart.tsx
index c169e7b37..5a2981536 100644
--- a/client/packages/lowcoder/src/pages/ComponentDoc/examples/ChartsComp/SankeyChart.tsx
+++ b/client/packages/lowcoder/src/pages/ComponentDoc/examples/ChartsComp/SankeyChart.tsx
@@ -6,27 +6,42 @@ import ExampleGroup from "../../common/ExampleGroup";
const ChartCompWithDefault = uiCompRegistry["sankeyChart"].comp;
-const defaultDataSource = "[\n {\n \"date\": \"2021-09\",\n \"department\": \"Administration\",\n \"spending\": 9003,\n \"budget\": 8000\n },\n {\n \"date\": \"2021-09\",\n \"department\": \"Finance\",\n \"spending\": 3033,\n \"budget\": 4000\n },\n {\n \"date\": \"2021-09\",\n \"department\": \"Sales\",\n \"spending\": 9230,\n \"budget\": 8000\n },\n {\n \"date\": \"2021-10\",\n \"department\": \"Administration\",\n \"spending\": 13032,\n \"budget\": 15000\n },\n {\n \"date\": \"2021-10\",\n \"department\": \"Finance\",\n \"spending\": 2300,\n \"budget\": 5000\n },\n {\n \"date\": \"2021-10\",\n \"department\": \"Sales\",\n \"spending\": 7323.5,\n \"budget\": 8000\n },\n {\n \"date\": \"2021-11\",\n \"department\": \"Administration\",\n \"spending\": 13000,\n \"budget\": 16023\n },\n {\n \"date\": \"2021-11\",\n \"department\": \"Finance\",\n \"spending\": 3569.5,\n \"budget\": 3000\n },\n {\n \"date\": \"2021-11\",\n \"department\": \"Sales\",\n \"spending\": 10000,\n \"budget\": 9932\n },\n {\n \"date\": \"2021-12\",\n \"department\": \"Administration\",\n \"spending\": 18033,\n \"budget\": 20000\n },\n {\n \"date\": \"2021-12\",\n \"department\": \"Finance\",\n \"spending\": 4890,\n \"budget\": 4500\n },\n {\n \"date\": \"2021-12\",\n \"department\": \"Sales\",\n \"spending\": 9322,\n \"budget\": 8000\n }\n]";
+const chartStyle= {
+ background: "linear-gradient(135deg, #72afd3 0%, #96e6a1 100%)",
+ chartBorderColor: "#FDFAFA",
+ chartBorderStyle: "solid",
+ chartBorderWidth: "2",
+ chartBoxShadow: "200",
+ chartShadowColor: "#3377FF"
+}
-const defaultEchartsJsonOption = "{\n \"xAxis\": {\n \"data\": [\n \"Day 1\",\n \"Day 2\",\n \"Day 3\",\n \"Day 4\",\n \"Day 5\"\n ]\n },\n \"data\": [\n [\n 100,\n 200,\n 50,\n 150\n ],\n [\n 120,\n 220,\n 80,\n 180\n ],\n [\n 80,\n 150,\n 60,\n 130\n ],\n [\n 130,\n 230,\n 110,\n 190\n ],\n [\n 90,\n 180,\n 70,\n 160\n ]\n ]\n}";
+const titleStyle = {
+ chartBoxShadow: "9",
+ chartFontStyle: "Italic",
+ chartShadowColor: "#FFBD01",
+ chartTextColor: "#36B389",
+ chartTextSize: "30",
+ chartTextWeight: "Bold"
+}
-const data = JSON.stringify(defaultDataSource);
-const echartsOption = JSON.stringify(defaultEchartsJsonOption);
+const lineStyle = {
+ chartBoxShadow: "5",
+ chartShadowColor: "#020101",
+ chartBorderColor: "#222222",
+ chartBorderWidth: "3",
+}
+
+const detailStyle = {
+ chartBoxShadow: "5",
+ chartFontFamily: "serif",
+ chartFontStyle: "Italic",
+ chartShadowColor: "#FFD701",
+ chartTextColor: "#7A7A7B",
+ chartTextSize: "20",
+ chartTextWeight: "bold"
+}
export default function SankeyChartExample() {
- const blackListConfig: string[] = ["data", "echartsOption", "series"];
- const series = [
- {
- "columnName": "spending",
- "seriesName": "Spending",
- "dataIndex": "f011b34c"
- },
- {
- "columnName": "budget",
- "seriesName": "Budget",
- "dataIndex": "30e02269"
- }
-];
return (
<>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/client/packages/lowcoder/src/pages/ComponentDoc/examples/ChartsComp/SunburstChart.tsx b/client/packages/lowcoder/src/pages/ComponentDoc/examples/ChartsComp/SunburstChart.tsx
index c04aec9d4..468d1ca02 100644
--- a/client/packages/lowcoder/src/pages/ComponentDoc/examples/ChartsComp/SunburstChart.tsx
+++ b/client/packages/lowcoder/src/pages/ComponentDoc/examples/ChartsComp/SunburstChart.tsx
@@ -6,29 +6,36 @@ import ExampleGroup from "../../common/ExampleGroup";
const ChartCompWithDefault = uiCompRegistry["sunburstChart"].comp;
-const defaultDataSource = "[\n {\n \"date\": \"2021-09\",\n \"department\": \"Administration\",\n \"spending\": 9003,\n \"budget\": 8000\n },\n {\n \"date\": \"2021-09\",\n \"department\": \"Finance\",\n \"spending\": 3033,\n \"budget\": 4000\n },\n {\n \"date\": \"2021-09\",\n \"department\": \"Sales\",\n \"spending\": 9230,\n \"budget\": 8000\n },\n {\n \"date\": \"2021-10\",\n \"department\": \"Administration\",\n \"spending\": 13032,\n \"budget\": 15000\n },\n {\n \"date\": \"2021-10\",\n \"department\": \"Finance\",\n \"spending\": 2300,\n \"budget\": 5000\n },\n {\n \"date\": \"2021-10\",\n \"department\": \"Sales\",\n \"spending\": 7323.5,\n \"budget\": 8000\n },\n {\n \"date\": \"2021-11\",\n \"department\": \"Administration\",\n \"spending\": 13000,\n \"budget\": 16023\n },\n {\n \"date\": \"2021-11\",\n \"department\": \"Finance\",\n \"spending\": 3569.5,\n \"budget\": 3000\n },\n {\n \"date\": \"2021-11\",\n \"department\": \"Sales\",\n \"spending\": 10000,\n \"budget\": 9932\n },\n {\n \"date\": \"2021-12\",\n \"department\": \"Administration\",\n \"spending\": 18033,\n \"budget\": 20000\n },\n {\n \"date\": \"2021-12\",\n \"department\": \"Finance\",\n \"spending\": 4890,\n \"budget\": 4500\n },\n {\n \"date\": \"2021-12\",\n \"department\": \"Sales\",\n \"spending\": 9322,\n \"budget\": 8000\n }\n]";
+const chartStyle= {
+ background: "linear-gradient(135deg, #72afd3 0%, #96e6a1 100%)",
+ chartBorderColor: "#FDFAFA",
+ chartBorderStyle: "solid",
+ chartBorderWidth: "2",
+ chartBoxShadow: "200",
+ chartShadowColor: "#3377FF"
+}
-const defaultEchartsJsonOption = "{\n \"xAxis\": {\n \"data\": [\n \"Day 1\",\n \"Day 2\",\n \"Day 3\",\n \"Day 4\",\n \"Day 5\"\n ]\n },\n \"data\": [\n [\n 100,\n 200,\n 50,\n 150\n ],\n [\n 120,\n 220,\n 80,\n 180\n ],\n [\n 80,\n 150,\n 60,\n 130\n ],\n [\n 130,\n 230,\n 110,\n 190\n ],\n [\n 90,\n 180,\n 70,\n 160\n ]\n ]\n}";
+const titleStyle = {
+ chartBoxShadow: "9",
+ chartFontStyle: "Italic",
+ chartShadowColor: "#FFBD01",
+ chartTextColor: "#36B389",
+ chartTextSize: "30",
+ chartTextWeight: "Bold"
+}
-const data = JSON.stringify(defaultDataSource);
-const echartsOption = JSON.stringify(defaultEchartsJsonOption);
+const detailStyle = {
+ chartFontFamily: "serif",
+ chartFontStyle: "Italic",
+ chartTextColor: "#7A7A7B",
+ chartTextSize: "20",
+ chartTextWeight: "bold"
+}
export default function SunburstChartExample() {
- const blackListConfig: string[] = ["data", "echartsOption", "series"];
- const series = [
- {
- "columnName": "spending",
- "seriesName": "Spending",
- "dataIndex": "f011b34c"
- },
- {
- "columnName": "budget",
- "seriesName": "Budget",
- "dataIndex": "30e02269"
- }
-];
return (
<>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/client/packages/lowcoder/src/pages/ComponentDoc/examples/ChartsComp/ThemeRiverChart.tsx b/client/packages/lowcoder/src/pages/ComponentDoc/examples/ChartsComp/ThemeRiverChart.tsx
index b8dbe29d8..a32d2f479 100644
--- a/client/packages/lowcoder/src/pages/ComponentDoc/examples/ChartsComp/ThemeRiverChart.tsx
+++ b/client/packages/lowcoder/src/pages/ComponentDoc/examples/ChartsComp/ThemeRiverChart.tsx
@@ -6,27 +6,44 @@ import ExampleGroup from "../../common/ExampleGroup";
const ChartCompWithDefault = uiCompRegistry["themeriverChart"].comp;
-const defaultDataSource = "[\n {\n \"date\": \"2021-09\",\n \"department\": \"Administration\",\n \"spending\": 9003,\n \"budget\": 8000\n },\n {\n \"date\": \"2021-09\",\n \"department\": \"Finance\",\n \"spending\": 3033,\n \"budget\": 4000\n },\n {\n \"date\": \"2021-09\",\n \"department\": \"Sales\",\n \"spending\": 9230,\n \"budget\": 8000\n },\n {\n \"date\": \"2021-10\",\n \"department\": \"Administration\",\n \"spending\": 13032,\n \"budget\": 15000\n },\n {\n \"date\": \"2021-10\",\n \"department\": \"Finance\",\n \"spending\": 2300,\n \"budget\": 5000\n },\n {\n \"date\": \"2021-10\",\n \"department\": \"Sales\",\n \"spending\": 7323.5,\n \"budget\": 8000\n },\n {\n \"date\": \"2021-11\",\n \"department\": \"Administration\",\n \"spending\": 13000,\n \"budget\": 16023\n },\n {\n \"date\": \"2021-11\",\n \"department\": \"Finance\",\n \"spending\": 3569.5,\n \"budget\": 3000\n },\n {\n \"date\": \"2021-11\",\n \"department\": \"Sales\",\n \"spending\": 10000,\n \"budget\": 9932\n },\n {\n \"date\": \"2021-12\",\n \"department\": \"Administration\",\n \"spending\": 18033,\n \"budget\": 20000\n },\n {\n \"date\": \"2021-12\",\n \"department\": \"Finance\",\n \"spending\": 4890,\n \"budget\": 4500\n },\n {\n \"date\": \"2021-12\",\n \"department\": \"Sales\",\n \"spending\": 9322,\n \"budget\": 8000\n }\n]";
+const chartStyle= {
+ background: "linear-gradient(135deg, #72afd3 0%, #96e6a1 100%)",
+ chartBorderColor: "#FDFAFA",
+ chartBorderStyle: "solid",
+ chartBorderWidth: "2",
+ chartBoxShadow: "200",
+ chartShadowColor: "#3377FF"
+}
-const defaultEchartsJsonOption = "{\n \"xAxis\": {\n \"data\": [\n \"Day 1\",\n \"Day 2\",\n \"Day 3\",\n \"Day 4\",\n \"Day 5\"\n ]\n },\n \"data\": [\n [\n 100,\n 200,\n 50,\n 150\n ],\n [\n 120,\n 220,\n 80,\n 180\n ],\n [\n 80,\n 150,\n 60,\n 130\n ],\n [\n 130,\n 230,\n 110,\n 190\n ],\n [\n 90,\n 180,\n 70,\n 160\n ]\n ]\n}";
+const titleStyle = {
+ chartBoxShadow: "9",
+ chartFontStyle: "Italic",
+ chartShadowColor: "#FFBD01",
+ chartTextColor: "#36B389",
+ chartTextSize: "30",
+ chartTextWeight: "Bold"
+}
-const data = JSON.stringify(defaultDataSource);
-const echartsOption = JSON.stringify(defaultEchartsJsonOption);
+const xAxisStyle = {
+ chartBoxShadow: "5",
+ chartFontFamily: "serif",
+ chartFontStyle: "Italic",
+ chartShadowColor: "#020101",
+ chartTextColor: "#971827",
+ chartTextSize: "20",
+ chartTextWeight: "bold"
+}
+
+const legendStyle = {
+ chartBoxShadow: "9",
+ chartFontStyle: "Italic",
+ chartShadowColor: "#FFBD01",
+ chartTextColor: "#36B389",
+ chartTextSize: "15",
+ chartTextWeight: "Bold"
+}
export default function ThemeRiverChartExample() {
- const blackListConfig: string[] = ["data", "echartsOption", "series"];
- const series = [
- {
- "columnName": "spending",
- "seriesName": "Spending",
- "dataIndex": "f011b34c"
- },
- {
- "columnName": "budget",
- "seriesName": "Budget",
- "dataIndex": "30e02269"
- }
-];
return (
<>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
>
);
}
diff --git a/client/packages/lowcoder/src/pages/ComponentDoc/examples/ChartsComp/TreeChart.tsx b/client/packages/lowcoder/src/pages/ComponentDoc/examples/ChartsComp/TreeChart.tsx
index b0d10650f..602206f7c 100644
--- a/client/packages/lowcoder/src/pages/ComponentDoc/examples/ChartsComp/TreeChart.tsx
+++ b/client/packages/lowcoder/src/pages/ComponentDoc/examples/ChartsComp/TreeChart.tsx
@@ -6,46 +6,199 @@ import ExampleGroup from "../../common/ExampleGroup";
const ChartCompWithDefault = uiCompRegistry["treeChart"].comp;
-const defaultDataSource = "[\n {\n \"date\": \"2021-09\",\n \"department\": \"Administration\",\n \"spending\": 9003,\n \"budget\": 8000\n },\n {\n \"date\": \"2021-09\",\n \"department\": \"Finance\",\n \"spending\": 3033,\n \"budget\": 4000\n },\n {\n \"date\": \"2021-09\",\n \"department\": \"Sales\",\n \"spending\": 9230,\n \"budget\": 8000\n },\n {\n \"date\": \"2021-10\",\n \"department\": \"Administration\",\n \"spending\": 13032,\n \"budget\": 15000\n },\n {\n \"date\": \"2021-10\",\n \"department\": \"Finance\",\n \"spending\": 2300,\n \"budget\": 5000\n },\n {\n \"date\": \"2021-10\",\n \"department\": \"Sales\",\n \"spending\": 7323.5,\n \"budget\": 8000\n },\n {\n \"date\": \"2021-11\",\n \"department\": \"Administration\",\n \"spending\": 13000,\n \"budget\": 16023\n },\n {\n \"date\": \"2021-11\",\n \"department\": \"Finance\",\n \"spending\": 3569.5,\n \"budget\": 3000\n },\n {\n \"date\": \"2021-11\",\n \"department\": \"Sales\",\n \"spending\": 10000,\n \"budget\": 9932\n },\n {\n \"date\": \"2021-12\",\n \"department\": \"Administration\",\n \"spending\": 18033,\n \"budget\": 20000\n },\n {\n \"date\": \"2021-12\",\n \"department\": \"Finance\",\n \"spending\": 4890,\n \"budget\": 4500\n },\n {\n \"date\": \"2021-12\",\n \"department\": \"Sales\",\n \"spending\": 9322,\n \"budget\": 8000\n }\n]";
+const chartStyle= {
+ background: "linear-gradient(135deg, #72afd3 0%, #96e6a1 100%)",
+ chartBorderColor: "#FDFAFA",
+ chartBorderStyle: "solid",
+ chartBorderWidth: "2",
+ chartBoxShadow: "200",
+ chartShadowColor: "#3377FF"
+}
-const defaultEchartsJsonOption = "{\n \"xAxis\": {\n \"data\": [\n \"Day 1\",\n \"Day 2\",\n \"Day 3\",\n \"Day 4\",\n \"Day 5\"\n ]\n },\n \"data\": [\n [\n 100,\n 200,\n 50,\n 150\n ],\n [\n 120,\n 220,\n 80,\n 180\n ],\n [\n 80,\n 150,\n 60,\n 130\n ],\n [\n 130,\n 230,\n 110,\n 190\n ],\n [\n 90,\n 180,\n 70,\n 160\n ]\n ]\n}";
+const titleStyle = {
+ chartBoxShadow: "9",
+ chartFontStyle: "Italic",
+ chartShadowColor: "#FFBD01",
+ chartTextColor: "#36B389",
+ chartTextSize: "30",
+ chartTextWeight: "Bold"
+}
-const data = JSON.stringify(defaultDataSource);
-const echartsOption = JSON.stringify(defaultEchartsJsonOption);
+const detailStyle = {
+ chartFontFamily: "serif",
+ chartFontStyle: "Italic",
+ chartTextColor: "#7A7A7B",
+ chartTextSize: "20",
+ chartTextWeight: "bold"
+}
export default function TreeChartExample() {
- const blackListConfig: string[] = ["data", "echartsOption", "series"];
- const series = [
- {
- "columnName": "spending",
- "seriesName": "Spending",
- "dataIndex": "f011b34c"
- },
- {
- "columnName": "budget",
- "seriesName": "Budget",
- "dataIndex": "30e02269"
- }
-];
return (
<>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
>
);
}
diff --git a/client/packages/lowcoder/src/pages/ComponentDoc/examples/ChartsComp/TreemapChart.tsx b/client/packages/lowcoder/src/pages/ComponentDoc/examples/ChartsComp/TreemapChart.tsx
index 35fdc1804..0971b5ef0 100644
--- a/client/packages/lowcoder/src/pages/ComponentDoc/examples/ChartsComp/TreemapChart.tsx
+++ b/client/packages/lowcoder/src/pages/ComponentDoc/examples/ChartsComp/TreemapChart.tsx
@@ -6,46 +6,164 @@ import ExampleGroup from "../../common/ExampleGroup";
const ChartCompWithDefault = uiCompRegistry["treemapChart"].comp;
-const defaultDataSource = "[\n {\n \"date\": \"2021-09\",\n \"department\": \"Administration\",\n \"spending\": 9003,\n \"budget\": 8000\n },\n {\n \"date\": \"2021-09\",\n \"department\": \"Finance\",\n \"spending\": 3033,\n \"budget\": 4000\n },\n {\n \"date\": \"2021-09\",\n \"department\": \"Sales\",\n \"spending\": 9230,\n \"budget\": 8000\n },\n {\n \"date\": \"2021-10\",\n \"department\": \"Administration\",\n \"spending\": 13032,\n \"budget\": 15000\n },\n {\n \"date\": \"2021-10\",\n \"department\": \"Finance\",\n \"spending\": 2300,\n \"budget\": 5000\n },\n {\n \"date\": \"2021-10\",\n \"department\": \"Sales\",\n \"spending\": 7323.5,\n \"budget\": 8000\n },\n {\n \"date\": \"2021-11\",\n \"department\": \"Administration\",\n \"spending\": 13000,\n \"budget\": 16023\n },\n {\n \"date\": \"2021-11\",\n \"department\": \"Finance\",\n \"spending\": 3569.5,\n \"budget\": 3000\n },\n {\n \"date\": \"2021-11\",\n \"department\": \"Sales\",\n \"spending\": 10000,\n \"budget\": 9932\n },\n {\n \"date\": \"2021-12\",\n \"department\": \"Administration\",\n \"spending\": 18033,\n \"budget\": 20000\n },\n {\n \"date\": \"2021-12\",\n \"department\": \"Finance\",\n \"spending\": 4890,\n \"budget\": 4500\n },\n {\n \"date\": \"2021-12\",\n \"department\": \"Sales\",\n \"spending\": 9322,\n \"budget\": 8000\n }\n]";
+const chartStyle= {
+ background: "linear-gradient(135deg, #72afd3 0%, #96e6a1 100%)",
+ chartBorderColor: "#FDFAFA",
+ chartBorderStyle: "solid",
+ chartBorderWidth: "2",
+ chartBoxShadow: "200",
+ chartShadowColor: "#3377FF"
+}
-const defaultEchartsJsonOption = "{\n \"xAxis\": {\n \"data\": [\n \"Day 1\",\n \"Day 2\",\n \"Day 3\",\n \"Day 4\",\n \"Day 5\"\n ]\n },\n \"data\": [\n [\n 100,\n 200,\n 50,\n 150\n ],\n [\n 120,\n 220,\n 80,\n 180\n ],\n [\n 80,\n 150,\n 60,\n 130\n ],\n [\n 130,\n 230,\n 110,\n 190\n ],\n [\n 90,\n 180,\n 70,\n 160\n ]\n ]\n}";
+const titleStyle = {
+ chartBoxShadow: "9",
+ chartFontStyle: "Italic",
+ chartShadowColor: "#FFBD01",
+ chartTextColor: "#36B389",
+ chartTextSize: "30",
+ chartTextWeight: "Bold"
+}
-const data = JSON.stringify(defaultDataSource);
-const echartsOption = JSON.stringify(defaultEchartsJsonOption);
+const detailStyle = {
+ chartFontFamily: "serif",
+ chartFontStyle: "Italic",
+ chartTextColor: "#fff",
+ chartTextSize: "20",
+ chartTextWeight: "bold"
+}
export default function TreemapChartExample() {
- const blackListConfig: string[] = ["data", "echartsOption", "series"];
- const series = [
- {
- "columnName": "spending",
- "seriesName": "Spending",
- "dataIndex": "f011b34c"
- },
- {
- "columnName": "budget",
- "seriesName": "Budget",
- "dataIndex": "30e02269"
- }
-];
return (
<>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
>
);
}
diff --git a/client/packages/lowcoder/src/pages/ComponentDoc/examples/ContainersComp/CollapsibleContainer.tsx b/client/packages/lowcoder/src/pages/ComponentDoc/examples/ContainersComp/CollapsibleContainer.tsx
new file mode 100644
index 000000000..f7fb4d23c
--- /dev/null
+++ b/client/packages/lowcoder/src/pages/ComponentDoc/examples/ContainersComp/CollapsibleContainer.tsx
@@ -0,0 +1,441 @@
+import { ContainerComp } from "comps/comps/containerComp/containerComp";
+import { trans } from "i18n";
+import { chartColorPalette } from "lowcoder-design";
+import Example from "../../common/Example";
+import ExampleGroup from "../../common/ExampleGroup";
+
+const container = {
+ "header": {
+ "layout": {
+ "fedaa62": {
+ "i": "fedaa62",
+ "h": 5,
+ "w": 6,
+ "x": 0,
+ "y": 0
+ },
+ "5661db3a": {
+ "i": "5661db3a",
+ "h": 5,
+ "w": 10,
+ "x": 14,
+ "y": 0
+ }
+ },
+ "items": {
+ "fedaa62": {
+ "compType": "text",
+ "comp": {
+ "text": "## Personal Details",
+ "autoHeight": "auto",
+ "type": "markdown",
+ "horizontalAlignment": "left",
+ "contentScrollBar": true,
+ "verticalAlignment": "center",
+ "style": {
+ "background": "#F5F5F6",
+ "margin": "3px",
+ "padding": "3px",
+ "text": "#222222",
+ "textSize": "14px",
+ "border": "#D7D9E0",
+ "borderStyle": "solid",
+ "radius": "4px",
+ "borderWidth": "0",
+ "lineHeight": "18px",
+ "links": "#3377FF"
+ },
+ "margin": {
+ "left": "",
+ "right": "",
+ "top": "",
+ "bottom": ""
+ },
+ "padding": {
+ "left": "",
+ "right": "",
+ "top": "",
+ "bottom": ""
+ },
+ "preventStyleOverwriting": false,
+ "appliedThemeId": "default-theme-id",
+ "version": "latest"
+ },
+ "name": "text6"
+ },
+ "5661db3a": {
+ "compType": "toggleButton",
+ "comp": {
+ "value": "true",
+ "showText": false,
+ "trueText": "Hide",
+ "falseText": "Show",
+ "trueIcon": "/icon:solid/AngleUp",
+ "falseIcon": "/icon:solid/AngleDown",
+ "iconPosition": "right",
+ "alignment": "right",
+ "style": {
+ "background": "#F5F5F6",
+ "margin": "3px",
+ "padding": "3px",
+ "text": "#222222",
+ "textSize": "14px",
+ "border": "#D7D9E0",
+ "borderStyle": "solid",
+ "radius": "4px",
+ "borderWidth": "1px",
+ "lineHeight": "18px"
+ },
+ "showBorder": false,
+ "preventStyleOverwriting": false,
+ "appliedThemeId": "default-theme-id",
+ "version": "latest"
+ },
+ "name": "toggleButton3"
+ }
+ }
+ },
+ "body": {
+ "0": {
+ "view": {
+ "layout": {
+ "c93dc520": {
+ "i": "c93dc520",
+ "h": 7,
+ "w": 10,
+ "x": 0,
+ "y": 0,
+ "pos": 0
+ },
+ "54dd6cc": {
+ "i": "54dd6cc",
+ "h": 10,
+ "w": 10,
+ "x": 14,
+ "y": 0,
+ "pos": 5
+ },
+ "aa36926a": {
+ "i": "aa36926a",
+ "h": 7,
+ "w": 10,
+ "x": 0,
+ "y": 7,
+ "pos": 1
+ },
+ "fc179ca5": {
+ "i": "fc179ca5",
+ "h": 7,
+ "w": 10,
+ "x": 14,
+ "y": 14,
+ "pos": 4
+ },
+ "99d1503e": {
+ "i": "99d1503e",
+ "h": 7,
+ "w": 10,
+ "x": 0,
+ "y": 14,
+ "pos": 6
+ }
+ },
+ "items": {
+ "c93dc520": {
+ "compType": "input",
+ "comp": {
+ "defaultValue": "",
+ "value": "",
+ "label": {
+ "text": "Full Name",
+ "width": "33",
+ "widthUnit": "%",
+ "position": "row",
+ "align": "left"
+ },
+ "placeholder": "Full name",
+ "required": true,
+ "validationType": "Text",
+ "style": {
+ "background": "#00000000",
+ "border": "#D7D9E0",
+ "margin": "3px",
+ "padding": "3px",
+ "borderStyle": "solid",
+ "radius": "4px",
+ "borderWidth": "0px",
+ "opacity": "1"
+ },
+ "labelStyle": {
+ "margin": "3px",
+ "padding": "3px",
+ "label": "#222222",
+ "textSize": "14px",
+ "border": "#D7D9E0",
+ "borderStyle": "solid",
+ "borderWidth": "0px",
+ "accent": "#3377FF"
+ },
+ "prefixIcon": "/icon:solid/file-lines",
+ "inputFieldStyle": {
+ "margin": "3px",
+ "padding": "3px",
+ "text": "#222222",
+ "textSize": "14px",
+ "border": "#D7D9E0",
+ "borderStyle": "solid",
+ "radius": "4px",
+ "borderWidth": "1px",
+ "accent": "#3377FF"
+ },
+ "preventStyleOverwriting": false,
+ "appliedThemeId": "default-theme-id",
+ "version": "latest"
+ },
+ "name": "input1"
+ },
+ "aa36926a": {
+ "compType": "input",
+ "comp": {
+ "defaultValue": "",
+ "value": "",
+ "label": {
+ "text": "Email",
+ "width": "33",
+ "widthUnit": "%",
+ "position": "row",
+ "align": "left"
+ },
+ "placeholder": "Email Address",
+ "required": true,
+ "validationType": "Email",
+ "style": {
+ "background": "#00000000",
+ "border": "#D7D9E0",
+ "margin": "3px",
+ "padding": "3px",
+ "borderStyle": "solid",
+ "radius": "4px",
+ "borderWidth": "0px",
+ "opacity": "1"
+ },
+ "labelStyle": {
+ "margin": "3px",
+ "padding": "3px",
+ "label": "#222222",
+ "textSize": "14px",
+ "border": "#D7D9E0",
+ "borderStyle": "solid",
+ "borderWidth": "0px",
+ "accent": "#3377FF"
+ },
+ "prefixIcon": "/icon:solid/inbox",
+ "inputFieldStyle": {
+ "margin": "3px",
+ "padding": "3px",
+ "text": "#222222",
+ "textSize": "14px",
+ "border": "#D7D9E0",
+ "borderStyle": "solid",
+ "radius": "4px",
+ "borderWidth": "1px",
+ "accent": "#3377FF"
+ },
+ "preventStyleOverwriting": false,
+ "appliedThemeId": "default-theme-id",
+ "version": "latest"
+ },
+ "name": "input2"
+ },
+ "54dd6cc": {
+ "compType": "radio",
+ "comp": {
+ "defaultValue": "1",
+ "value": "",
+ "label": {
+ "text": "Gender",
+ "width": "33",
+ "widthUnit": "%",
+ "position": "row",
+ "align": "left"
+ },
+ "options": {
+ "optionType": "manual",
+ "manual": {
+ "manual": [
+ {
+ "value": "1",
+ "label": "Male"
+ },
+ {
+ "value": "2",
+ "label": "Female"
+ }
+ ]
+ },
+ "mapData": {
+ "data": "[]"
+ }
+ },
+ "style": {
+ "background": "#00000000",
+ "border": "#D7D9E0",
+ "margin": "3px",
+ "padding": "3px",
+ "borderStyle": "solid",
+ "radius": "4px",
+ "borderWidth": "0px",
+ "opacity": "1"
+ },
+ "labelStyle": {
+ "margin": "3px",
+ "padding": "3px",
+ "label": "#222222",
+ "textSize": "14px",
+ "border": "#D7D9E0",
+ "borderStyle": "solid",
+ "borderWidth": "0px",
+ "accent": "#3377FF"
+ },
+ "layout": "horizontal",
+ "inputFieldStyle": {
+ "margin": "3px",
+ "padding": "3px",
+ "staticText": "#222222",
+ "textSize": "14px",
+ "borderStyle": "solid",
+ "borderWidth": "1px",
+ "checkedBackground": "#3377FF",
+ "uncheckedBorder": "#D7D9E0",
+ "checkedBorder": "#3377FF"
+ },
+ "preventStyleOverwriting": false,
+ "appliedThemeId": "default-theme-id",
+ "version": "latest"
+ },
+ "name": "radio1"
+ },
+ "fc179ca5": {
+ "compType": "date",
+ "comp": {
+ "defaultValue": "",
+ "value": "",
+ "userTimeZone": "Europe/Madrid",
+ "label": {
+ "text": "DOB",
+ "width": "33",
+ "widthUnit": "%",
+ "position": "row",
+ "align": "left"
+ },
+ "placeholder": "Select Date",
+ "inputFormat": "YYYY-MM-DD",
+ "style": {
+ "background": "#00000000",
+ "border": "#D7D9E0",
+ "margin": "3px",
+ "padding": "3px",
+ "borderStyle": "solid",
+ "radius": "4px",
+ "borderWidth": "0px",
+ "opacity": "1"
+ },
+ "labelStyle": {
+ "margin": "3px",
+ "padding": "3px",
+ "label": "#222222",
+ "textSize": "14px",
+ "border": "#D7D9E0",
+ "borderStyle": "solid",
+ "borderWidth": "0px"
+ },
+ "suffixIcon": "/icon:regular/calendar",
+ "minDate": "1960-01-01",
+ "maxDate": "2010-12-31",
+ "inputFieldStyle": {
+ "border": "#D7D9E0",
+ "radius": "4px",
+ "text": "#222222",
+ "margin": "3px",
+ "padding": "3px",
+ "borderStyle": "solid",
+ "borderWidth": "1px",
+ "accent": "#3377FF"
+ },
+ "timeZone": "Europe/Madrid",
+ "preventStyleOverwriting": false,
+ "appliedThemeId": "default-theme-id",
+ "version": "latest"
+ },
+ "name": "date1"
+ },
+ "99d1503e": {
+ "compType": "numberInput",
+ "comp": {
+ "defaultValue": "",
+ "value": "",
+ "placeholder": "+449827222541",
+ "label": {
+ "text": "Phone #",
+ "width": "33",
+ "widthUnit": "%",
+ "position": "row",
+ "align": "left"
+ },
+ "formatter": "standard",
+ "step": "",
+ "controls": false,
+ "thousandsSeparator": false,
+ "prefixText": "",
+ "preventStyleOverwriting": false,
+ "appliedThemeId": "default-theme-id",
+ "version": "latest"
+ },
+ "name": "numberInput1"
+ }
+ }
+ }
+ }
+ },
+ "footer": {
+ "layout": {}
+ },
+ "showHeader": true,
+ "showBody": true,
+ "autoHeight": "auto",
+ "showVerticalScrollbar": false,
+ "horizontalGridCells": 24,
+ "scrollbars": false,
+ "style": {
+ "border": "#D7D9E0",
+ "background": "#FFFFFF",
+ "radius": "4px",
+ "borderWidth": "1px",
+ "borderStyle": "solid",
+ "margin": "3px",
+ "padding": "3px"
+ },
+ "appliedThemeId": "default-theme-id"
+};
+
+export default function CollapsibleContainerExample() {
+ return (
+ <>
+
+
+
+ >
+ );
+}
\ No newline at end of file
diff --git a/client/packages/lowcoder/src/pages/ComponentDoc/examples/ContainersComp/ColumnLayout.tsx b/client/packages/lowcoder/src/pages/ComponentDoc/examples/ContainersComp/ColumnLayout.tsx
index e6a59383c..b86f4ce3b 100644
--- a/client/packages/lowcoder/src/pages/ComponentDoc/examples/ContainersComp/ColumnLayout.tsx
+++ b/client/packages/lowcoder/src/pages/ComponentDoc/examples/ContainersComp/ColumnLayout.tsx
@@ -3,268 +3,235 @@ import Example from "../../common/Example";
import ExampleGroup from "../../common/ExampleGroup";
const columns={
- "manual": [
- {
- "id": 0,
- "label": "Column1",
- "key": "Column1",
- "minWidth": "",
- "background": "",
- "backgroundImage": "",
- "border": "",
- "radius": "",
- "margin": "",
- "padding": ""
- },
- {
- "id": 1,
- "label": "Column2",
- "key": "Column2",
- "minWidth": "",
- "background": "",
- "backgroundImage": "",
- "border": "",
- "radius": "",
- "margin": "",
- "padding": ""
- },
- {
- "id": 2,
- "label": "Add Column1",
- "key": "Add Column1",
- "minWidth": "",
- "background": "",
- "backgroundImage": "",
- "border": "",
- "radius": "",
- "margin": "",
- "padding": ""
- },
- {
- "id": 3,
- "label": "Add Column2",
- "key": "Add Column2",
- "minWidth": "",
- "background": "",
- "backgroundImage": "",
- "border": "",
- "radius": "",
- "margin": "",
- "padding": ""
- },
- {
- "id": 4,
- "label": "Add Column3",
- "key": "Add Column3",
- "minWidth": "",
- "background": "",
- "backgroundImage": "",
- "border": "",
- "radius": "",
- "margin": "",
- "padding": ""
- },
- {
- "id": 5,
- "label": "Add Column4",
- "key": "Add Column4",
- "minWidth": "",
- "background": "",
- "backgroundImage": "",
- "border": "",
- "radius": "",
- "margin": "",
- "padding": ""
- }
- ]
+ "manual": [
+ {
+ "id": 0,
+ "label": "Column1",
+ "key": "Column1",
+ "minWidth": "",
+ "background": "",
+ "backgroundImage": "",
+ "border": "",
+ "radius": "",
+ "margin": "",
+ "padding": ""
+ },
+ {
+ "id": 1,
+ "label": "Column2",
+ "key": "Column2",
+ "minWidth": "",
+ "background": "",
+ "backgroundImage": "",
+ "border": "",
+ "radius": "",
+ "margin": "",
+ "padding": ""
+ },
+ {
+ "id": 2,
+ "label": "Add Column1",
+ "key": "Add Column1",
+ "minWidth": "",
+ "background": "",
+ "backgroundImage": "",
+ "border": "",
+ "radius": "",
+ "margin": "",
+ "padding": ""
+ },
+ {
+ "id": 3,
+ "label": "Add Column2",
+ "key": "Add Column2",
+ "minWidth": "",
+ "background": "",
+ "backgroundImage": "",
+ "border": "",
+ "radius": "",
+ "margin": "",
+ "padding": ""
+ }
+ ]
};
const container={
"0": {
"layout": {
- "d131aa12": {
- "i": "d131aa12",
+ "164dcb77": {
+ "i": "164dcb77",
"h": 6,
- "w": 17,
- "x": 4,
- "y": 5,
- "pos": 1
+ "w": 14,
+ "x": 5,
+ "y": 4,
+ "pos": 0
}
},
"items": {
- "d131aa12": {
- "compType": "progress",
+ "164dcb77": {
+ "compType": "text",
"comp": {
- "value": "60",
+ "text": "### Row1, Column1",
+ "autoHeight": "auto",
+ "type": "markdown",
+ "horizontalAlignment": "center",
+ "contentScrollBar": true,
+ "verticalAlignment": "center",
+ "margin": {
+ "left": "",
+ "right": "",
+ "top": "",
+ "bottom": ""
+ },
+ "padding": {
+ "left": "",
+ "right": "",
+ "top": "",
+ "bottom": ""
+ },
"preventStyleOverwriting": false,
"appliedThemeId": "",
"version": "latest"
},
- "name": "progress1"
+ "name": "text1"
}
}
},
"1": {
"layout": {
- "e193cd76": {
- "i": "e193cd76",
+ "6e4f0687": {
+ "i": "6e4f0687",
"h": 6,
- "w": 24,
- "x": 0,
- "y": 5,
+ "w": 14,
+ "x": 5,
+ "y": 4,
"pos": 0
}
},
"items": {
- "e193cd76": {
- "compType": "button",
+ "6e4f0687": {
+ "compType": "text",
"comp": {
- "text": "Button",
- "type": "",
- "form": "",
+ "text": "### Row1, Column2",
+ "autoHeight": "auto",
+ "type": "markdown",
+ "horizontalAlignment": "center",
+ "contentScrollBar": true,
+ "verticalAlignment": "center",
+ "margin": {
+ "left": "",
+ "right": "",
+ "top": "",
+ "bottom": ""
+ },
+ "padding": {
+ "left": "",
+ "right": "",
+ "top": "",
+ "bottom": ""
+ },
"preventStyleOverwriting": false,
"appliedThemeId": "",
"version": "latest"
},
- "name": "button1"
+ "name": "text3"
}
}
},
"2": {
"layout": {
- "1d3eac41": {
- "i": "1d3eac41",
- "h": 7,
- "w": 21,
- "x": 1,
- "y": 5,
+ "b47baba7": {
+ "i": "b47baba7",
+ "h": 6,
+ "w": 14,
+ "x": 5,
+ "y": 4,
"pos": 0
}
},
"items": {
- "1d3eac41": {
- "compType": "switch",
+ "b47baba7": {
+ "compType": "text",
"comp": {
- "defaultValue": "",
- "value": "",
- "label": {
- "text": "Switch",
- "width": "33",
- "widthUnit": "%",
- "position": "row",
- "align": "left"
+ "text": "### Row2, Column1",
+ "autoHeight": "auto",
+ "type": "markdown",
+ "horizontalAlignment": "center",
+ "contentScrollBar": true,
+ "verticalAlignment": "center",
+ "margin": {
+ "left": "",
+ "right": "",
+ "top": "",
+ "bottom": ""
+ },
+ "padding": {
+ "left": "",
+ "right": "",
+ "top": "",
+ "bottom": ""
},
"preventStyleOverwriting": false,
"appliedThemeId": "",
"version": "latest"
},
- "name": "switch1"
+ "name": "text2"
}
}
},
"3": {
"layout": {
- "5853c1f5": {
- "i": "5853c1f5",
- "h": 20,
- "w": 15,
- "x": 5,
- "y": 0,
- "pos": 0
- }
- },
- "items": {
- "5853c1f5": {
- "compType": "progressCircle",
- "comp": {
- "value": "60",
- "preventStyleOverwriting": false,
- "appliedThemeId": "",
- "version": "latest"
- },
- "name": "progressCircle1"
- }
- }
- },
- "4": {
- "layout": {
- "68b3d00f": {
- "i": "68b3d00f",
+ "ce02a8ee": {
+ "i": "ce02a8ee",
"h": 6,
- "w": 23,
- "x": 1,
- "y": 7,
- "pos": 0
- }
- },
- "items": {
- "68b3d00f": {
- "compType": "button",
- "comp": {
- "text": "Button",
- "type": "",
- "form": "",
- "preventStyleOverwriting": false,
- "appliedThemeId": "",
- "version": "latest"
- },
- "name": "button2"
- }
- }
- },
- "5": {
- "layout": {
- "307f8e6b": {
- "i": "307f8e6b",
- "h": 10,
- "w": 24,
- "x": 0,
- "y": 6,
+ "w": 14,
+ "x": 5,
+ "y": 3,
"pos": 0
}
},
"items": {
- "307f8e6b": {
- "compType": "checkbox",
+ "ce02a8ee": {
+ "compType": "text",
"comp": {
- "defaultValue": "",
- "value": "",
- "label": {
- "text": "Check box",
- "width": "33",
- "widthUnit": "%",
- "position": "row",
- "align": "left"
- },
- "options": {
- "optionType": "manual",
- "manual": {
- "manual": [
- {
- "value": "1",
- "label": "Option 1"
- },
- {
- "value": "2",
- "label": "Option 2"
- }
- ]
- },
- "mapData": {
- "data": "[]"
- }
+ "text": "### Row2, Column2",
+ "autoHeight": "auto",
+ "type": "markdown",
+ "horizontalAlignment": "center",
+ "contentScrollBar": true,
+ "verticalAlignment": "center",
+ "margin": {
+ "left": "",
+ "right": "",
+ "top": "",
+ "bottom": ""
+ },
+ "padding": {
+ "left": "",
+ "right": "",
+ "top": "",
+ "bottom": ""
},
- "layout": "horizontal",
"preventStyleOverwriting": false,
"appliedThemeId": "",
"version": "latest"
},
- "name": "checkbox1"
+ "name": "text4"
}
}
}
};
+const columnStyle = {
+ "background": "linear-gradient(45deg, #d53369 0%, #daae51 100%)",
+ "border": "#222222",
+ "padding": "0px"
+};
+
+const style= {
+ "background": "linear-gradient(135deg, #FFFFFF 0%, rgba(255, 255, 255, 1) 100%)"
+};
+
export default function ColumnLayoutExample() {
return (
<>
@@ -275,20 +242,31 @@ export default function ColumnLayoutExample() {
@@ -299,48 +277,865 @@ export default function ColumnLayoutExample() {
description="The Following Examples Show the Column Layout options on Column Layout Component."
>
diff --git a/client/packages/lowcoder/src/pages/ComponentDoc/examples/ContainersComp/FloatTextContainer.tsx b/client/packages/lowcoder/src/pages/ComponentDoc/examples/ContainersComp/FloatTextContainer.tsx
new file mode 100644
index 000000000..7a1578773
--- /dev/null
+++ b/client/packages/lowcoder/src/pages/ComponentDoc/examples/ContainersComp/FloatTextContainer.tsx
@@ -0,0 +1,120 @@
+import { ContainerComp } from "comps/comps/containerComp/containerComp";
+import { trans } from "i18n";
+import { chartColorPalette } from "lowcoder-design";
+import Example from "../../common/Example";
+import ExampleGroup from "../../common/ExampleGroup";
+
+const container = {
+ "header": {
+ "layout": {
+ "f1e0a72f": {
+ "i": "f1e0a72f",
+ "h": 5,
+ "w": 24,
+ "x": 0,
+ "y": 0
+ }
+ },
+ "items": {
+ "f1e0a72f": {
+ "compType": "text",
+ "comp": {
+ "text": "### Displayed Container Title",
+ "autoHeight": "auto",
+ "type": "markdown",
+ "horizontalAlignment": "left",
+ "contentScrollBar": true,
+ "verticalAlignment": "center",
+ "margin": {
+ "left": "",
+ "right": "",
+ "top": "",
+ "bottom": ""
+ },
+ "padding": {
+ "left": "",
+ "right": "",
+ "top": "",
+ "bottom": ""
+ },
+ "preventStyleOverwriting": false,
+ "appliedThemeId": "",
+ "version": "latest"
+ },
+ "name": "containerTitle1"
+ }
+ }
+ },
+ "body": {
+ "0": {
+ "view": {
+ "layout": {
+ "e13e96e1": {
+ "i": "e13e96e1",
+ "h": 20,
+ "w": 17,
+ "x": 3,
+ "y": 1,
+ "pos": 0
+ }
+ },
+ "items": {
+ "e13e96e1": {
+ "compType": "image",
+ "comp": {
+ "src": "https://temp.im/350x400",
+ "autoHeight": "fixed",
+ "restrictPaddingOnRotation": "image",
+ "preventStyleOverwriting": false,
+ "appliedThemeId": "",
+ "version": "latest"
+ },
+ "name": "image1"
+ }
+ }
+ }
+ }
+ },
+ "footer": {
+ "layout": {}
+ },
+ "showHeader": true,
+ "showBody": true,
+ "showFooter": true,
+ "autoHeight": "auto",
+ "showVerticalScrollbar": false,
+ "horizontalGridCells": 24,
+ "scrollbars": false,
+ "style": {
+ "borderWidth": "1px"
+ },
+ "appliedThemeId": ""
+};
+
+const text ="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi feugiat faucibus eleifend. Pellentesque eleifend, risus vel sagittis mattis, mauris ipsum tempor sapien, eu lobortis lacus libero a dui. Cras erat felis, rhoncus vestibulum consectetur et, ultrices ut purus. Sed a tortor orci. Vestibulum nec eleifend ante.";
+
+export default function FloatTextContainerExample() {
+ return (
+ <>
+
+
+
+ >
+ );
+}
\ No newline at end of file
diff --git a/client/packages/lowcoder/src/pages/ComponentDoc/examples/ContainersComp/ResponsiveLayout.tsx b/client/packages/lowcoder/src/pages/ComponentDoc/examples/ContainersComp/ResponsiveLayout.tsx
index 926c916df..23152d129 100644
--- a/client/packages/lowcoder/src/pages/ComponentDoc/examples/ContainersComp/ResponsiveLayout.tsx
+++ b/client/packages/lowcoder/src/pages/ComponentDoc/examples/ContainersComp/ResponsiveLayout.tsx
@@ -2,6 +2,341 @@ import { ResponsiveLayoutComp } from "comps/comps/responsiveLayout/responsiveLay
import Example from "../../common/Example";
import ExampleGroup from "../../common/ExampleGroup";
+const container= {
+ "0": {
+ "layout": {
+ "2c8159fd": {
+ "i": "2c8159fd",
+ "h": 23,
+ "w": 24,
+ "x": 0,
+ "y": 0,
+ "pos": 0
+ }
+ },
+ "items": {
+ "2c8159fd": {
+ "compType": "text",
+ "comp": {
+ "text": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus vehicula quis justo et ornare.",
+ "autoHeight": "auto",
+ "type": "markdown",
+ "horizontalAlignment": "left",
+ "contentScrollBar": true,
+ "verticalAlignment": "center",
+ "margin": {
+ "left": "",
+ "right": "",
+ "top": "",
+ "bottom": ""
+ },
+ "padding": {
+ "left": "",
+ "right": "",
+ "top": "",
+ "bottom": ""
+ },
+ "preventStyleOverwriting": false,
+ "appliedThemeId": "",
+ "version": "latest"
+ },
+ "name": "text1"
+ }
+ }
+ },
+ "1": {
+ "layout": {
+ "6b3372d7": {
+ "i": "6b3372d7",
+ "h": 26,
+ "w": 24,
+ "x": 0,
+ "y": 0,
+ "pos": 0
+ }
+ },
+ "items": {
+ "6b3372d7": {
+ "compType": "text",
+ "comp": {
+ "text": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus vehicula quis justo et ornare. Pellentesque aliquet libero id scelerisque dapibus. Integer tristique risus a nisl facilisis, vel tincidunt risus venenatis. Ut ut sapien velit. Nunc hendrerit nisi non magna consectetur ullamcorper. ",
+ "autoHeight": "auto",
+ "type": "markdown",
+ "horizontalAlignment": "left",
+ "contentScrollBar": true,
+ "verticalAlignment": "center",
+ "margin": {
+ "left": "",
+ "right": "",
+ "top": "",
+ "bottom": ""
+ },
+ "padding": {
+ "left": "",
+ "right": "",
+ "top": "",
+ "bottom": ""
+ },
+ "preventStyleOverwriting": false,
+ "appliedThemeId": "",
+ "version": "latest"
+ },
+ "name": "text4"
+ }
+ }
+ },
+ "2": {
+ "layout": {
+ "fb172507": {
+ "i": "fb172507",
+ "h": 30,
+ "w": 24,
+ "x": 0,
+ "y": 0,
+ "pos": 0
+ }
+ },
+ "items": {
+ "fb172507": {
+ "compType": "text",
+ "comp": {
+ "text": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus vehicula quis justo et ornare.",
+ "autoHeight": "auto",
+ "type": "markdown",
+ "horizontalAlignment": "left",
+ "contentScrollBar": true,
+ "verticalAlignment": "center",
+ "margin": {
+ "left": "",
+ "right": "",
+ "top": "",
+ "bottom": ""
+ },
+ "padding": {
+ "left": "",
+ "right": "",
+ "top": "",
+ "bottom": ""
+ },
+ "preventStyleOverwriting": false,
+ "appliedThemeId": "",
+ "version": "latest"
+ },
+ "name": "text2"
+ }
+ }
+ },
+ "3": {
+ "layout": {
+ "b66b7903": {
+ "i": "b66b7903",
+ "h": 33,
+ "w": 24,
+ "x": 0,
+ "y": 0,
+ "pos": 0
+ }
+ },
+ "items": {
+ "b66b7903": {
+ "compType": "text",
+ "comp": {
+ "text": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus vehicula quis justo et ornare. Pellentesque aliquet libero id scelerisque dapibus. Integer tristique risus a nisl facilisis, vel tincidunt risus venenatis. Ut ut sapien velit. Nunc hendrerit nisi non magna consectetur ullamcorper. ",
+ "autoHeight": "auto",
+ "type": "markdown",
+ "horizontalAlignment": "left",
+ "contentScrollBar": true,
+ "verticalAlignment": "center",
+ "margin": {
+ "left": "",
+ "right": "",
+ "top": "",
+ "bottom": ""
+ },
+ "padding": {
+ "left": "",
+ "right": "",
+ "top": "",
+ "bottom": ""
+ },
+ "preventStyleOverwriting": false,
+ "appliedThemeId": "",
+ "version": "latest"
+ },
+ "name": "text5"
+ }
+ }
+ },
+ "4": {
+ "layout": {
+ "43127fff": {
+ "i": "43127fff",
+ "h": 26,
+ "w": 24,
+ "x": 0,
+ "y": 2,
+ "pos": 0
+ }
+ },
+ "items": {
+ "43127fff": {
+ "compType": "text",
+ "comp": {
+ "text": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus vehicula quis justo et ornare.",
+ "autoHeight": "auto",
+ "type": "markdown",
+ "horizontalAlignment": "left",
+ "contentScrollBar": true,
+ "verticalAlignment": "center",
+ "margin": {
+ "left": "",
+ "right": "",
+ "top": "",
+ "bottom": ""
+ },
+ "padding": {
+ "left": "",
+ "right": "",
+ "top": "",
+ "bottom": ""
+ },
+ "preventStyleOverwriting": false,
+ "appliedThemeId": "",
+ "version": "latest"
+ },
+ "name": "text3"
+ }
+ }
+ },
+ "5": {
+ "layout": {
+ "8274cd26": {
+ "i": "8274cd26",
+ "h": 33,
+ "w": 24,
+ "x": 0,
+ "y": 0,
+ "pos": 0
+ }
+ },
+ "items": {
+ "8274cd26": {
+ "compType": "text",
+ "comp": {
+ "text": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus vehicula quis justo et ornare. Pellentesque aliquet libero id scelerisque dapibus. Integer tristique risus a nisl facilisis, vel tincidunt risus venenatis. Ut ut sapien velit. Nunc hendrerit nisi non magna consectetur ullamcorper. ",
+ "autoHeight": "auto",
+ "type": "markdown",
+ "horizontalAlignment": "left",
+ "contentScrollBar": true,
+ "verticalAlignment": "center",
+ "margin": {
+ "left": "",
+ "right": "",
+ "top": "",
+ "bottom": ""
+ },
+ "padding": {
+ "left": "",
+ "right": "",
+ "top": "",
+ "bottom": ""
+ },
+ "preventStyleOverwriting": false,
+ "appliedThemeId": "",
+ "version": "latest"
+ },
+ "name": "text6"
+ }
+ }
+ }
+};
+
+const column= {
+ "manual": [
+ {
+ "id": 0,
+ "label": "Column1",
+ "key": "Column1",
+ "minWidth": "",
+ "background": "",
+ "backgroundImage": "",
+ "border": "",
+ "radius": "",
+ "margin": "",
+ "padding": ""
+ },
+ {
+ "id": 1,
+ "label": "Column2",
+ "key": "Column2",
+ "minWidth": "",
+ "background": "",
+ "backgroundImage": "",
+ "border": "",
+ "radius": "",
+ "margin": "",
+ "padding": ""
+ },
+ {
+ "id": 2,
+ "label": "Column3",
+ "key": "Column3",
+ "minWidth": "",
+ "background": "",
+ "backgroundImage": "",
+ "border": "",
+ "radius": "",
+ "margin": "",
+ "padding": ""
+ },
+ {
+ "id": 3,
+ "label": "Column4",
+ "key": "Column4",
+ "minWidth": "",
+ "background": "",
+ "backgroundImage": "",
+ "border": "",
+ "radius": "",
+ "margin": "",
+ "padding": ""
+ },
+ {
+ "id": 4,
+ "label": "Column5",
+ "key": "Column5",
+ "minWidth": "",
+ "background": "",
+ "backgroundImage": "",
+ "border": "",
+ "radius": "",
+ "margin": "",
+ "padding": ""
+ },
+ {
+ "id": 5,
+ "label": "Column6",
+ "key": "Column6",
+ "minWidth": "",
+ "background": "",
+ "backgroundImage": "",
+ "border": "",
+ "radius": "",
+ "margin": "",
+ "padding": ""
+ }
+ ]
+};
+
+const columnStyle= {
+ "background": "linear-gradient(135deg, #FFFFFF 0%, #FFFFFF 100%)",
+ "border": "#222222"
+};
+
+const style= {
+ "background": "linear-gradient(45deg, #d53369 0%, #daae51 100%)"
+};
+
export default function ResponsiveLayoutExample() {
return (
<>
@@ -11,15 +346,29 @@ export default function ResponsiveLayoutExample() {
>
@@ -30,16 +379,43 @@ export default function ResponsiveLayoutExample() {
description="The Following Examples Show the Layout options on Component."
>
+
diff --git a/client/packages/lowcoder/src/pages/ComponentDoc/examples/ContainersComp/SplitLayout.tsx b/client/packages/lowcoder/src/pages/ComponentDoc/examples/ContainersComp/SplitLayout.tsx
new file mode 100644
index 000000000..84cade537
--- /dev/null
+++ b/client/packages/lowcoder/src/pages/ComponentDoc/examples/ContainersComp/SplitLayout.tsx
@@ -0,0 +1,214 @@
+import { SplitLayoutComp } from "comps/comps/splitLayout/splitLayout";
+import Example from "../../common/Example";
+import ExampleGroup from "../../common/ExampleGroup";
+
+const columns= {
+ "manual": [
+ {
+ "id": 0,
+ "label": "Area 1",
+ "key": "Area1",
+ "minWidth": "10%",
+ "maxWidth": "90%",
+ "width": "50%",
+ "collapsible": false,
+ "background": "",
+ "backgroundImage": "",
+ "padding": ""
+ },
+ {
+ "id": 1,
+ "label": "Area 2",
+ "key": "Area2",
+ "minWidth": "10%",
+ "maxWidth": "90%",
+ "width": "50%",
+ "collapsible": true,
+ "background": "",
+ "backgroundImage": "",
+ "padding": ""
+ },
+ {
+ "id": 2,
+ "label": "Option 1",
+ "key": "Option 1",
+ "minWidth": "10%",
+ "maxWidth": "90%",
+ "width": "50%",
+ "collapsible": false,
+ "background": "",
+ "backgroundImage": "",
+ "padding": ""
+ }
+ ]
+};
+
+const bodyStyle= {
+ background: "#FFFFFF",
+ border: "#222222",
+};
+
+const columnStyle= {
+ background: "#FFFFFF",
+ border: "#222222",
+ margin: "10px",
+};
+
+export default function SplitLayoutExample() {
+ return (
+ <>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ >
+ );
+ }
\ No newline at end of file
diff --git a/client/packages/lowcoder/src/pages/ComponentDoc/examples/MediaComp/Audio.tsx b/client/packages/lowcoder/src/pages/ComponentDoc/examples/MediaComp/Audio.tsx
index ac0b62b3c..0b68aa54d 100644
--- a/client/packages/lowcoder/src/pages/ComponentDoc/examples/MediaComp/Audio.tsx
+++ b/client/packages/lowcoder/src/pages/ComponentDoc/examples/MediaComp/Audio.tsx
@@ -7,6 +7,7 @@ export default function AudioExample() {
<>
+
+
+
+
+
+
+
+
+
+
+
diff --git a/client/packages/lowcoder/src/pages/ComponentDoc/examples/MediaComp/BPMNEditor.tsx b/client/packages/lowcoder/src/pages/ComponentDoc/examples/MediaComp/BPMNEditor.tsx
index a32d10c91..e0725ab3c 100644
--- a/client/packages/lowcoder/src/pages/ComponentDoc/examples/MediaComp/BPMNEditor.tsx
+++ b/client/packages/lowcoder/src/pages/ComponentDoc/examples/MediaComp/BPMNEditor.tsx
@@ -10,15 +10,72 @@ export default function BPMNEditorExample() {
return (
<>
+
+
+
+
+
+
+
>
);
diff --git a/client/packages/lowcoder/src/pages/ComponentDoc/examples/MediaComp/ColorPicker.tsx b/client/packages/lowcoder/src/pages/ComponentDoc/examples/MediaComp/ColorPicker.tsx
index d3db96d3c..0bedb9c43 100644
--- a/client/packages/lowcoder/src/pages/ComponentDoc/examples/MediaComp/ColorPicker.tsx
+++ b/client/packages/lowcoder/src/pages/ComponentDoc/examples/MediaComp/ColorPicker.tsx
@@ -66,6 +66,15 @@ export default function ColorPickerExample() {
}}
compFactory={ColorPickerComp}
/>
+
+
+
+
+
+
+
+
+
>
);
}
\ No newline at end of file
diff --git a/client/packages/lowcoder/src/pages/ComponentDoc/examples/MediaComp/Icons.tsx b/client/packages/lowcoder/src/pages/ComponentDoc/examples/MediaComp/Icons.tsx
index 3e6190a15..525348dcd 100644
--- a/client/packages/lowcoder/src/pages/ComponentDoc/examples/MediaComp/Icons.tsx
+++ b/client/packages/lowcoder/src/pages/ComponentDoc/examples/MediaComp/Icons.tsx
@@ -60,6 +60,138 @@ export default function IconExample() {
compFactory={IconComp}
/>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
>
);
}
\ No newline at end of file
diff --git a/client/packages/lowcoder/src/pages/ComponentDoc/examples/MediaComp/LottieAnimation.tsx b/client/packages/lowcoder/src/pages/ComponentDoc/examples/MediaComp/LottieAnimation.tsx
index 1f0dfa614..59e69d79c 100644
--- a/client/packages/lowcoder/src/pages/ComponentDoc/examples/MediaComp/LottieAnimation.tsx
+++ b/client/packages/lowcoder/src/pages/ComponentDoc/examples/MediaComp/LottieAnimation.tsx
@@ -7,6 +7,7 @@ export default function JsonLottieAnimationExample() {
<>
+
+
+
+
+
+
+
+
+
+
+
+
+
>
);
}
\ No newline at end of file
diff --git a/client/packages/lowcoder/src/pages/ComponentDoc/examples/MediaComp/Mention.tsx b/client/packages/lowcoder/src/pages/ComponentDoc/examples/MediaComp/Mention.tsx
index 9edbeb2ab..f6a05c68b 100644
--- a/client/packages/lowcoder/src/pages/ComponentDoc/examples/MediaComp/Mention.tsx
+++ b/client/packages/lowcoder/src/pages/ComponentDoc/examples/MediaComp/Mention.tsx
@@ -8,14 +8,119 @@ export default function MentionCompExample() {
<>
+
+
+
+
+
+
+
+
+
+
+
+
+
>
);
diff --git a/client/packages/lowcoder/src/pages/ComponentDoc/examples/MediaComp/QRCode.tsx b/client/packages/lowcoder/src/pages/ComponentDoc/examples/MediaComp/QRCode.tsx
index e56cda509..093c65592 100644
--- a/client/packages/lowcoder/src/pages/ComponentDoc/examples/MediaComp/QRCode.tsx
+++ b/client/packages/lowcoder/src/pages/ComponentDoc/examples/MediaComp/QRCode.tsx
@@ -7,6 +7,7 @@ export default function QRCodeExample() {
<>
+
+
+
+
+
+
+
+
+
+
+
>
);
}
\ No newline at end of file
diff --git a/client/packages/lowcoder/src/pages/ComponentDoc/examples/MediaComp/Scanner.tsx b/client/packages/lowcoder/src/pages/ComponentDoc/examples/MediaComp/Scanner.tsx
index 6cd6ef8ef..3f3b21f46 100644
--- a/client/packages/lowcoder/src/pages/ComponentDoc/examples/MediaComp/Scanner.tsx
+++ b/client/packages/lowcoder/src/pages/ComponentDoc/examples/MediaComp/Scanner.tsx
@@ -47,6 +47,54 @@ export default function ScannerExample() {
compFactory={ScannerComp}
/>
+
+
+
+
+
+
>
);
}
diff --git a/client/packages/lowcoder/src/pages/ComponentDoc/examples/MediaComp/Shape.tsx b/client/packages/lowcoder/src/pages/ComponentDoc/examples/MediaComp/Shape.tsx
index 1b5259742..ced700365 100644
--- a/client/packages/lowcoder/src/pages/ComponentDoc/examples/MediaComp/Shape.tsx
+++ b/client/packages/lowcoder/src/pages/ComponentDoc/examples/MediaComp/Shape.tsx
@@ -7,15 +7,16 @@ export default function ShapeExample() {
<>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
>
);
}
\ No newline at end of file
diff --git a/client/packages/lowcoder/src/pages/ComponentDoc/examples/MediaComp/Signature.tsx b/client/packages/lowcoder/src/pages/ComponentDoc/examples/MediaComp/Signature.tsx
index f90c7ef5d..4ca7d8dc7 100644
--- a/client/packages/lowcoder/src/pages/ComponentDoc/examples/MediaComp/Signature.tsx
+++ b/client/packages/lowcoder/src/pages/ComponentDoc/examples/MediaComp/Signature.tsx
@@ -11,6 +11,8 @@ export default function SignatureExample() {
>
+
+
+
+
+
+
+
+
+
+
+
+
+
>
);
}
\ No newline at end of file
diff --git a/client/packages/lowcoder/src/pages/ComponentDoc/examples/MediaComp/Transfer.tsx b/client/packages/lowcoder/src/pages/ComponentDoc/examples/MediaComp/Transfer.tsx
index 4b7564fac..a1b22979a 100644
--- a/client/packages/lowcoder/src/pages/ComponentDoc/examples/MediaComp/Transfer.tsx
+++ b/client/packages/lowcoder/src/pages/ComponentDoc/examples/MediaComp/Transfer.tsx
@@ -2,15 +2,221 @@ import { transferComp } from "comps/comps/transferComp";
import Example from "../../common/Example";
import ExampleGroup from "../../common/ExampleGroup";
+const items = "[\n {\n \"key\": \"1\",\n \"title\": \"Alice Jones\"\n \"description\" : \"Business Owner\"\n },\n {\n \"key\": \"2\",\n \"title\": \"James Anderson\"\n },\n {\n \"key\": \"3\",\n \"title\": \"Philip Salt\"\n },\n {\n \"key\": \"4\",\n \"title\": \"Martinez\"\n },\n {\n \"key\": \"5\",\n \"title\": \"Chris Harris\"\n },\n {\n \"key\": \"6\",\n \"title\": \"John Smith\"\n },\n {\n \"key\": \"7\",\n \"title\": \"Christina\"\n }\n]";
+
export default function TransferExample() {
return (
<>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/client/packages/lowcoder/src/pages/ComponentDoc/examples/MediaComp/Video.tsx b/client/packages/lowcoder/src/pages/ComponentDoc/examples/MediaComp/Video.tsx
index c62153911..3aa86d297 100644
--- a/client/packages/lowcoder/src/pages/ComponentDoc/examples/MediaComp/Video.tsx
+++ b/client/packages/lowcoder/src/pages/ComponentDoc/examples/MediaComp/Video.tsx
@@ -6,17 +6,38 @@ export default function VideoExample() {
return (
<>
+
+
+
+
+
+
+
+
+
+
+
>
);
}
\ No newline at end of file
diff --git a/client/packages/lowcoder/src/pages/ComponentDoc/examples/Navigation.tsx b/client/packages/lowcoder/src/pages/ComponentDoc/examples/Navigation.tsx
index b94f1a73f..c110581b6 100644
--- a/client/packages/lowcoder/src/pages/ComponentDoc/examples/Navigation.tsx
+++ b/client/packages/lowcoder/src/pages/ComponentDoc/examples/Navigation.tsx
@@ -368,7 +368,182 @@ export default function NavigationExample() {
}}
compFactory={NavComp}
/>
+
+
+
+
+
+
+
+
+
>
);
}
diff --git a/client/packages/lowcoder/src/pages/ComponentDoc/examples/index.ts b/client/packages/lowcoder/src/pages/ComponentDoc/examples/index.ts
index 007750d93..ca2388e95 100644
--- a/client/packages/lowcoder/src/pages/ComponentDoc/examples/index.ts
+++ b/client/packages/lowcoder/src/pages/ComponentDoc/examples/index.ts
@@ -94,6 +94,9 @@ import HillChartExample from "./ChartsComp/HillChart";
import BPMNEditorExample from "./MediaComp/BPMNEditor";
import ImageEditorExample from "./presentationComp/imageEditor";
import DrawerExample from "./ChartsComp/Drawer";
+import CollapsibleContainerExample from "./ContainersComp/CollapsibleContainer";
+import FloatTextContainerExample from "./ContainersComp/FloatTextContainer";
+import SplitLayoutExample from "./ContainersComp/SplitLayout";
const examples: { [key in UICompType]?: React.FunctionComponent } = {
button: ButtonExample,
@@ -191,6 +194,9 @@ const examples: { [key in UICompType]?: React.FunctionComponent } = {
bpmnEditor: BPMNEditorExample,
imageEditor: ImageEditorExample,
drawer: DrawerExample,
+ collapsibleContainer: CollapsibleContainerExample,
+ floatTextContainer: FloatTextContainerExample,
+ splitLayout: SplitLayoutExample,
};
export default examples;
diff --git a/client/packages/lowcoder/src/pages/ComponentDoc/examples/numberInputComp/NumberInput.tsx b/client/packages/lowcoder/src/pages/ComponentDoc/examples/numberInputComp/NumberInput.tsx
index 27745477d..ed6988a5a 100644
--- a/client/packages/lowcoder/src/pages/ComponentDoc/examples/numberInputComp/NumberInput.tsx
+++ b/client/packages/lowcoder/src/pages/ComponentDoc/examples/numberInputComp/NumberInput.tsx
@@ -8,7 +8,7 @@ export default function NumberInputExample() {
<>
-
-
-
+
+
+
+ title="Left- Left Alignment"
+ config={{
+ label: { position: "row" },
+ }}
+ compFactory={NumberInputComp}
+ />
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
>
);
}
diff --git a/client/packages/lowcoder/src/pages/ComponentDoc/examples/numberInputComp/Rating.tsx b/client/packages/lowcoder/src/pages/ComponentDoc/examples/numberInputComp/Rating.tsx
index 540602bf5..3736be495 100644
--- a/client/packages/lowcoder/src/pages/ComponentDoc/examples/numberInputComp/Rating.tsx
+++ b/client/packages/lowcoder/src/pages/ComponentDoc/examples/numberInputComp/Rating.tsx
@@ -37,6 +37,14 @@ export default function RatingExample() {
}}
compFactory={RatingComp}
/>
+
@@ -88,6 +96,17 @@ export default function RatingExample() {
}}
compFactory={RatingComp}
/>
+
@@ -110,6 +129,109 @@ export default function RatingExample() {
compFactory={RatingComp}
/>
+
+
+
+
+
+
+
+
+
+
+
+
>
);
}
diff --git a/client/packages/lowcoder/src/pages/ComponentDoc/examples/presentationComp/Kanban.tsx b/client/packages/lowcoder/src/pages/ComponentDoc/examples/presentationComp/Kanban.tsx
index a811f8412..40e21298b 100644
--- a/client/packages/lowcoder/src/pages/ComponentDoc/examples/presentationComp/Kanban.tsx
+++ b/client/packages/lowcoder/src/pages/ComponentDoc/examples/presentationComp/Kanban.tsx
@@ -6,16 +6,154 @@ import ExampleGroup from "../../common/ExampleGroup";
const ChartCompWithDefault = uiCompRegistry["kanban"].comp;
+const assigneeOptions = "[\n {\n \"id\": \"1\",\n \"name\": \"Nancy Davloio\"\n },\n {\n \"id\": \"2\",\n \"name\": \"Andrew Fuller\"\n },\n {\n \"id\": \"3\",\n \"name\": \"James Wilson\"\n },\n {\n \"id\": \"4\",\n \"name\": \"George Linde\"\n }\n]";
+
+const data = {
+ "optionType": "manual",
+ "manual": {
+ "manual": [
+ {
+ "label": "Task - 29001",
+ "status": "Open",
+ "summary": "Analyze customer requirements.",
+ "priority": "High",
+ "tags": "Bug, Release Bug",
+ "estimate": "0",
+ "assignee": "Nancy Davloio",
+ "rankId": "1",
+ "id": "0"
+ },
+ {
+ "label": "Task - 29002",
+ "status": "InProgress",
+ "summary": "Add responsive support to applicaton",
+ "priority": "Low",
+ "tags": "Story, Kanban",
+ "estimate": "0",
+ "assignee": "Nancy Davloio",
+ "rankId": "1",
+ "id": "1"
+ },
+ {
+ "label": "Task - 29003",
+ "status": "Open",
+ "summary": "Resolve Frontend issues",
+ "priority": "Medium",
+ "tags": "Frontend, UI/UX",
+ "estimate": "2",
+ "assignee": "Andrew Fuller",
+ "rankId": "1",
+ "id": "2"
+ },
+ {
+ "label": "Task - 29004",
+ "status": "Open",
+ "summary": "Setup Docker",
+ "priority": "1",
+ "tags": "Docker, Setup",
+ "estimate": "2",
+ "assignee": "James Wilson",
+ "rankId": "0",
+ "id": "3"
+ },
+ {
+ "label": "Task - 29005",
+ "status": "Open",
+ "summary": "Setup Staging Server",
+ "priority": "High",
+ "tags": "Testing, BE",
+ "estimate": "0",
+ "assignee": "George Linde",
+ "rankId": "0",
+ "id": "4"
+ },
+ {
+ "label": "Task - 29006",
+ "status": "InProgress",
+ "summary": "Implment Payment module",
+ "priority": "High",
+ "tags": "Subscription, BE",
+ "estimate": "2",
+ "assignee": "James Wilson",
+ "rankId": "0",
+ "id": "5"
+ },
+ {
+ "label": "Task - 29007",
+ "status": "InProgress",
+ "summary": "Setup Project Documentation",
+ "priority": "High",
+ "tags": "Docs, Requirements",
+ "estimate": "3",
+ "assignee": "George Linde",
+ "rankId": "0",
+ "id": "6"
+ },
+ {
+ "label": "Task - 29008",
+ "status": "Review",
+ "summary": "Setup MySQL DB",
+ "priority": "High",
+ "tags": "DB Setup",
+ "estimate": "0",
+ "assignee": "Andrew Fuller",
+ "rankId": "0",
+ "id": "7"
+ },
+ {
+ "label": "Task - 29009",
+ "status": "Review",
+ "summary": "Project Setup",
+ "priority": "High",
+ "tags": "Setup",
+ "estimate": "0",
+ "assignee": "James Wilson",
+ "rankId": "0",
+ "id": "8"
+ },
+ {
+ "label": "Task - 29010",
+ "status": "Close",
+ "summary": "Finalize Project Timelines",
+ "priority": "High",
+ "tags": "Setup, Timeline",
+ "estimate": "0",
+ "assignee": "Nancy Davloio",
+ "rankId": "0",
+ "id": "9"
+ }
+ ]
+ },
+ "mapData": {
+ "data": "[{\"label\":\"Task - 29001\",\"status\":\"Open\",\"summary\":\"Analyze customer requirements.\",\"type\":\"\",\"priority\":\"High\",\"tags\":\"Bug, Release Bug\",\"estimate\":0,\"assignee\":\"Nancy Davloio\",\"rankId\":1,\"id\":0},{\"label\":\"Task - 29002\",\"status\":\"InProgress\",\"summary\":\"Add responsive support to applicaton\",\"type\":\"\",\"priority\":\"Low\",\"tags\":\"Story, Kanban\",\"estimate\":0,\"assignee\":\"Nancy Davloio\",\"rankId\":1,\"id\":1},{\"label\":\"Option 1\",\"status\":\"Open\",\"summary\":\"\",\"type\":\"\",\"priority\":\"\",\"tags\":\"\",\"estimate\":0,\"assignee\":\"\",\"rankId\":0,\"id\":2},{\"label\":\"Option 2\",\"status\":\"Open\",\"summary\":\"\",\"type\":\"\",\"priority\":\"\",\"tags\":\"\",\"estimate\":0,\"assignee\":\"\",\"rankId\":0,\"id\":3},{\"label\":\"Option 3\",\"status\":\"Open\",\"summary\":\"\",\"type\":\"\",\"priority\":\"\",\"tags\":\"\",\"estimate\":0,\"assignee\":\"\",\"rankId\":0,\"id\":4},{\"label\":\"Option 4\",\"status\":\"InProgress\",\"summary\":\"\",\"type\":\"\",\"priority\":\"\",\"tags\":\"\",\"estimate\":0,\"assignee\":\"\",\"rankId\":0,\"id\":5},{\"label\":\"Option 5\",\"status\":\"InProgress\",\"summary\":\"\",\"type\":\"\",\"priority\":\"\",\"tags\":\"\",\"estimate\":0,\"assignee\":\"\",\"rankId\":0,\"id\":6},{\"label\":\"Option 6\",\"status\":\"Review\",\"summary\":\"\",\"type\":\"\",\"priority\":\"\",\"tags\":\"\",\"estimate\":0,\"assignee\":\"\",\"rankId\":0,\"id\":7},{\"label\":\"Option 7\",\"status\":\"Review\",\"summary\":\"\",\"type\":\"\",\"priority\":\"\",\"tags\":\"\",\"estimate\":0,\"assignee\":\"\",\"rankId\":0,\"id\":8},{\"label\":\"Option 8\",\"status\":\"Close\",\"summary\":\"\",\"type\":\"\",\"priority\":\"\",\"tags\":\"\",\"estimate\":0,\"assignee\":\"\",\"rankId\":0,\"id\":9}]",
+ "mapData": {
+ "status": "Open"
+ }
+ }
+};
+
export default function KanbanExample() {
return (
<>
+
diff --git a/client/packages/lowcoder/src/pages/ComponentDoc/examples/presentationComp/avatar.tsx b/client/packages/lowcoder/src/pages/ComponentDoc/examples/presentationComp/avatar.tsx
index c0949dc26..5ff405e2c 100644
--- a/client/packages/lowcoder/src/pages/ComponentDoc/examples/presentationComp/avatar.tsx
+++ b/client/packages/lowcoder/src/pages/ComponentDoc/examples/presentationComp/avatar.tsx
@@ -36,12 +36,30 @@ export default function AvatarExample(){
compFactory={AvatarComp}
/>
+
+
@@ -50,8 +68,7 @@ export default function AvatarExample(){
config={{
avatarCatption: "user@email.com",
avatarLabel: "User",
- icon: "/icon:solid/user",
- shape:"cirlce",
+ src: "https://i.pravatar.cc/300?u=a029026704a",
iconSize: "60",
}}
compFactory={AvatarComp}
@@ -169,6 +186,201 @@ export default function AvatarExample(){
compFactory={AvatarComp}
/>
+
+
+
+
+
+
+
+
+
+
+
>
);
}
\ No newline at end of file
diff --git a/client/packages/lowcoder/src/pages/ComponentDoc/examples/presentationComp/avatarGroup.tsx b/client/packages/lowcoder/src/pages/ComponentDoc/examples/presentationComp/avatarGroup.tsx
index 5e0995cf4..093c3a6e9 100644
--- a/client/packages/lowcoder/src/pages/ComponentDoc/examples/presentationComp/avatarGroup.tsx
+++ b/client/packages/lowcoder/src/pages/ComponentDoc/examples/presentationComp/avatarGroup.tsx
@@ -3,6 +3,35 @@ import Example from "../../common/Example";
import ExampleGroup from "../../common/ExampleGroup";
import { trans } from "i18n/design";
+const avatars = {
+ "optionType": "manual",
+ "manual": {
+ "manual": [
+ {
+ "src": "https:\\/\\/reqres.in\\/img\\/faces\\/3-image.jpg",
+ "label": "Ellis",
+ "Tooltip": "Ellis"
+ },
+ {
+ "src": "https:\\/\\/reqres.in\\/img\\/faces\\/5-image.jpg",
+ "AvatarIcon": "/icon:antd/startwotone",
+ "label": "Javas",
+ "Tooltip": "Javas"
+ },
+ {
+ "src": "https:\\/\\/i.pravatar.cc\\/300?u=a029026704a",
+ "label": "Kirk",
+ "Tooltip": "Kirk"
+ },
+ {
+ "src": "https:\\/\\/i.pravatar.cc\\/300?u=a042581f4e4a",
+ "label": "Gray",
+ "Tooltip": "Gray"
+ }
+ ]
+ },
+};
+
export default function AvatarGroupExample(){
const nameMap: Record = {
title: "title",
@@ -29,6 +58,14 @@ export default function AvatarGroupExample(){
}}
compFactory={AvatarGroupComp}
/>
+
+
+
>
);
diff --git a/client/packages/lowcoder/src/pages/ComponentDoc/examples/presentationComp/divider.tsx b/client/packages/lowcoder/src/pages/ComponentDoc/examples/presentationComp/divider.tsx
index 10c65f83b..00071dae1 100644
--- a/client/packages/lowcoder/src/pages/ComponentDoc/examples/presentationComp/divider.tsx
+++ b/client/packages/lowcoder/src/pages/ComponentDoc/examples/presentationComp/divider.tsx
@@ -17,10 +17,26 @@ export default function DividerExample() {
description={trans("componentDoc.basicDemoDescription")}
>
+
@@ -58,7 +74,7 @@ export default function DividerExample() {
/>
-
+
+
+
+
+
+
+
+
+
>
);
diff --git a/client/packages/lowcoder/src/pages/ComponentDoc/examples/presentationComp/image.tsx b/client/packages/lowcoder/src/pages/ComponentDoc/examples/presentationComp/image.tsx
index f9836f559..807086b86 100644
--- a/client/packages/lowcoder/src/pages/ComponentDoc/examples/presentationComp/image.tsx
+++ b/client/packages/lowcoder/src/pages/ComponentDoc/examples/presentationComp/image.tsx
@@ -8,30 +8,30 @@ export default function ImageExample() {
<>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
>
);
}
diff --git a/client/packages/lowcoder/src/pages/ComponentDoc/examples/presentationComp/imageCarousel.tsx b/client/packages/lowcoder/src/pages/ComponentDoc/examples/presentationComp/imageCarousel.tsx
index a90e5e3f1..eb5fbbe88 100644
--- a/client/packages/lowcoder/src/pages/ComponentDoc/examples/presentationComp/imageCarousel.tsx
+++ b/client/packages/lowcoder/src/pages/ComponentDoc/examples/presentationComp/imageCarousel.tsx
@@ -30,7 +30,7 @@ export default function ImageCarouselExample() {
compFactory={CarouselComp}
/>
+
@@ -75,6 +85,79 @@ export default function ImageCarouselExample() {
}}
compFactory={CarouselComp}
/>
+
+
+
+
+
+
+
+
>
);
diff --git a/client/packages/lowcoder/src/pages/ComponentDoc/examples/presentationComp/imageEditor.tsx b/client/packages/lowcoder/src/pages/ComponentDoc/examples/presentationComp/imageEditor.tsx
index 62981a0f4..bfd332b5c 100644
--- a/client/packages/lowcoder/src/pages/ComponentDoc/examples/presentationComp/imageEditor.tsx
+++ b/client/packages/lowcoder/src/pages/ComponentDoc/examples/presentationComp/imageEditor.tsx
@@ -11,11 +11,66 @@ export default function ImageEditorExample() {
<>
+
+
+
+
+
+
+
diff --git a/client/packages/lowcoder/src/pages/ComponentDoc/examples/presentationComp/progress.tsx b/client/packages/lowcoder/src/pages/ComponentDoc/examples/presentationComp/progress.tsx
index d7919bb9a..4b9cb2c50 100644
--- a/client/packages/lowcoder/src/pages/ComponentDoc/examples/presentationComp/progress.tsx
+++ b/client/packages/lowcoder/src/pages/ComponentDoc/examples/presentationComp/progress.tsx
@@ -8,8 +8,35 @@ export default function ProgressExample() {
<>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
>
);
}
diff --git a/client/packages/lowcoder/src/pages/ComponentDoc/examples/presentationComp/progressCircle.tsx b/client/packages/lowcoder/src/pages/ComponentDoc/examples/presentationComp/progressCircle.tsx
index b264f83ef..5b85cda90 100644
--- a/client/packages/lowcoder/src/pages/ComponentDoc/examples/presentationComp/progressCircle.tsx
+++ b/client/packages/lowcoder/src/pages/ComponentDoc/examples/presentationComp/progressCircle.tsx
@@ -12,8 +12,6 @@ export default function ProgressCircleExample() {
>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
>
);
diff --git a/client/packages/lowcoder/src/pages/ComponentDoc/examples/presentationComp/table.tsx b/client/packages/lowcoder/src/pages/ComponentDoc/examples/presentationComp/table.tsx
index 4a050d0a7..c6b05a3bf 100644
--- a/client/packages/lowcoder/src/pages/ComponentDoc/examples/presentationComp/table.tsx
+++ b/client/packages/lowcoder/src/pages/ComponentDoc/examples/presentationComp/table.tsx
@@ -5,6 +5,540 @@ import ExampleGroup from "../../common/ExampleGroup";
const data = JSON.stringify(i18nObjs.table.defaultData);
+const data2 = "[\n {\n \"id\": 1,\n \"name\": \"4\",\n \"date\": \"https://api.dicebear.com/7.x/miniavs/svg?seed=1\",\n \"department\": \"true\"\n },\n {\n \"id\": 2,\n \"name\": \"2\",,\n \"date\": \"https://api.dicebear.com/7.x/miniavs/svg?seed=1\",\n \"department\": \"true\"\n },\n {\n \"id\": 3,\n \"name\": \"1\",\n \"date\": \"https://api.dicebear.com/7.x/miniavs/svg?seed=1\",\n \"department\": \"false\"\n },\n {\n \"id\": 4,\n \"name\": \"3\",\n \"date\": \"https://api.dicebear.com/7.x/miniavs/svg?seed=1\",\n },\n {\n \"id\": 5,\n \"name\": \"5\",\n \"date\": \"https://api.dicebear.com/7.x/miniavs/svg?seed=1\",\n \"department\": \"true\"\n },\n {\n \"id\": 6,\n \"name\": \"2\",\n \"date\": \"https://api.dicebear.com/7.x/miniavs/svg?seed=1\",\n \"department\": \"\"\n },\n {\n \"id\": 7,\n \"name\": \"4\",\n \"date\": \"https://api.dicebear.com/7.x/miniavs/svg?seed=1\",\n \"department\": \"true\"\n },\n {\n \"id\": 8,\n \"name\": \"3\",\n \"date\": \"https://api.dicebear.com/7.x/miniavs/svg?seed=1\",\n \"department\": \"true\"\n },\n {\n \"id\": 9,\n \"name\": \"5\",\n \"date\": \"https://api.dicebear.com/7.x/miniavs/svg?seed=1\",\n \"department\": \"true\"\n },\n {\n \"id\": 10,\n \"name\": \"2\",\n \"date\": \"https://api.dicebear.com/7.x/miniavs/svg?seed=1\",\n \"department\": \"false\"\n }\n]";
+
+const data3 = "[\n {\n \"id\": 1,\n \"name\": \"Reagen Gilberthorpe\",\n \"date\": \"Completed\",\n \"department\": \"100\"\n },\n {\n \"id\": 2,\n \"name\": \"Haroun Lortzing\",\n \"date\": \"To Do\",\n \"department\": \"0\"\n },\n {\n \"id\": 2,\n \"name\": \"Garret Kilmaster\",\n \"date\": \"In Progress\",\n \"department\": \"45\"\n },\n {\n \"id\": 3,\n \"name\": \"Israel Harrowsmith\",\n \"date\": \"Closed\",\n \"department\": \"100\"\n },\n {\n \"id\": 1,\n \"name\": \"Loren O'Lagen\",\n \"date\": \"Backlog\",\n \"department\": \"0\"\n },\n {\n \"id\": 2,\n \"name\": \"Wallis Hothersall\",\n \"date\": \"Partially Completed\",\n \"department\": \"85\"\n },\n {\n \"id\": 1,\n \"name\": \"Kaia Biskup\",\n \"date\": \"To Do\",\n \"department\": \"0\"\n },\n {\n \"id\": 3,\n \"name\": \"Travers Saterweyte\",\n \"date\": \"Done\",\n \"department\": \"100\"\n },\n {\n \"id\": 3,\n \"name\": \"Mikey Niemetz\",\n \"date\": \"In Progress\",\n \"department\": \"45\"\n },\n {\n \"id\": 1,\n \"name\": \"Mano Meckiff\",\n \"date\": \"Completed\",\n \"department\": \"100\"\n }\n]";
+
+const data4 = "[\n {\n \"id\": \"https://www.google.com\",\n \"name\": \"Reagen Gilberthorpe\",\n \"date\": \"7/5/2022\",\n },\n {\n \"id\": \"https://www.linkedin.com\",\n \"name\": \"Haroun Lortzing\",\n \"date\": \"11/6/2022\",\n },\n {\n \"id\": \"http://lowcoder.cloud/\",\n \"name\": \"Garret Kilmaster\",\n \"date\": \"11/14/2021\",\n },\n {\n \"id\": \"https://docs.lowcoder.cloud/\",\n \"name\": \"Israel Harrowsmith\",\n \"date\": \"4/3/2022\",\n },\n {\n \"id\": \"https://app.lowcoder.cloud\",\n \"name\": \"Loren O'Lagen\",\n \"date\": \"9/10/2022\",\n },\n {\n \"id\": \"https://www.espncricinfo.com/\",\n \"name\": \"Wallis Hothersall\",\n \"date\": \"4/18/2022\",\n },\n {\n \"id\": \"https://techcrunch.com/\",\n \"name\": \"Kaia Biskup\",\n \"date\": \"3/4/2022\",\n },\n {\n \"id\": \"https://www.apple.com/\",\n \"name\": \"Travers Saterweyte\",\n \"date\": \"1/9/2022\",\n },\n {\n \"id\": \"https://www.amazon.com/\",\n \"name\": \"Mikey Niemetz\",\n \"date\": \"1/4/2022\",\n },\n {\n \"id\": \"https://www.etsy.com/\",\n \"name\": \"Mano Meckiff\",\n \"date\": \"2/19/2022\",\n }\n]";
+
+const columns = [
+ {
+ "title": "ID",
+ "showTitle": true,
+ "isCustom": false,
+ "dataIndex": "id",
+ "width": "55",
+ "autoWidth": "fixed",
+ "render": {
+ "compType": "text",
+ "comp": {
+ "text": "{{currentCell}}"
+ }
+ },
+ "align": "left",
+ "fixed": "close",
+ "editable": true,
+ "background": "",
+ "margin": "",
+ "text": "",
+ "border": "",
+ "borderWidth": "",
+ "radius": "",
+ "textSize": "",
+ "textWeight": "normal",
+ "fontFamily": "sans-serif",
+ "fontStyle": "normal",
+ "textOverflow": "ellipsis",
+ "linkColor": "#3377ff",
+ "linkHoverColor": "",
+ "linkActiveColor": "",
+ "summaryColumns": [
+ {
+ "isCustom": false,
+ "dataIndex": "",
+ "render": {
+ "compType": "text",
+ "comp": {}
+ },
+ "align": "left",
+ "background": "",
+ "margin": "",
+ "text": "",
+ "border": "",
+ "radius": "",
+ "textSize": "",
+ "textWeight": "normal",
+ "fontFamily": "sans-serif",
+ "fontStyle": "normal",
+ "textOverflow": "ellipsis",
+ "linkColor": "#3377ff",
+ "linkHoverColor": "",
+ "linkActiveColor": ""
+ },
+ {
+ "isCustom": false,
+ "dataIndex": "",
+ "render": {
+ "compType": "text",
+ "comp": {}
+ },
+ "align": "left",
+ "background": "",
+ "margin": "",
+ "text": "",
+ "border": "",
+ "radius": "",
+ "textSize": "",
+ "textWeight": "normal",
+ "fontFamily": "sans-serif",
+ "fontStyle": "normal",
+ "textOverflow": "ellipsis",
+ "linkColor": "#3377ff",
+ "linkHoverColor": "",
+ "linkActiveColor": ""
+ },
+ {
+ "isCustom": false,
+ "dataIndex": "",
+ "render": {
+ "compType": "text",
+ "comp": {}
+ },
+ "align": "left",
+ "background": "",
+ "margin": "",
+ "text": "",
+ "border": "",
+ "radius": "",
+ "textSize": "",
+ "textWeight": "normal",
+ "fontFamily": "sans-serif",
+ "fontStyle": "normal",
+ "textOverflow": "ellipsis",
+ "linkColor": "#3377ff",
+ "linkHoverColor": "",
+ "linkActiveColor": ""
+ }
+ ]
+ },
+ {
+ "title": "Name",
+ "showTitle": true,
+ "isCustom": false,
+ "dataIndex": "name",
+ "width": "200",
+ "autoWidth": "fixed",
+ "render": {
+ "compType": "text",
+ "comp": {
+ "text": "{{currentCell}}"
+ }
+ },
+ "align": "left",
+ "fixed": "close",
+ "editable": true,
+ "background": "",
+ "margin": "",
+ "text": "",
+ "border": "",
+ "borderWidth": "",
+ "radius": "",
+ "textSize": "",
+ "textWeight": "normal",
+ "fontFamily": "sans-serif",
+ "fontStyle": "normal",
+ "textOverflow": "ellipsis",
+ "linkColor": "#3377ff",
+ "linkHoverColor": "",
+ "linkActiveColor": "",
+ "summaryColumns": [
+ {
+ "isCustom": false,
+ "dataIndex": "",
+ "render": {
+ "compType": "text",
+ "comp": {}
+ },
+ "align": "left",
+ "background": "",
+ "margin": "",
+ "text": "",
+ "border": "",
+ "radius": "",
+ "textSize": "",
+ "textWeight": "normal",
+ "fontFamily": "sans-serif",
+ "fontStyle": "normal",
+ "textOverflow": "ellipsis",
+ "linkColor": "#3377ff",
+ "linkHoverColor": "",
+ "linkActiveColor": ""
+ },
+ {
+ "isCustom": false,
+ "dataIndex": "",
+ "render": {
+ "compType": "text",
+ "comp": {}
+ },
+ "align": "left",
+ "background": "",
+ "margin": "",
+ "text": "",
+ "border": "",
+ "radius": "",
+ "textSize": "",
+ "textWeight": "normal",
+ "fontFamily": "sans-serif",
+ "fontStyle": "normal",
+ "textOverflow": "ellipsis",
+ "linkColor": "#3377ff",
+ "linkHoverColor": "",
+ "linkActiveColor": ""
+ },
+ {
+ "isCustom": false,
+ "dataIndex": "",
+ "render": {
+ "compType": "text",
+ "comp": {}
+ },
+ "align": "left",
+ "background": "",
+ "margin": "",
+ "text": "",
+ "border": "",
+ "radius": "",
+ "textSize": "",
+ "textWeight": "normal",
+ "fontFamily": "sans-serif",
+ "fontStyle": "normal",
+ "textOverflow": "ellipsis",
+ "linkColor": "#3377ff",
+ "linkHoverColor": "",
+ "linkActiveColor": ""
+ }
+ ]
+ },
+ {
+ "title": "Date",
+ "showTitle": true,
+ "isCustom": false,
+ "dataIndex": "date",
+ "width": "110",
+ "autoWidth": "fixed",
+ "render": {
+ "compType": "text",
+ "comp": {
+ "text": "{{currentCell}}"
+ }
+ },
+ "align": "left",
+ "fixed": "close",
+ "editable": true,
+ "background": "",
+ "margin": "",
+ "text": "",
+ "border": "",
+ "borderWidth": "",
+ "radius": "",
+ "textSize": "",
+ "textWeight": "normal",
+ "fontFamily": "sans-serif",
+ "fontStyle": "normal",
+ "textOverflow": "ellipsis",
+ "linkColor": "#3377ff",
+ "linkHoverColor": "",
+ "linkActiveColor": "",
+ "summaryColumns": [
+ {
+ "isCustom": false,
+ "dataIndex": "",
+ "render": {
+ "compType": "text",
+ "comp": {}
+ },
+ "align": "left",
+ "background": "",
+ "margin": "",
+ "text": "",
+ "border": "",
+ "radius": "",
+ "textSize": "",
+ "textWeight": "normal",
+ "fontFamily": "sans-serif",
+ "fontStyle": "normal",
+ "textOverflow": "ellipsis",
+ "linkColor": "#3377ff",
+ "linkHoverColor": "",
+ "linkActiveColor": ""
+ },
+ {
+ "isCustom": false,
+ "dataIndex": "",
+ "render": {
+ "compType": "text",
+ "comp": {}
+ },
+ "align": "left",
+ "background": "",
+ "margin": "",
+ "text": "",
+ "border": "",
+ "radius": "",
+ "textSize": "",
+ "textWeight": "normal",
+ "fontFamily": "sans-serif",
+ "fontStyle": "normal",
+ "textOverflow": "ellipsis",
+ "linkColor": "#3377ff",
+ "linkHoverColor": "",
+ "linkActiveColor": ""
+ },
+ {
+ "isCustom": false,
+ "dataIndex": "",
+ "render": {
+ "compType": "text",
+ "comp": {}
+ },
+ "align": "left",
+ "background": "",
+ "margin": "",
+ "text": "",
+ "border": "",
+ "radius": "",
+ "textSize": "",
+ "textWeight": "normal",
+ "fontFamily": "sans-serif",
+ "fontStyle": "normal",
+ "textOverflow": "ellipsis",
+ "linkColor": "#3377ff",
+ "linkHoverColor": "",
+ "linkActiveColor": ""
+ }
+ ]
+ },
+ {
+ "title": "Department",
+ "showTitle": true,
+ "isCustom": false,
+ "dataIndex": "department",
+ "width": "250",
+ "autoWidth": "fixed",
+ "render": {
+ "compType": "tag",
+ "comp": {
+ "text": "{{currentCell}}",
+ "tagColors": {
+ "optionType": "manual",
+ "manual": {
+ "manual": [
+ {
+ "label": "Tag1",
+ "icon": "/icon:solid/tag",
+ "color": "#f50"
+ },
+ {
+ "label": "Tag2",
+ "icon": "/icon:solid/tag",
+ "color": "#2db7f5"
+ }
+ ]
+ },
+ "mapData": {
+ "data": "[]",
+ "mapData": {
+ "color": ""
+ }
+ }
+ }
+ }
+ },
+ "align": "left",
+ "fixed": "close",
+ "editable": true,
+ "background": "",
+ "margin": "",
+ "text": "",
+ "border": "",
+ "borderWidth": "",
+ "radius": "",
+ "textSize": "",
+ "textWeight": "normal",
+ "fontFamily": "sans-serif",
+ "fontStyle": "normal",
+ "textOverflow": "ellipsis",
+ "linkColor": "#3377ff",
+ "linkHoverColor": "",
+ "linkActiveColor": "",
+ "summaryColumns": [
+ {
+ "isCustom": false,
+ "dataIndex": "",
+ "render": {
+ "compType": "text",
+ "comp": {}
+ },
+ "align": "left",
+ "background": "",
+ "margin": "",
+ "text": "",
+ "border": "",
+ "radius": "",
+ "textSize": "",
+ "textWeight": "normal",
+ "fontFamily": "sans-serif",
+ "fontStyle": "normal",
+ "textOverflow": "ellipsis",
+ "linkColor": "#3377ff",
+ "linkHoverColor": "",
+ "linkActiveColor": ""
+ },
+ {
+ "isCustom": false,
+ "dataIndex": "",
+ "render": {
+ "compType": "text",
+ "comp": {}
+ },
+ "align": "left",
+ "background": "",
+ "margin": "",
+ "text": "",
+ "border": "",
+ "radius": "",
+ "textSize": "",
+ "textWeight": "normal",
+ "fontFamily": "sans-serif",
+ "fontStyle": "normal",
+ "textOverflow": "ellipsis",
+ "linkColor": "#3377ff",
+ "linkHoverColor": "",
+ "linkActiveColor": ""
+ },
+ {
+ "isCustom": false,
+ "dataIndex": "",
+ "render": {
+ "compType": "text",
+ "comp": {}
+ },
+ "align": "left",
+ "background": "",
+ "margin": "",
+ "text": "",
+ "border": "",
+ "radius": "",
+ "textSize": "",
+ "textWeight": "normal",
+ "fontFamily": "sans-serif",
+ "fontStyle": "normal",
+ "textOverflow": "ellipsis",
+ "linkColor": "#3377ff",
+ "linkHoverColor": "",
+ "linkActiveColor": ""
+ }
+ ]
+ }
+];
+const expansion = {
+ "expandable": true,
+ "slot": {
+ "container": {
+ "layout": {
+ "d7274235": {
+ "i": "d7274235",
+ "h": 8,
+ "w": 24,
+ "x": 0,
+ "y": 0,
+ "pos": 0
+ }
+ },
+ "items": {
+ "d7274235": {
+ "compType": "text",
+ "comp": {
+ "text": "### You can configure/add any component inside the Exapandable Table View",
+ "autoHeight": "auto",
+ "type": "markdown",
+ "horizontalAlignment": "center",
+ "contentScrollBar": true,
+ "verticalAlignment": "center",
+ "margin": {
+ "left": "",
+ "right": "",
+ "top": "",
+ "bottom": ""
+ },
+ "padding": {
+ "left": "",
+ "right": "",
+ "top": "",
+ "bottom": ""
+ },
+ "showDataLoadingIndicators": false,
+ "preventStyleOverwriting": false,
+ "appliedThemeId": "",
+ "version": "latest"
+ },
+ "name": "text1"
+ }
+ }
+ }
+ }
+};
+const style= {
+ "margin": "10px",
+ "padding": "20px",
+ "borderStyle": "dashed",
+ "borderWidth": "3px",
+ "background": "linear-gradient(135deg, #72afd3 0%, #96e6a1 100%)",
+ "border": "#000",
+ "radius": "10px"
+};
+const headerStyle = {
+ "margin": "10px",
+ "fontFamily": "Courier New",
+ "fontStyle": "italic",
+ "text": "#222222",
+ "headerBackground": "#F7A007",
+ "border": "#E67373",
+ "borderWidth": "7px",
+ "textSize": "25px"
+};
+const toolbarStyle = {
+ "margin": "0px",
+ "background": "#F7A007",
+ "border": "#E67373",
+ "toolbarText": "#FFFFFF"
+};
+const rowStyle = {
+ "borderWidth": "10px",
+ "borderStyle": "dashed",
+ "background": "linear-gradient(0deg, #fdfbfb 0%, #ebedee 100%)",
+ "border": "#222222",
+ "radius": "10px",
+ "selectedRowBackground": "#3377FF",
+ "hoverRowBackground": "#FFF6E6",
+ "alternateBackground": "linear-gradient(0deg, #FFFFFF 0%, rgba(235, 237, 238, 1) 100%)"
+};
+const columnStyle = {
+ "background": "linear-gradient(90deg, RGBA(247, 160, 7, 1) 0%, rgba(254,225,64,1) 100%)",
+ "border": "#222222",
+ "margin": "10px",
+ "radius": "10px",
+ "text": "#000000",
+ "textSize": "15px",
+ "textWeight": "bold",
+ "fontFamily": "Courier New",
+ "fontStyle": "italic"
+};
+const summaryRowStyle = {
+ "borderWidth": "5px",
+ "borderStyle": "dashed",
+ "background": "#D7D9E0",
+ "border": "#222222",
+ "radius": "10px",
+ "margin": "1px",
+ "text": "#FFFFFF",
+ "textSize": "15px",
+ "textWeight": "bold",
+ "fontFamily": "Courier New",
+ "fontStyle": "italic"
+};
+
export default function TableExample() {
const blackListConfig: string[] = ["data", "size"];
const nameMap: Record = {
@@ -51,7 +585,7 @@ export default function TableExample() {
/>
-
+
+
+
+
+
+
+
+
@@ -154,6 +756,46 @@ export default function TableExample() {
blackListConfig={blackListConfig}
compFactory={TableComp}
/>
+
+
+
+
@@ -202,6 +844,6036 @@ export default function TableExample() {
compFactory={TableComp}
/>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
>
);
}
diff --git a/client/packages/lowcoder/src/pages/ComponentDoc/examples/presentationComp/text.tsx b/client/packages/lowcoder/src/pages/ComponentDoc/examples/presentationComp/text.tsx
index 16f3ee3f4..fab465482 100644
--- a/client/packages/lowcoder/src/pages/ComponentDoc/examples/presentationComp/text.tsx
+++ b/client/packages/lowcoder/src/pages/ComponentDoc/examples/presentationComp/text.tsx
@@ -33,6 +33,16 @@ export default function TextExample() {
nameMap={nameMap}
compFactory={TextComp}
/>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
>
);
}
diff --git a/client/packages/lowcoder/src/pages/ComponentDoc/examples/presentationComp/timeline.tsx b/client/packages/lowcoder/src/pages/ComponentDoc/examples/presentationComp/timeline.tsx
index 34f87e1a9..a5c916911 100644
--- a/client/packages/lowcoder/src/pages/ComponentDoc/examples/presentationComp/timeline.tsx
+++ b/client/packages/lowcoder/src/pages/ComponentDoc/examples/presentationComp/timeline.tsx
@@ -10,15 +10,31 @@ export default function TimeLineExample() {
title={trans("componentDoc.basicUsage")}
description="The Following Examples Show the Basic Usage of the TimeLine Component."
>
+
+
+
+
+
+
+
+
+
+
+
+
>
);
}
diff --git a/client/packages/lowcoder/src/pages/ComponentDoc/examples/selectInputComp/AutoComplete.tsx b/client/packages/lowcoder/src/pages/ComponentDoc/examples/selectInputComp/AutoComplete.tsx
index 65e3a7f72..ff6c0a38d 100644
--- a/client/packages/lowcoder/src/pages/ComponentDoc/examples/selectInputComp/AutoComplete.tsx
+++ b/client/packages/lowcoder/src/pages/ComponentDoc/examples/selectInputComp/AutoComplete.tsx
@@ -93,6 +93,147 @@ export default function AutoCompleteExample() {
}}
compFactory={AutoCompleteComp}
/>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
>
);
diff --git a/client/packages/lowcoder/src/pages/ComponentDoc/examples/selectInputComp/Cascader.tsx b/client/packages/lowcoder/src/pages/ComponentDoc/examples/selectInputComp/Cascader.tsx
index c64abd6fd..d7a8a9dc8 100644
--- a/client/packages/lowcoder/src/pages/ComponentDoc/examples/selectInputComp/Cascader.tsx
+++ b/client/packages/lowcoder/src/pages/ComponentDoc/examples/selectInputComp/Cascader.tsx
@@ -3,10 +3,11 @@ import { trans, i18nObjs } from "i18n";
import Example from "../../common/Example";
import ExampleGroup from "../../common/ExampleGroup";
-const options = JSON.stringify(i18nObjs.cascaderDefult);
+const options = '[\n {\n "value": "California",\n "label": "California",\n "children": [\n {\n "value": "San Francisco",\n "label": "San Francisco",\n "children": [\n {\n "value": "The Golden Gate Bridge",\n "label": "The Golden Gate Bridge"\n }\n ]\n }\n ]\n },\n {\n "value": "New South Wales",\n "label": "New South Wales",\n "children": [\n {\n "value": "Sydney",\n "label": "Sydney",\n "children": [\n {\n "value": "Sydney Opera House",\n "label": "Sydney Opera House"\n }\n ]\n }\n ]\n }\n]';
export default function CascaderExample() {
const blackListConfig: string[] = ["options"];
+
return (
<>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
>
);
diff --git a/client/packages/lowcoder/src/pages/ComponentDoc/examples/selectInputComp/CheckBox.tsx b/client/packages/lowcoder/src/pages/ComponentDoc/examples/selectInputComp/CheckBox.tsx
index a9f2d7bf7..d1c0ba828 100644
--- a/client/packages/lowcoder/src/pages/ComponentDoc/examples/selectInputComp/CheckBox.tsx
+++ b/client/packages/lowcoder/src/pages/ComponentDoc/examples/selectInputComp/CheckBox.tsx
@@ -44,6 +44,7 @@ export default function CheckboxExample() {
};
return (
<>
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
>
);
}
diff --git a/client/packages/lowcoder/src/pages/ComponentDoc/examples/selectInputComp/File.tsx b/client/packages/lowcoder/src/pages/ComponentDoc/examples/selectInputComp/File.tsx
index b383bffea..be97c5bdb 100644
--- a/client/packages/lowcoder/src/pages/ComponentDoc/examples/selectInputComp/File.tsx
+++ b/client/packages/lowcoder/src/pages/ComponentDoc/examples/selectInputComp/File.tsx
@@ -8,30 +8,35 @@ export default function FileExample() {
<>
+
+
+
+
+
+
+
+
+
+
+
+
>
);
}
diff --git a/client/packages/lowcoder/src/pages/ComponentDoc/examples/selectInputComp/MultiSelect.tsx b/client/packages/lowcoder/src/pages/ComponentDoc/examples/selectInputComp/MultiSelect.tsx
index 293317832..1070870b1 100644
--- a/client/packages/lowcoder/src/pages/ComponentDoc/examples/selectInputComp/MultiSelect.tsx
+++ b/client/packages/lowcoder/src/pages/ComponentDoc/examples/selectInputComp/MultiSelect.tsx
@@ -44,6 +44,7 @@ export default function MultiSelectExample() {
};
return (
<>
+
+
+
+
+
+
+
+
+
+
+
+
+
>
);
}
diff --git a/client/packages/lowcoder/src/pages/ComponentDoc/examples/selectInputComp/Radio.tsx b/client/packages/lowcoder/src/pages/ComponentDoc/examples/selectInputComp/Radio.tsx
index bb6233d34..9cb93046f 100644
--- a/client/packages/lowcoder/src/pages/ComponentDoc/examples/selectInputComp/Radio.tsx
+++ b/client/packages/lowcoder/src/pages/ComponentDoc/examples/selectInputComp/Radio.tsx
@@ -88,7 +88,21 @@ export default function RadioExample() {
blackListConfig={blackListConfig}
compFactory={RadioComp}
/>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
>
);
}
diff --git a/client/packages/lowcoder/src/pages/ComponentDoc/examples/selectInputComp/Select.tsx b/client/packages/lowcoder/src/pages/ComponentDoc/examples/selectInputComp/Select.tsx
index a08b855cd..192ccb811 100644
--- a/client/packages/lowcoder/src/pages/ComponentDoc/examples/selectInputComp/Select.tsx
+++ b/client/packages/lowcoder/src/pages/ComponentDoc/examples/selectInputComp/Select.tsx
@@ -44,6 +44,7 @@ export default function SelectExample() {
};
return (
<>
+
+
+
+
+
+
+
+
+
+
+
+
+
>
);
}
diff --git a/client/packages/lowcoder/src/pages/ComponentDoc/examples/selectInputComp/Tree.tsx b/client/packages/lowcoder/src/pages/ComponentDoc/examples/selectInputComp/Tree.tsx
index 556cb637d..376cc16e5 100644
--- a/client/packages/lowcoder/src/pages/ComponentDoc/examples/selectInputComp/Tree.tsx
+++ b/client/packages/lowcoder/src/pages/ComponentDoc/examples/selectInputComp/Tree.tsx
@@ -2,6 +2,7 @@ import { TreeComp } from "comps/comps/treeComp/treeComp";
import { trans } from "i18n";
import Example from "../../common/Example";
import ExampleGroup from "../../common/ExampleGroup";
+import { InputFieldStyle } from "@lowcoder-ee/index.sdk";
export default function TreeExample() {
const blackListConfig: string[] = ["options.manual.manual"];
@@ -263,6 +264,180 @@ export default function TreeExample() {
compFactory={TreeComp}
/>
+
+
+
+
+
+
+
+
+
+
+
+
>
);
diff --git a/client/packages/lowcoder/src/pages/ComponentDoc/examples/selectInputComp/TreeSelect.tsx b/client/packages/lowcoder/src/pages/ComponentDoc/examples/selectInputComp/TreeSelect.tsx
index 0458b9cce..afd7a541f 100644
--- a/client/packages/lowcoder/src/pages/ComponentDoc/examples/selectInputComp/TreeSelect.tsx
+++ b/client/packages/lowcoder/src/pages/ComponentDoc/examples/selectInputComp/TreeSelect.tsx
@@ -294,6 +294,180 @@ export default function TreeSelectExample() {
compFactory={TreeSelectComp}
/>
+
+
+
+
+
+
+
+
+
+
+
+
>
);
}
diff --git a/client/packages/lowcoder/src/pages/ComponentDoc/examples/textInputComp/Input.tsx b/client/packages/lowcoder/src/pages/ComponentDoc/examples/textInputComp/Input.tsx
index 1426ac789..ced66f5a3 100644
--- a/client/packages/lowcoder/src/pages/ComponentDoc/examples/textInputComp/Input.tsx
+++ b/client/packages/lowcoder/src/pages/ComponentDoc/examples/textInputComp/Input.tsx
@@ -14,7 +14,6 @@ export default function InputExample() {
title={trans("componentDoc.placeholder")}
config={{
placeholder: trans("componentDoc.pleaseInputName"),
- disabled: false,
}}
compFactory={InputComp}
/>
@@ -22,7 +21,6 @@ export default function InputExample() {
title="Default Value"
config={{
placeholder: trans("componentDoc.pleaseInputName"),
- disabled: false,
defaultValue: "Default Text",
}}
compFactory={InputComp}
@@ -35,11 +33,19 @@ export default function InputExample() {
}}
compFactory={InputComp}
/>
+
+
+
+
@@ -113,6 +141,28 @@ export default function InputExample() {
}}
compFactory={InputComp}
/>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
>
);
}
diff --git a/client/packages/lowcoder/src/pages/ComponentDoc/examples/textInputComp/Password.tsx b/client/packages/lowcoder/src/pages/ComponentDoc/examples/textInputComp/Password.tsx
index 099aa3793..ba5c6d353 100644
--- a/client/packages/lowcoder/src/pages/ComponentDoc/examples/textInputComp/Password.tsx
+++ b/client/packages/lowcoder/src/pages/ComponentDoc/examples/textInputComp/Password.tsx
@@ -26,11 +26,19 @@ export default function PasswordExample() {
}}
compFactory={PasswordComp}
/>
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
>
);
}
diff --git a/client/packages/lowcoder/src/pages/ComponentDoc/examples/textInputComp/RichTextEditor.tsx b/client/packages/lowcoder/src/pages/ComponentDoc/examples/textInputComp/RichTextEditor.tsx
index ffbaab53b..184f793a4 100644
--- a/client/packages/lowcoder/src/pages/ComponentDoc/examples/textInputComp/RichTextEditor.tsx
+++ b/client/packages/lowcoder/src/pages/ComponentDoc/examples/textInputComp/RichTextEditor.tsx
@@ -8,10 +8,12 @@ export default function InputExample() {
<>
-
+
+
+
+
+
>
);
}
diff --git a/client/packages/lowcoder/src/pages/ComponentDoc/examples/textInputComp/TextArea.tsx b/client/packages/lowcoder/src/pages/ComponentDoc/examples/textInputComp/TextArea.tsx
index a26f0391a..dbf3bb1e4 100644
--- a/client/packages/lowcoder/src/pages/ComponentDoc/examples/textInputComp/TextArea.tsx
+++ b/client/packages/lowcoder/src/pages/ComponentDoc/examples/textInputComp/TextArea.tsx
@@ -35,11 +35,19 @@ export default function ButtonExample() {
}}
compFactory={TextAreaComp}
/>
+
+
+
@@ -121,6 +145,114 @@ export default function ButtonExample() {
compFactory={TextAreaComp}
/>
+
+
+
+
+
+
+
+
+
+
+
+
>
);
}
diff --git a/client/packages/lowcoder/src/pages/common/headerStartDropdown.tsx b/client/packages/lowcoder/src/pages/common/headerStartDropdown.tsx
index bb7d41b5a..3170f9871 100644
--- a/client/packages/lowcoder/src/pages/common/headerStartDropdown.tsx
+++ b/client/packages/lowcoder/src/pages/common/headerStartDropdown.tsx
@@ -100,7 +100,7 @@ export function HeaderStartDropdown(props: { setEdit: () => void, isViewMarketpl
})}
),
- visible: true,
+ visible: !isPublicApp,
},
];
diff --git a/client/packages/lowcoder/src/pages/common/previewHeader.tsx b/client/packages/lowcoder/src/pages/common/previewHeader.tsx
index 89aafa153..f8d4cba2e 100644
--- a/client/packages/lowcoder/src/pages/common/previewHeader.tsx
+++ b/client/packages/lowcoder/src/pages/common/previewHeader.tsx
@@ -115,6 +115,8 @@ export function HeaderProfile(props: { user: User }) {
const { user } = props;
const fetchingUser = useSelector(isFetchingUser);
const templateId = useSelector(getTemplateId);
+ const isPublicApp = useSelector(isPublicApplication);
+
if (fetchingUser) {
return ;
}
@@ -122,7 +124,13 @@ export function HeaderProfile(props: { user: User }) {
{user.isAnonymous ? (
!templateId ? (
-
history.push(AUTH_LOGIN_URL)}>
+ {
+ if (isPublicApp) {
+ window.top?.open('https://app.lowcoder.cloud/user/auth/login');
+ } else {
+ history.push(AUTH_LOGIN_URL)
+ }
+ }}>
{trans("userAuth.login")}
) : null
@@ -147,7 +155,7 @@ const PreviewHeaderComp = () => {
const headerStart = (
<>
- history.push(ALL_APPLICATIONS_URL)}>
+ !isPublicApp && history.push(ALL_APPLICATIONS_URL)}>
{isViewMarketplaceMode && (
@@ -204,36 +212,44 @@ const PreviewHeaderComp = () => {
);
- const headerMiddle = (
- <>
- {/* Devices */}
-
- options={[
- { value: 'mobile', icon: },
- { value: 'tablet', icon: },
- { value: 'desktop', icon: },
- ]}
- value={editorState.deviceType}
- onChange={(value) => {
- editorState.setDeviceType(value);
- }}
- />
-
- {/* Orientation */}
- {editorState.deviceType !== 'desktop' && (
-
+ const headerMiddle = useMemo(() => {
+ if (isPublicApp) return null;
+
+ return (
+ <>
+ {/* Devices */}
+
options={[
- { value: 'portrait', label: "Portrait" },
- { value: 'landscape', label: "Landscape" },
+ { value: 'mobile', icon: },
+ { value: 'tablet', icon: },
+ { value: 'desktop', icon: },
]}
- value={editorState.deviceOrientation}
+ value={editorState.deviceType}
onChange={(value) => {
- editorState.setDeviceOrientation(value);
+ editorState.setDeviceType(value);
}}
/>
- )}
- >
- );
+
+ {/* Orientation */}
+ {editorState.deviceType !== 'desktop' && (
+
+ options={[
+ { value: 'portrait', label: "Portrait" },
+ { value: 'landscape', label: "Landscape" },
+ ]}
+ value={editorState.deviceOrientation}
+ onChange={(value) => {
+ editorState.setDeviceOrientation(value);
+ }}
+ />
+ )}
+ >
+ );
+ }, [
+ isPublicApp,
+ editorState.deviceType,
+ editorState.deviceOrientation,
+ ]);
return (
,
basicChart : ,
+ barChart : ,
+ lineChart : ,
+ pieChart : ,
+ scatterChart : ,
+
avatar: ,
avatarGroup: ,
colorPicker: ,
diff --git a/client/packages/lowcoder/src/pages/editor/right/PluginPanel/index.tsx b/client/packages/lowcoder/src/pages/editor/right/PluginPanel/index.tsx
index ea4781c75..ade61d984 100644
--- a/client/packages/lowcoder/src/pages/editor/right/PluginPanel/index.tsx
+++ b/client/packages/lowcoder/src/pages/editor/right/PluginPanel/index.tsx
@@ -97,6 +97,8 @@ export default function PluginPanel() {
();
const [prevJsonStr, setPrevJsonStr] = useState();
+ const [prevQueryId, setPrevQueryId] = useState();
+ const queryId = query?.id;
useEffect(() => {
- if (!comp || comp === prevComp || !query || !comp?.children.query.children.id.getView()) {
+ if (!comp || comp === prevComp) {
return;
}
+
const curJson = comp.toJsonValue();
const curJsonStr = JSON.stringify(curJson);
+
+ if (isEmpty(curJson?.query?.comp)) {
+ return;
+ }
+ if (!Boolean(prevQueryId) && Boolean(queryId)) {
+ setPrevComp(comp);
+ setPrevJsonStr(curJsonStr);
+ return setPrevQueryId(queryId);
+ }
+ if (prevQueryId !== queryId) {
+ setPrevComp(comp);
+ setPrevJsonStr(curJsonStr);
+ return setPrevQueryId(queryId);
+ }
+ if (!Boolean(prevJsonStr) && Boolean(curJsonStr)) {
+ setPrevComp(comp)
+ return setPrevJsonStr(curJsonStr);
+ }
if (prevJsonStr === curJsonStr) {
return;
}
+
// the first time is a normal change, the latter is the manual update
if (prevComp) {
query.name = comp.children.query.children.name.getView();
@@ -411,5 +434,6 @@ function useSaveQueryLibrary(
}
setPrevComp(comp);
setPrevJsonStr(curJsonStr);
- }, [comp, query, prevComp, prevJsonStr, dispatch]);
+ setPrevQueryId(queryId);
+ }, [comp, queryId, dispatch]);
}
diff --git a/client/packages/lowcoder/src/pages/support/supportDetail.tsx b/client/packages/lowcoder/src/pages/support/supportDetail.tsx
index cb1021f8f..8048c0ae6 100644
--- a/client/packages/lowcoder/src/pages/support/supportDetail.tsx
+++ b/client/packages/lowcoder/src/pages/support/supportDetail.tsx
@@ -15,6 +15,7 @@ import remarkGfm from 'remark-gfm';
import { contrastColor } from "comps/controls/styleControlConstants";
import ReactQuill from 'react-quill';
import 'react-quill/dist/quill.snow.css';
+import { useCurrentUser } from "util/currentUser";
const { Title, Text } = Typography;
const { TextArea } = Input;
@@ -270,7 +271,7 @@ export function SupportDetail() {
const [isAddingComment, setIsAddingComment] = useState(false);
const [isUploading, setIsUploading] = useState(false);
const [fileList, setFileList] = useState([]);
-
+ const user = useCurrentUser();
// State for description edit
const [isEditingDescription, setIsEditingDescription] = useState(false);
@@ -538,8 +539,8 @@ export function SupportDetail() {
renderItem={(comment: any) => (
}
- title={comment.author.displayName}
+ avatar={ }
+ title={comment.author.accountId == "712020:a25c863c-bd24-456e-aa3f-2335c18e0235" ? trans("support.selfUser") : comment.author.displayName}
description={
<>
diff --git a/client/packages/lowcoder/src/redux/sagas/subscriptionSagas.ts b/client/packages/lowcoder/src/redux/sagas/subscriptionSagas.ts
index 8f43b9fc1..1e94116d7 100644
--- a/client/packages/lowcoder/src/redux/sagas/subscriptionSagas.ts
+++ b/client/packages/lowcoder/src/redux/sagas/subscriptionSagas.ts
@@ -11,9 +11,7 @@ import { Subscription, LowcoderSearchCustomer } from '@lowcoder-ee/constants/sub
function* fetchSubscriptionsSaga(action: ReturnType
) {
try {
const user: User = yield select(getUser);
- const currentUser: CurrentUser = yield select(getCurrentUser);
const orgID = user.currentOrgId;
- const domain = `${window.location.protocol}//${window.location.hostname}${window.location.port ? `:${window.location.port}` : ''}`;
const deploymentId: string = yield select(getDeploymentId);
const subscriptionSearchCustomer: LowcoderSearchCustomer = {
diff --git a/client/packages/lowcoder/src/util/context/SubscriptionContext.tsx b/client/packages/lowcoder/src/util/context/SubscriptionContext.tsx
index f89e5ff77..1d1b16d93 100644
--- a/client/packages/lowcoder/src/util/context/SubscriptionContext.tsx
+++ b/client/packages/lowcoder/src/util/context/SubscriptionContext.tsx
@@ -1,4 +1,4 @@
-import { createCheckoutLink, createCustomer, getProducts, searchCustomer } from "@lowcoder-ee/api/subscriptionApi";
+import { createCheckoutLink, cleanupCustomer } from "@lowcoder-ee/api/subscriptionApi";
import { StripeCustomer, SubscriptionProduct, InitSubscriptionProducts, LowcoderSearchCustomer, LowcoderNewCustomer, Subscription } from "@lowcoder-ee/constants/subscriptionConstants";
import { getDeploymentId } from "@lowcoder-ee/redux/selectors/configSelectors";
import { getFetchSubscriptionsFinished, getSubscriptions, getSubscriptionsError } from "@lowcoder-ee/redux/selectors/subscriptionSelectors";
@@ -78,17 +78,6 @@ export const SubscriptionContextProvider = (props: {
userId: user.id,
};
- const subscriptionNewCustomer: LowcoderNewCustomer = {
- hostname: domain,
- hostId: deploymentId,
- email: currentUser.email,
- orgId: orgID,
- userId: user.id,
- userName: user.username,
- type: admin,
- companyName: currentOrg?.name || "Unknown",
- };
-
useEffect(() => {
// If products are already loaded in the outer context, reuse them
if (productsLoaded) {
@@ -104,28 +93,11 @@ export const SubscriptionContextProvider = (props: {
const initializeCustomer = async () => {
if (existingCustomer) {
setCustomer(existingCustomer);
+
+ cleanupCustomer(subscriptionSearchCustomer);
+
return;
}
-
- /* try {
- setIsCreatingCustomer(true);
- const subscriptionSearchCustomer: LowcoderSearchCustomer = {
- hostId: deploymentId,
- orgId: orgID,
- userId: user.id,
- };
- const existingCustomer = await searchCustomer(subscriptionSearchCustomer);
- if (existingCustomer) {
- setCustomer(existingCustomer);
- } else {
- const newCustomer = await createCustomer(subscriptionNewCustomer);
- setCustomer(newCustomer);
- }
- } catch (error) {
- setCustomerDataError(true);
- } finally {
- setIsCreatingCustomer(false);
- } */
};
if (!customer && isCustomerInitializationComplete) {
diff --git a/client/packages/lowcoder/src/util/currentUser.tsx b/client/packages/lowcoder/src/util/currentUser.tsx
index b638343ef..506032eda 100644
--- a/client/packages/lowcoder/src/util/currentUser.tsx
+++ b/client/packages/lowcoder/src/util/currentUser.tsx
@@ -1,7 +1,8 @@
import { useSelector } from "react-redux";
-import { getCurrentUser } from "redux/selectors/usersSelectors";
+import { getCurrentUser, getUser } from "redux/selectors/usersSelectors";
export function useCurrentUser() {
const currentUser = useSelector(getCurrentUser);
- return currentUser;
+ const { hasPassword } = useSelector(getUser);
+ return {...currentUser, hasPassword};
}
diff --git a/client/packages/lowcoder/vite.config.mts b/client/packages/lowcoder/vite.config.mts
index 9699e15db..1350607c1 100644
--- a/client/packages/lowcoder/vite.config.mts
+++ b/client/packages/lowcoder/vite.config.mts
@@ -1,5 +1,5 @@
import dotenv from "dotenv";
-import { defineConfig, ServerOptions, UserConfig } from "vite";
+import { defineConfig, PluginOption, ServerOptions, UserConfig } from "vite";
import react from "@vitejs/plugin-react";
import viteTsconfigPaths from "vite-tsconfig-paths";
import svgrPlugin from "vite-plugin-svgr";
@@ -12,6 +12,7 @@ import dynamicImport from 'vite-plugin-dynamic-import';
import { ensureLastSlash } from "./src/dev-utils/util";
import { buildVars } from "./src/dev-utils/buildVars";
import { globalDepPlugin } from "./src/dev-utils/globalDepPlguin";
+import { terser } from 'rollup-plugin-terser';
// import { nodePolyfills } from 'vite-plugin-node-polyfills'
dotenv.config();
@@ -66,6 +67,7 @@ export const viteConfig: UserConfig = {
},
base,
build: {
+ minify: "terser",
manifest: true,
target: "es2020",
cssTarget: "chrome87",
@@ -73,9 +75,117 @@ export const viteConfig: UserConfig = {
assetsDir: "static",
emptyOutDir: false,
rollupOptions: {
+ treeshake: {
+ moduleSideEffects: true,
+ propertyReadSideEffects: false,
+ tryCatchDeoptimization: false,
+ unknownGlobalSideEffects: false,
+ },
output: {
- chunkFileNames: "[hash].js",
+ inlineDynamicImports: false,
+ chunkFileNames: "[name]-[hash].js",
+ manualChunks: (id) => {
+ if (id.includes("node_modules")) {
+ // UI LIBRARIES
+ if (id.includes("@ant-design/icons")) return "ant-design-icons";
+ if (id.includes("node_modules/antd")) return "antd";
+ if (id.includes("styled-components")) return "styled-components";
+
+ // 🔹 BARCODE & QR CODE PROCESSING
+ if (id.includes("react-qr-barcode-scanner")) return "barcode";
+
+ // TEXT EDITORS & PARSERS
+ if (id.includes("codemirror")) return "codemirror";
+ if (id.includes("quill")) return "quill";
+ if (id.includes("react-json-view")) return "react-json-view";
+ if (id.includes("react-quill")) return "react-quill";
+ if (id.includes("remark-gfm")) return "remark-gfm";
+ if (id.includes("rehype-raw")) return "rehype-raw";
+ if (id.includes("rehype-sanitize")) return "rehype-sanitize";
+
+ // DRAG & DROP
+ if (id.includes("@dnd-kit")) return "dnd-kit";
+ if (id.includes("react-draggable")) return "react-draggable";
+ if (id.includes("react-grid-layout")) return "react-grid-layout";
+ if (id.includes("react-sortable-hoc")) return "react-sortable-hoc";
+
+ // ICONS & FONTS
+ if (id.includes("@fortawesome")) return "fontawesome";
+ if (id.includes("@remixicon")) return "remixicon";
+
+ // DATE/TIME HANDLING
+ if (id.includes("moment")) return "moment";
+ if (id.includes("date-fns")) return "date-fns";
+ if (id.includes("dayjs")) return "dayjs";
+
+ // UTILITIES & HELPERS
+ if (id.includes("clsx")) return "clsx";
+ if (id.includes("immer")) return "immer";
+ if (id.includes("lodash")) return "lodash";
+ if (id.includes("lodash-es")) return "lodash-es";
+ if (id.includes("uuid")) return "uuid";
+ if (id.includes("ua-parser-js")) return "ua-parser-js";
+ if (id.includes("html2canvas")) return "ua-parser-js";
+ if (id.includes("numbro")) return "numbro";
+
+ // FILE & DATA PROCESSING
+ if (id.includes("buffer")) return "buffer";
+ if (id.includes("file-saver")) return "file-saver";
+ if (id.includes("papaparse")) return "papaparse";
+ if (id.includes("parse5")) return "parse5";
+ if (id.includes("xlsx")) return "xlsx";
+ if (id.includes("alasql")) return "alasql";
+ if (id.includes("sql-formatter")) return "sql-formatter";
+
+ // NETWORK & HTTP
+ if (id.includes("axios")) return "axios";
+ if (id.includes("fetch")) return "fetch";
+ if (id.includes("http")) return "http-modules";
+ if (id.includes("https")) return "https-modules";
+
+ // WEB SOCKETS & STREAMING
+ if (id.includes("sockjs")) return "websockets";
+ if (id.includes("websocket")) return "websockets";
+
+ // STATE MANAGEMENT
+ if (id.includes("react-error-boundary")) return "react-error-boundary";
+ if (id.includes("redux-devtools-extension")) return "redux-devtools";
+
+ // POLYFILLS & BROWSER COMPATIBILITY
+ // if (id.includes("core-js")) return "core-js";
+ if (id.includes("regenerator-runtime")) return "regenerator-runtime";
+ if (id.includes("eslint4b-prebuilt-2")) return "eslint4b-prebuilt-2";
+
+ // MISCELLANEOUS
+ if (id.includes("cnchar")) return "cnchar";
+ if (id.includes("hotkeys-js")) return "hotkeys-js";
+ if (id.includes("loglevel")) return "loglevel";
+ if (id.includes("qrcode.react")) return "qrcode-react";
+ if (id.includes("react-joyride")) return "react-joyride";
+ if (id.includes("rc-trigger")) return "rc-trigger";
+ if (id.includes("really-relaxed-json")) return "really-relaxed-json";
+ if (id.includes("simplebar-react")) return "simplebar-react";
+ if (id.includes("react-documents")) return "react-documents";
+ if (id.includes("react-colorful")) return "react-colorful";
+ if (id.includes("react-best-gradient-color-picker")) return "react-best-gradient-color-picker";
+ if (id.includes("@supabase/supabase-js")) return "supabase";
+ return null;
+ }
+ return null;
+ },
},
+ plugins: [
+ terser({
+ compress: {
+ drop_console: true,
+ drop_debugger: true,
+ pure_funcs: ["console.info", "console.debug", "console.log"],
+ },
+ format: {
+ comments: /(@vite-ignore|webpackIgnore)/
+ },
+ }) as PluginOption,
+ ],
onwarn: (warning, warn) => {
if (warning.code === 'MODULE_LEVEL_DIRECTIVE') {
return
@@ -84,6 +194,7 @@ export const viteConfig: UserConfig = {
},
},
commonjsOptions: {
+ transformMixedEsModules : true,
defaultIsModuleExports: (id) => {
if (id.indexOf("antd/lib") !== -1) {
return false;
@@ -178,7 +289,7 @@ const browserCheckConfig: UserConfig = {
copyPublicDir: true,
emptyOutDir: true,
lib: {
- formats: ["iife"],
+ formats: ["es"],
name: "BrowserCheck",
entry: "./src/browser-check.ts",
fileName: () => {
diff --git a/client/yarn.lock b/client/yarn.lock
index 1589f0bb7..7fae135fa 100644
--- a/client/yarn.lock
+++ b/client/yarn.lock
@@ -1785,6 +1785,15 @@ __metadata:
languageName: node
linkType: hard
+"@babel/runtime@npm:^7.13.9":
+ version: 7.26.9
+ resolution: "@babel/runtime@npm:7.26.9"
+ dependencies:
+ regenerator-runtime: ^0.14.0
+ checksum: 838492d8a925092f9ccfbd82ec183a54f430af3a4ce88fb1337a4570629202d5123bad3097a5b8df53822504d12ccb29f45c0f6842e86094f0164f17a51eec92
+ languageName: node
+ linkType: hard
+
"@babel/runtime@npm:^7.25.7, @babel/runtime@npm:^7.26.0":
version: 7.26.7
resolution: "@babel/runtime@npm:7.26.7"
@@ -4484,7 +4493,7 @@ __metadata:
languageName: node
linkType: hard
-"@types/babel__core@npm:^7.1.14":
+"@types/babel__core@npm:^7.1.12, @types/babel__core@npm:^7.1.14":
version: 7.20.5
resolution: "@types/babel__core@npm:7.20.5"
dependencies:
@@ -6652,6 +6661,37 @@ __metadata:
languageName: node
linkType: hard
+"babel-plugin-transform-vite-meta-env@npm:1.0.3":
+ version: 1.0.3
+ resolution: "babel-plugin-transform-vite-meta-env@npm:1.0.3"
+ dependencies:
+ "@babel/runtime": ^7.13.9
+ "@types/babel__core": ^7.1.12
+ checksum: 781b4f7d9e7497e869d87749a6d0a13a882c19995e3d97262622d6bfaab0d6da1a182f8440facab8316f1360070bbd7ca6898b1c70400645d1f52990f960b801
+ languageName: node
+ linkType: hard
+
+"babel-plugin-transform-vite-meta-glob@npm:1.1.2":
+ version: 1.1.2
+ resolution: "babel-plugin-transform-vite-meta-glob@npm:1.1.2"
+ dependencies:
+ "@babel/runtime": ^7.13.9
+ "@types/babel__core": ^7.1.12
+ glob: ^10.3.10
+ checksum: 8a73f38a0827f07f2e5cd8f41066eb7fac08ec2ce900adc671cae817a55faf349f4f17946971d3fd80eb5f31657cd58c44e6da8f5a47668e39da0d90facd64bd
+ languageName: node
+ linkType: hard
+
+"babel-plugin-transform-vite-meta-hot@npm:1.0.0":
+ version: 1.0.0
+ resolution: "babel-plugin-transform-vite-meta-hot@npm:1.0.0"
+ dependencies:
+ "@babel/runtime": ^7.13.9
+ "@types/babel__core": ^7.1.12
+ checksum: bcaeecbe89f6f279c8bf90afa2cec0f3e86576179b268cefba9acac4070799a243e66d6e31ec6283068df964a5beb746390ed025b52bb6fc651e69a1610ccaa5
+ languageName: node
+ linkType: hard
+
"babel-preset-current-node-syntax@npm:^1.0.0":
version: 1.0.1
resolution: "babel-preset-current-node-syntax@npm:1.0.1"
@@ -6710,6 +6750,19 @@ __metadata:
languageName: node
linkType: hard
+"babel-preset-vite@npm:^1.1.3":
+ version: 1.1.3
+ resolution: "babel-preset-vite@npm:1.1.3"
+ dependencies:
+ "@babel/runtime": ^7.13.9
+ "@types/babel__core": ^7.1.12
+ babel-plugin-transform-vite-meta-env: 1.0.3
+ babel-plugin-transform-vite-meta-glob: 1.1.2
+ babel-plugin-transform-vite-meta-hot: 1.0.0
+ checksum: 243b43c25846a597a03cf36b1b0e6b39d209f5a13207a238bdc9a03b61fcdd450abe2a26595cde17513c321ba63071868def875a54664e45058b5c532f8306a4
+ languageName: node
+ linkType: hard
+
"bail@npm:^2.0.0":
version: 2.0.2
resolution: "bail@npm:2.0.2"
@@ -7339,6 +7392,13 @@ __metadata:
languageName: node
linkType: hard
+"claygl@npm:^1.2.1":
+ version: 1.3.0
+ resolution: "claygl@npm:1.3.0"
+ checksum: cbf3c4788b426ecc183e0fc5f7e3f88fae15d616ebf39467cb719c1f78efbef8bbe92f8def22c927a9d3cbb2a3ae6d1194755edae96d5f623b4dca0b78bdefa8
+ languageName: node
+ linkType: hard
+
"clean-css@npm:^5.2.2":
version: 5.3.3
resolution: "clean-css@npm:5.3.3"
@@ -9234,6 +9294,18 @@ coolshapes-react@lowcoder-org/coolshapes-react:
languageName: node
linkType: hard
+"echarts-gl@npm:^2.0.9":
+ version: 2.0.9
+ resolution: "echarts-gl@npm:2.0.9"
+ dependencies:
+ claygl: ^1.2.1
+ zrender: ^5.1.1
+ peerDependencies:
+ echarts: ^5.1.2
+ checksum: d07dfeb093c5ca05a671317a8f4f4be7fffaa12fb91d485ab19c65d740bbf3c08b02b57c4d7b772bc3ce025184843f1a44ba8bdfc3d48257a46684a5d10fb941
+ languageName: node
+ linkType: hard
+
"echarts-wordcloud@npm:^2.1.0":
version: 2.1.0
resolution: "echarts-wordcloud@npm:2.1.0"
@@ -13932,6 +14004,7 @@ coolshapes-react@lowcoder-org/coolshapes-react:
agora-rtm-sdk: ^1.5.1
big.js: ^6.2.1
echarts-extension-gmap: ^1.6.0
+ echarts-gl: ^2.0.9
echarts-wordcloud: ^2.1.0
jest: 29.3.0
lowcoder-cli: "workspace:^"
@@ -14035,6 +14108,7 @@ coolshapes-react@lowcoder-org/coolshapes-react:
antd-mobile: ^5.34.0
babel-jest: ^29.3.0
babel-preset-react-app: ^10.0.1
+ babel-preset-vite: ^1.1.3
chalk: 4
flag-icons: ^7.2.1
husky: ^8.0.1
@@ -14242,6 +14316,7 @@ coolshapes-react@lowcoder-org/coolshapes-react:
rehype-sanitize: ^5.0.1
remark-gfm: ^4.0.0
resize-observer-polyfill: ^1.5.1
+ rollup-plugin-terser: ^7.0.2
rollup-plugin-visualizer: ^5.9.2
simplebar-react: ^3.2.4
sql-formatter: ^8.2.0
@@ -22680,6 +22755,15 @@ coolshapes-react@lowcoder-org/coolshapes-react:
languageName: node
linkType: hard
+"zrender@npm:^5.1.1":
+ version: 5.6.1
+ resolution: "zrender@npm:5.6.1"
+ dependencies:
+ tslib: 2.3.0
+ checksum: 01caeac2d30f0083009aafa531ccb7fe991b6ac0ddd8134dc7b0015f794ed7e3d4fbfe5d32f61cb591014245eca15aeebcfc962cdebfe3829598f0c94ba3dc29
+ languageName: node
+ linkType: hard
+
"zwitch@npm:^2.0.0":
version: 2.0.4
resolution: "zwitch@npm:2.0.4"
diff --git a/docs/lowcoder-extension/opensource-contribution/develop-data-source-plugins.md b/docs/lowcoder-extension/opensource-contribution/develop-data-source-plugins.md
index edd912076..7ff5814e8 100644
--- a/docs/lowcoder-extension/opensource-contribution/develop-data-source-plugins.md
+++ b/docs/lowcoder-extension/opensource-contribution/develop-data-source-plugins.md
@@ -1,6 +1,6 @@
# Develop Data Source Plugins
-This document provides basic information and guides for developing data source plugins. Developers are highly welcomed to make contributions to [Lowcoder](https://github.com/Lowcoder-dev/Lowcoder)--the open source project.
+This document provides basic information and guides for developing data source plugins. Developers are highly welcomed to make contributions to [Lowcoder](https://github.com/lowcoder-org/lowcoder)--the open source project.
## Basics
@@ -12,7 +12,7 @@ A data source plugin is described by a **JavaScript Object** which mainly consis
* Definition of the **Action list** for data source queries and the configuration form for each Action.
* Definition of the **execution logic** for Actions.
-Currently, all data source plugins are maintained in the `src/plugins` directory of the `node-service` project. Click to view [the project](https://github.com/Lowcoder-dev/Lowcoder/tree/develop/server/node-service), and you might take a quick look at the [S3 plugin](https://github.com/Lowcoder-dev/Lowcoder/tree/develop/server/node-service/src/plugins/s3).
+Currently, all data source plugins are maintained in the `src/plugins` directory of the `node-service` project. Click to view [the project](https://github.com/lowcoder-org/lowcoder/tree/main/server/node-service), and you might take a quick look at the [S3 plugin](https://github.com/lowcoder-org/lowcoder/tree/main/server/node-service/src/plugins/s3).
## Overall definition of a plugin
@@ -268,7 +268,7 @@ Due to various reasons, the generated plugin code needs to be correctly validate
## Testing
-Necessary testing should be done before publishing the plugin. Testing a data source plugin requires a backend environment. You can start a local environment by following the documentation [Start a local backend server](https://github.com/Lowcoder-dev/Lowcoder/tree/develop/client#readme) and test the data source plugin in following aspects:
+Necessary testing should be done before publishing the plugin. Testing a data source plugin requires a backend environment. You can start a local environment by following the documentation [Start a local backend server](https://github.com/lowcoder-org/lowcoder/tree/main/server/api-service#readme) and test the data source plugin in following aspects:
1. Make sure the data source plugin has been added to the plugin list in the file `src/plugins/index.ts`.
2. Start the node-service server in the `node-service` directory by executing `yarn dev`.
@@ -292,4 +292,4 @@ You can then use the data source plugin just developed in this environment.
## What's next
-Congrats! After testing the data source plugin, you can submit a [Pull Request](https://github.com/Lowcoder-dev/Lowcoder/pulls) now.
+Congrats! After testing the data source plugin, you can submit a [Pull Request](https://github.com/lowcoder-org/lowcoder/pulls) now.
diff --git a/docs/setup-and-run/self-hosting/heroku.md b/docs/setup-and-run/self-hosting/heroku.md
index 460850231..133252d19 100644
--- a/docs/setup-and-run/self-hosting/heroku.md
+++ b/docs/setup-and-run/self-hosting/heroku.md
@@ -3,7 +3,7 @@
## Deploy
1. [Sign up](https://signup.heroku.com/) for a new Heroku account, or [log in](https://id.heroku.com/login) to get started.
-2. Click to start Heroku [one-click deployment](https://heroku.com/deploy?template=https://github.com/Lowcoder-dev/Lowcoder).
+2. Click to start Heroku [one-click deployment](https://heroku.com/deploy?template=https://github.com/lowcoder-org/lowcoder).
3. Set the **App name** which will be part of the app URL later, and choose a region.
4. (Not required) Fill in the **Config Vars** according to the descriptions. These are all optional variables used for environment-specific configuration. You can skip this step and manage environment variables later.
5. Click the **Deploy app** button.
diff --git a/server/api-service/lowcoder-dependencies/pom.xml b/server/api-service/lowcoder-dependencies/pom.xml
index 3f8b6b703..0787bcfcf 100644
--- a/server/api-service/lowcoder-dependencies/pom.xml
+++ b/server/api-service/lowcoder-dependencies/pom.xml
@@ -26,7 +26,7 @@
org.lowcoder.plugin
lowcoder-plugin-api
- 2.3.0
+ 2.3.1
diff --git a/server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/application/model/Application.java b/server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/application/model/Application.java
index 84d0264e6..3e15e9aa9 100644
--- a/server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/application/model/Application.java
+++ b/server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/application/model/Application.java
@@ -47,6 +47,7 @@ public class Application extends HasIdAndAuditing {
private Integer applicationType;
private ApplicationStatus applicationStatus;
+ @Setter
private Map editingApplicationDSL;
@Setter
diff --git a/server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/bundle/repository/BundleRepository.java b/server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/bundle/repository/BundleRepository.java
index 70180fb06..9670cc525 100644
--- a/server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/bundle/repository/BundleRepository.java
+++ b/server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/bundle/repository/BundleRepository.java
@@ -13,6 +13,7 @@
public interface BundleRepository extends ReactiveMongoRepository {
Mono deleteAllByGid(Collection gids);
Flux findByGid(@Nonnull String gid);
+ Flux findAllByGid(Collection gids);
Flux findByCreatedBy(String userId);
/**
diff --git a/server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/bundle/service/BundleService.java b/server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/bundle/service/BundleService.java
index 646d2eff1..5518d82fd 100644
--- a/server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/bundle/service/BundleService.java
+++ b/server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/bundle/service/BundleService.java
@@ -16,6 +16,7 @@ public interface BundleService {
Mono updateById(String id, Bundle resource);
Mono findById(String id);
+ Flux findByIdIn(Collection ids);
Mono findByIdWithoutDsl(String id);
diff --git a/server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/bundle/service/BundleServiceImpl.java b/server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/bundle/service/BundleServiceImpl.java
index 611f74d4c..48550aec3 100644
--- a/server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/bundle/service/BundleServiceImpl.java
+++ b/server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/bundle/service/BundleServiceImpl.java
@@ -20,6 +20,7 @@
import java.util.Collection;
import java.util.Map;
+import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
@@ -56,6 +57,15 @@ public Mono