diff --git a/plugins/panel/radar/Editor.tsx b/plugins/panel/radar/Editor.tsx
new file mode 100644
index 000000000..b64c89690
--- /dev/null
+++ b/plugins/panel/radar/Editor.tsx
@@ -0,0 +1,112 @@
+// Copyright 2023 Datav.io Team
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+import { Select, Switch, Textarea } from "@chakra-ui/react"
+import PanelAccordion from "src/views/dashboard/edit-panel/Accordion"
+import PanelEditItem from "src/views/dashboard/edit-panel/PanelEditItem"
+import { Panel, PanelEditorProps } from "types/dashboard"
+import React, { memo } from "react";
+import { useStore } from "@nanostores/react"
+import { commonMsg } from "src/i18n/locales/en"
+import { PluginSettings, initSettings, } from "./types"
+import { dispatch } from "use-bus";
+import { PanelForceRebuildEvent } from "src/data/bus-events";
+import { defaultsDeep } from "lodash";
+import RadionButtons from "components/RadioButtons";
+import { EditorNumberItem } from "components/editor/EditorItem";
+
+
+const PanelEditor = memo(({ panel, onChange }: PanelEditorProps) => {
+ const t = useStore(commonMsg)
+ panel.plugins[panel.type] = defaultsDeep(panel.plugins[panel.type], initSettings)
+ const options: PluginSettings = panel.plugins[panel.type]
+ return (
+ <>
+
+
+ onChange((panel: Panel) => {
+ const plugin: PluginSettings = panel.plugins[panel.type]
+ plugin.animation = e.currentTarget.checked
+ // force the panel to rebuild to avoid some problems
+ dispatch(PanelForceRebuildEvent + panel.id)
+ })} />
+
+
+
+
+
+
+
+ onChange((panel: Panel) => {
+ const plugin: PluginSettings = panel.plugins[panel.type]
+ plugin.graph.legend.mode = v
+ dispatch(PanelForceRebuildEvent + panel.id)
+ })} />
+
+
+
+
+
+ {
+ const plugin: PluginSettings = panel.plugins[panel.type]
+ plugin.graph.legend.top = e
+ dispatch(PanelForceRebuildEvent + panel.id)
+ }} />
+
+
+ {
+ const plugin: PluginSettings = panel.plugins[panel.type]
+ plugin.graph.legend.bottom = e
+ dispatch(PanelForceRebuildEvent + panel.id)
+ }} />
+
+
+ {
+ const plugin: PluginSettings = panel.plugins[panel.type]
+ plugin.graph.legend.left = e
+ dispatch(PanelForceRebuildEvent + panel.id)
+ }} />
+
+
+ {
+ const plugin: PluginSettings = panel.plugins[panel.type]
+ plugin.graph.legend.right = e
+ dispatch(PanelForceRebuildEvent + panel.id)
+ }} />
+
+
+ {
+ const plugin: PluginSettings = panel.plugins[panel.type]
+ plugin.graph.legend.itemGap = e
+ dispatch(PanelForceRebuildEvent + panel.id)
+ }} />
+
+
+ >
+ )
+})
+
+export default PanelEditor
\ No newline at end of file
diff --git a/plugins/panel/radar/OverrideEditor.tsx b/plugins/panel/radar/OverrideEditor.tsx
new file mode 100644
index 000000000..79146b874
--- /dev/null
+++ b/plugins/panel/radar/OverrideEditor.tsx
@@ -0,0 +1,38 @@
+// Copyright 2023 Datav.io Team
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import { OverrideRule } from "types/dashboard";
+import React from "react";
+
+interface Props {
+ override: OverrideRule
+ onChange: any
+}
+
+
+const OverrideEditor = (props: Props) => {
+ return <>>
+}
+
+export default OverrideEditor
+
+export enum OverrideRules {
+ // basic
+}
+
+// The above example will get targets from SeriesData, Table and Graph panels are using this method to get targets
+// If return [] or null or undefined, Datav will use the default function to get override targets
+export const getOverrideTargets = (panel, data) => {
+ // for demonstration purpose, we just return a hard coded targets list
+ return []
+}
\ No newline at end of file
diff --git a/plugins/panel/radar/Panel.tsx b/plugins/panel/radar/Panel.tsx
new file mode 100644
index 000000000..6f5745268
--- /dev/null
+++ b/plugins/panel/radar/Panel.tsx
@@ -0,0 +1,69 @@
+// Copyright 2023 Datav.io Team
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+import { Box, Center, Text, useColorMode } from "@chakra-ui/react";
+import ChartComponent from "src/components/charts/Chart";
+import { memo, useMemo, useState } from "react";
+import { PanelProps } from "types/dashboard"
+import { FieldType, SeriesData } from "types/seriesData";
+import React from "react";
+import { isEmpty } from "utils/validate";
+import NoData from "src/views/dashboard/components/PanelNoData";
+import { defaultsDeep } from "lodash";
+import { PluginSettings, initSettings } from "./types";
+import { buildOptions } from "./buildOptions";
+import mockData from './mockData.json'
+import { isSeriesData } from "utils/seriesData";
+
+interface Props extends PanelProps {
+ data: SeriesData[][]
+}
+
+const PanelComponentWrapper = memo((props: Props) => {
+ const d: SeriesData[] = props.data.flat()
+ if (isEmpty(d)) {
+ return
+ }
+
+ return (<>
+
+ >
+ )
+})
+
+export default PanelComponentWrapper
+
+const PanelComponent = (props: Props) => {
+ const { panel, height, width } = props
+ const [chart, setChart] = useState(null)
+ const { colorMode } = useColorMode()
+
+
+ // init panel plugin settings
+ props.panel.plugins[panel.type] = defaultsDeep(props.panel.plugins[panel.type], initSettings)
+ // give plugin settings a name for easy access
+ const options: PluginSettings = props.panel.plugins[panel.type]
+
+ const echartOptions = useMemo(() => {
+ // transform SeriesData to candlestick data format
+ const option = buildOptions(panel, props.data.flat(), colorMode)
+ return option
+ }, [props.data, panel.overrides, colorMode, options])
+
+ return (<>
+ {options && setChart(c)} onChartEvents={null} />}
+ >)
+}
+
+export const mockDataForTestDataDs = () => {
+ return mockData
+}
diff --git a/plugins/panel/radar/buildOptions.ts b/plugins/panel/radar/buildOptions.ts
new file mode 100644
index 000000000..335102695
--- /dev/null
+++ b/plugins/panel/radar/buildOptions.ts
@@ -0,0 +1,50 @@
+import { Panel } from "types/dashboard";
+import { SeriesData } from "types/seriesData";
+import { PluginSettings } from "./types";
+
+
+export const buildOptions = (panel: Panel, data: SeriesData[], colorMode: "light" | "dark") => {
+ const options: PluginSettings = panel.plugins[panel.type]
+
+ const legend = data.map(item => item.name)
+ const seriesData = legend.map(i => ({ name: i, value: [] }))
+ const indicator = {}
+ data.forEach(item => {
+ item.fields.forEach(field => {
+ const total = field.values.reduce((a, b) => a + b)
+ if (indicator[field.name] && indicator[field.name] > total) {
+ indicator[field.name] = field.values.reduce((a, b) => a + b)
+ } else {
+ indicator[field.name] = field.values.reduce((a, b) => a + b)
+ }
+ const idx = seriesData.findIndex(i => i.name === item.name)
+ seriesData[idx].value.push(total)
+ })
+ })
+ const opts = {
+ darkMode: colorMode === 'dark',
+ legend: {
+ data: legend,
+ show: options.graph.legend.mode,
+ top: options.graph.legend.top,
+ bottom: options.graph.legend.bottom,
+ left: options.graph.legend.left,
+ right: options.graph.legend.right,
+ orient: options.graph.legend.orient,
+ itemGap: options.graph.legend.itemGap,
+ },
+ animation: options.animation,
+ radar: {
+ shape: options.radar.shape,
+ indicator: Object.keys(indicator).map(key => ({ name: key, value: indicator[key] * 1.25 })),
+ },
+ series: [
+ {
+ type: 'radar',
+ data: seriesData,
+ }
+ ]
+ }
+
+ return opts
+}
\ No newline at end of file
diff --git a/plugins/panel/radar/icon.svg b/plugins/panel/radar/icon.svg
new file mode 100644
index 000000000..345057093
--- /dev/null
+++ b/plugins/panel/radar/icon.svg
@@ -0,0 +1,1593 @@
+
+
+
diff --git a/plugins/panel/radar/index.ts b/plugins/panel/radar/index.ts
new file mode 100644
index 000000000..26efca75c
--- /dev/null
+++ b/plugins/panel/radar/index.ts
@@ -0,0 +1,23 @@
+import { PanelPluginComponents } from "types/plugin";
+import PanelComponent, { mockDataForTestDataDs } from "./Panel";
+import PanelEditor from "./Editor";
+import OverrideEditor, { OverrideRules, getOverrideTargets } from "./OverrideEditor";
+import icon from './icon.svg'
+import { PanelTypeRadar, initSettings } from "./types";
+
+
+const panelComponents: PanelPluginComponents = {
+ panel: PanelComponent,
+ editor: PanelEditor,
+ overrideEditor: OverrideEditor,
+ overrideRules: OverrideRules,
+ getOverrideTargets: getOverrideTargets,
+ mockDataForTestDataDs: mockDataForTestDataDs,
+ settings: {
+ type: PanelTypeRadar,
+ icon,
+ initOptions: initSettings
+ }
+}
+
+export default panelComponents
\ No newline at end of file
diff --git a/plugins/panel/radar/mockData.json b/plugins/panel/radar/mockData.json
new file mode 100644
index 000000000..e91d4e7d2
--- /dev/null
+++ b/plugins/panel/radar/mockData.json
@@ -0,0 +1,125 @@
+[
+ {
+ "name": "Beijing",
+ "fields": [
+ {
+ "name": "PM2.5",
+ "type": "number",
+ "values": [
+ 10,
+ 20,
+ 30
+ ]
+ },
+ {
+ "name": "PM10",
+ "type": "number",
+ "values": [
+ 15,
+ 25,
+ 35
+ ]
+ },
+ {
+ "name": "CO",
+ "type": "number",
+ "values": [
+ 15,
+ 25,
+ 35
+ ]
+ },
+ {
+ "name": "NO2",
+ "type": "number",
+ "values": [
+ 25,
+ 27,
+ 30
+ ]
+ }
+ ]
+ },
+ {
+ "name": "Shanghai",
+ "fields": [
+ {
+ "name": "PM2.5",
+ "type": "number",
+ "values": [
+ 13,
+ 17,
+ 20
+ ]
+ },
+ {
+ "name": "PM10",
+ "type": "number",
+ "values": [
+ 15,
+ 27,
+ 40
+ ]
+ },
+ {
+ "name": "CO",
+ "type": "number",
+ "values": [
+ 35,
+ 47,
+ 60
+ ]
+ },
+ {
+ "name": "NO2",
+ "type": "number",
+ "values": [
+ 35,
+ 47,
+ 60
+ ]
+ }
+ ]
+ },
+ {
+ "name": "Shenzhen",
+ "fields": [
+ {
+ "name": "PM2.5",
+ "type": "number",
+ "values": [
+ 5,
+ 7,
+ 13
+ ]
+ },
+ {
+ "name": "PM10",
+ "type": "number",
+ "values": [
+ 19,
+ 26,
+ 50
+ ]
+ },
+ {
+ "name": "CO",
+ "type": "number",
+ "values": [
+ 15,
+ 27,
+ 30
+ ]
+ },
+ {
+ "name": "NO2",
+ "type": "number",
+ "values": [
+ 42,
+ 56,
+ 60
+ ]
+ }
+ ]
+ }
+]
\ No newline at end of file
diff --git a/plugins/panel/radar/types.ts b/plugins/panel/radar/types.ts
new file mode 100644
index 000000000..a1874741e
--- /dev/null
+++ b/plugins/panel/radar/types.ts
@@ -0,0 +1,36 @@
+export const PanelTypeRadar = "radar"
+
+export interface PluginSettings {
+ animation: boolean
+ graph: {
+ legend: {
+ mode: boolean
+ left?: number
+ right?: number
+ top?: number
+ bottom?: number
+ orient?: string
+ itemGap?: number
+ }
+ }
+ radar: {
+ shape?: string
+ }
+}
+
+
+export const initSettings: PluginSettings = {
+ animation: false,
+ radar: {
+ shape: 'polygon'
+ },
+ graph: {
+ legend: {
+ mode: true,
+ right: 0,
+ top: 0,
+ orient: 'vertical',
+ itemGap: 20
+ }
+ }
+}
\ No newline at end of file
diff --git a/ui/src/views/dashboard/grid/PanelGrid/PanelGrid.tsx b/ui/src/views/dashboard/grid/PanelGrid/PanelGrid.tsx
index 91f48176a..6380a4394 100644
--- a/ui/src/views/dashboard/grid/PanelGrid/PanelGrid.tsx
+++ b/ui/src/views/dashboard/grid/PanelGrid/PanelGrid.tsx
@@ -195,7 +195,7 @@ export const PanelComponent = ({ dashboard, panel, variables, onRemovePanel, onH
if (!plugin) {
setQueryError("Datasource plugin not found: " + datasource.type)
setPanelData([])
- return
+ return
}
setLoading(true)
@@ -206,6 +206,7 @@ export const PanelComponent = ({ dashboard, panel, variables, onRemovePanel, onH
} else {
const promises = []
for (const q0 of ds.queries) {
+ console.log('===>', ds.queries)
if (!q0.visible) {
continue
}
diff --git a/ui/src/views/dashboard/plugins/built-in/panel/echarts/Echarts.tsx b/ui/src/views/dashboard/plugins/built-in/panel/echarts/Echarts.tsx
index 29c68ebc9..73c94a1f1 100644
--- a/ui/src/views/dashboard/plugins/built-in/panel/echarts/Echarts.tsx
+++ b/ui/src/views/dashboard/plugins/built-in/panel/echarts/Echarts.tsx
@@ -20,7 +20,7 @@ import { cloneDeep, isEmpty, isFunction } from "lodash";
import { useSearchParam } from "react-use";
import React from "react";
import moment from "moment";
-import { paletteMap, palettes } from "utils/colors";
+import { paletteMap, palettes } from "utils/colors";
import loadash from "lodash"
import 'echarts/extension/bmap/bmap';
import { genDynamicFunction } from "utils/dashboard/dynamicCall";
@@ -86,7 +86,7 @@ const EchartsPanel = memo((props: PanelProps) => {
if (options) {
options.animation = panel.plugins.echarts.animation
}
-
+
return [options, onEvents]
}, [panel.plugins.echarts, props.data, chart])
@@ -147,7 +147,7 @@ export const EchartsComponent = ({ options, theme, width, height, onChartCreated
useEffect(() => {
if (onChartEvents && chart) {
onChartEvents(options, chart, gnavigate, (k, v) => setVariable(k, v), setDateTime, $variables)
- }
+ }
}, [onChartEvents])
useEffect(() => {
diff --git a/ui/src/views/dashboard/plugins/built-in/panel/echarts/index.ts b/ui/src/views/dashboard/plugins/built-in/panel/echarts/index.ts
index f7aa73e49..63ad3a4da 100644
--- a/ui/src/views/dashboard/plugins/built-in/panel/echarts/index.ts
+++ b/ui/src/views/dashboard/plugins/built-in/panel/echarts/index.ts
@@ -10,7 +10,7 @@ import { PanelTypeEcharts } from "./types";
const panelComponents: PanelPluginComponents = {
panel: EchartsPanel,
editor: PanelEditor,
- mockDataForTestDataDs: mockEchartsDataForTestDataDs,
+ mockDataForTestDataDs: mockEchartsDataForTestDataDs,
settings: {
type: PanelTypeEcharts,
icon,
@@ -43,4 +43,4 @@ function registerEvents(options, chart, navigate, setVariable, setDateTime, $var
}
}
-export default panelComponents
\ No newline at end of file
+export default panelComponents
\ No newline at end of file
diff --git a/ui/src/views/dashboard/plugins/external/panel/candlestick/Editor.tsx b/ui/src/views/dashboard/plugins/external/panel/candlestick/Editor.tsx
index e2b53796c..d27d1c2a5 100644
--- a/ui/src/views/dashboard/plugins/external/panel/candlestick/Editor.tsx
+++ b/ui/src/views/dashboard/plugins/external/panel/candlestick/Editor.tsx
@@ -55,12 +55,12 @@ const PanelEditor = memo(({ panel, onChange }: CandleEditorProps) => {
})} />
- onChange((panel: Panel) => {
+ onChange((panel: Panel) => {
panel.plugins[PanelTypeCandle].kChart.upColor = v
})} />
- onChange((panel: Panel) => {
+ onChange((panel: Panel) => {
panel.plugins[PanelTypeCandle].kChart.downColor = v
})} />
@@ -110,7 +110,7 @@ const PanelEditor = memo(({ panel, onChange }: CandleEditorProps) => {
} />
- onChange((panel: Panel) => { panel.plugins[PanelTypeCandle].volumeChart.value.decimal = v })} />
+ onChange((panel: Panel) => { panel.plugins[PanelTypeCandle].volumeChart.value.decimal = v })} />
@@ -145,7 +145,7 @@ const PanelEditor = memo(({ panel, onChange }: CandleEditorProps) => {
} />
- onChange((panel: Panel) => { panel.plugins[PanelTypeCandle].value.decimal = v })} />
+ onChange((panel: Panel) => { panel.plugins[PanelTypeCandle].value.decimal = v })} />
{/* {
@@ -160,7 +160,7 @@ const PanelEditor = memo(({ panel, onChange }: CandleEditorProps) => {
})} />
- onChange((panel: Panel) => { panel.plugins[PanelTypeCandle].maLine.lineWidth = v })} />
+ onChange((panel: Panel) => { panel.plugins[PanelTypeCandle].maLine.lineWidth = v })} />
onChange((panel: Panel) => {
diff --git a/ui/src/views/dashboard/plugins/external/panel/candlestick/buildOptions.ts b/ui/src/views/dashboard/plugins/external/panel/candlestick/buildOptions.ts
index f06ef672e..918c222fc 100644
--- a/ui/src/views/dashboard/plugins/external/panel/candlestick/buildOptions.ts
+++ b/ui/src/views/dashboard/plugins/external/panel/candlestick/buildOptions.ts
@@ -13,10 +13,10 @@ export const buildOptions = (panel: Panel, data: SeriesData[], colorMode: "light
const upColor = paletteColorNameToHex(options.kChart.upColor, colorMode)
const downColor = paletteColorNameToHex(options.kChart.downColor, colorMode)
-
+
// Each item: open,close,lowest,highest
const series = cloneDeep(data[0])
- const kChartName = isEmpty(options.kChart.displayName) ? (isEmpty(series.name) ? "K" : series.name) : options.kChart.displayName
+ const kChartName = isEmpty(options.kChart.displayName) ? (isEmpty(series.name) ? "K" : series.name) : options.kChart.displayName
const data0 = splitData(transformSeriesDataToCandlestickFormat(series));
function splitData(rawData) {
let categoryData = [];
@@ -26,7 +26,7 @@ export const buildOptions = (panel: Panel, data: SeriesData[], colorMode: "light
categoryData.push(rawData[i].splice(0, 1)[0]);
values.push(rawData[i]);
if (rawData[i][4]) {
- volumes.push([i, rawData[i][4], rawData[i][0] > rawData[i][1] ? 1 : -1]);
+ volumes.push([i, rawData[i][4], rawData[i][0] > rawData[i][1] ? 1 : -1]);
}
}
@@ -95,7 +95,7 @@ export const buildOptions = (panel: Panel, data: SeriesData[], colorMode: "light
left: '5%',
top: '65%',
height: '13%'
- }]): []
+ }]) : []
const volumeOverride = findOverride(panel, "Volume")
const ma5verride = findOverride(panel, "MA5")
@@ -103,7 +103,7 @@ export const buildOptions = (panel: Panel, data: SeriesData[], colorMode: "light
const ma20verride = findOverride(panel, "MA20")
const ma30verride = findOverride(panel, "MA30")
- return {
+ return {
animation: options.animation,
tooltip: [{
trigger: 'axis',
@@ -236,7 +236,7 @@ export const buildOptions = (panel: Panel, data: SeriesData[], colorMode: "light
gridIndex: 1,
splitNumber: 2,
position: "right",
- axisLabel: {
+ axisLabel: {
show: options.volumeChart.showYAxisLabel,
formatter: (function (value) {
return formatUnit(value, options.volumeChart.value.units, options.volumeChart.value.decimal)
@@ -308,7 +308,7 @@ export const buildOptions = (panel: Panel, data: SeriesData[], colorMode: "light
data: data0.volumes,
itemStyle: {
opacity: options.chartOpacity,
- color: paletteColorNameToHex(findRuleInOverride(volumeOverride, OverrideRules.SeriesColor),colorMode) ?? null,
+ color: paletteColorNameToHex(findRuleInOverride(volumeOverride, OverrideRules.SeriesColor), colorMode) ?? null,
},
tooltip: {
valueFormatter: (function (value) {
@@ -329,7 +329,7 @@ export const buildOptions = (panel: Panel, data: SeriesData[], colorMode: "light
width: options.maLine.lineWidth
},
itemStyle: {
- color: paletteColorNameToHex(findRuleInOverride(ma5verride, OverrideRules.SeriesColor),colorMode) ?? null,
+ color: paletteColorNameToHex(findRuleInOverride(ma5verride, OverrideRules.SeriesColor), colorMode) ?? null,
},
symbol: options.maLine.lineSymbol
},
@@ -343,7 +343,7 @@ export const buildOptions = (panel: Panel, data: SeriesData[], colorMode: "light
width: options.maLine.lineWidth
},
itemStyle: {
- color: paletteColorNameToHex(findRuleInOverride(ma10verride, OverrideRules.SeriesColor),colorMode) ?? null,
+ color: paletteColorNameToHex(findRuleInOverride(ma10verride, OverrideRules.SeriesColor), colorMode) ?? null,
},
symbol: options.maLine.lineSymbol
},
@@ -357,7 +357,7 @@ export const buildOptions = (panel: Panel, data: SeriesData[], colorMode: "light
width: options.maLine.lineWidth
},
itemStyle: {
- color: paletteColorNameToHex(findRuleInOverride(ma20verride, OverrideRules.SeriesColor),colorMode) ?? null,
+ color: paletteColorNameToHex(findRuleInOverride(ma20verride, OverrideRules.SeriesColor), colorMode) ?? null,
},
symbol: options.maLine.lineSymbol
},
@@ -371,7 +371,7 @@ export const buildOptions = (panel: Panel, data: SeriesData[], colorMode: "light
width: options.maLine.lineWidth
},
itemStyle: {
- color: paletteColorNameToHex(findRuleInOverride(ma30verride, OverrideRules.SeriesColor),colorMode) ?? null,
+ color: paletteColorNameToHex(findRuleInOverride(ma30verride, OverrideRules.SeriesColor), colorMode) ?? null,
},
symbol: options.maLine.lineSymbol
}
@@ -390,7 +390,7 @@ const transformSeriesDataToCandlestickFormat = (s: SeriesData) => {
const volumeField = s.fields.find(f => f.name == "volume")
// [time, open, close, lowest, highest, volume]
- timeField.values.forEach((t,i) => {
+ timeField.values.forEach((t, i) => {
const v = [
t,
openField.values[i],
@@ -404,7 +404,7 @@ const transformSeriesDataToCandlestickFormat = (s: SeriesData) => {
}
res.push(v)
- })
+ })
return res
}
\ No newline at end of file
diff --git a/ui/src/views/dashboard/plugins/external/panel/radar/Editor.tsx b/ui/src/views/dashboard/plugins/external/panel/radar/Editor.tsx
new file mode 100644
index 000000000..b64c89690
--- /dev/null
+++ b/ui/src/views/dashboard/plugins/external/panel/radar/Editor.tsx
@@ -0,0 +1,112 @@
+// Copyright 2023 Datav.io Team
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+import { Select, Switch, Textarea } from "@chakra-ui/react"
+import PanelAccordion from "src/views/dashboard/edit-panel/Accordion"
+import PanelEditItem from "src/views/dashboard/edit-panel/PanelEditItem"
+import { Panel, PanelEditorProps } from "types/dashboard"
+import React, { memo } from "react";
+import { useStore } from "@nanostores/react"
+import { commonMsg } from "src/i18n/locales/en"
+import { PluginSettings, initSettings, } from "./types"
+import { dispatch } from "use-bus";
+import { PanelForceRebuildEvent } from "src/data/bus-events";
+import { defaultsDeep } from "lodash";
+import RadionButtons from "components/RadioButtons";
+import { EditorNumberItem } from "components/editor/EditorItem";
+
+
+const PanelEditor = memo(({ panel, onChange }: PanelEditorProps) => {
+ const t = useStore(commonMsg)
+ panel.plugins[panel.type] = defaultsDeep(panel.plugins[panel.type], initSettings)
+ const options: PluginSettings = panel.plugins[panel.type]
+ return (
+ <>
+
+
+ onChange((panel: Panel) => {
+ const plugin: PluginSettings = panel.plugins[panel.type]
+ plugin.animation = e.currentTarget.checked
+ // force the panel to rebuild to avoid some problems
+ dispatch(PanelForceRebuildEvent + panel.id)
+ })} />
+
+
+
+
+
+
+
+ onChange((panel: Panel) => {
+ const plugin: PluginSettings = panel.plugins[panel.type]
+ plugin.graph.legend.mode = v
+ dispatch(PanelForceRebuildEvent + panel.id)
+ })} />
+
+
+
+
+
+ {
+ const plugin: PluginSettings = panel.plugins[panel.type]
+ plugin.graph.legend.top = e
+ dispatch(PanelForceRebuildEvent + panel.id)
+ }} />
+
+
+ {
+ const plugin: PluginSettings = panel.plugins[panel.type]
+ plugin.graph.legend.bottom = e
+ dispatch(PanelForceRebuildEvent + panel.id)
+ }} />
+
+
+ {
+ const plugin: PluginSettings = panel.plugins[panel.type]
+ plugin.graph.legend.left = e
+ dispatch(PanelForceRebuildEvent + panel.id)
+ }} />
+
+
+ {
+ const plugin: PluginSettings = panel.plugins[panel.type]
+ plugin.graph.legend.right = e
+ dispatch(PanelForceRebuildEvent + panel.id)
+ }} />
+
+
+ {
+ const plugin: PluginSettings = panel.plugins[panel.type]
+ plugin.graph.legend.itemGap = e
+ dispatch(PanelForceRebuildEvent + panel.id)
+ }} />
+
+
+ >
+ )
+})
+
+export default PanelEditor
\ No newline at end of file
diff --git a/ui/src/views/dashboard/plugins/external/panel/radar/OverrideEditor.tsx b/ui/src/views/dashboard/plugins/external/panel/radar/OverrideEditor.tsx
new file mode 100644
index 000000000..79146b874
--- /dev/null
+++ b/ui/src/views/dashboard/plugins/external/panel/radar/OverrideEditor.tsx
@@ -0,0 +1,38 @@
+// Copyright 2023 Datav.io Team
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import { OverrideRule } from "types/dashboard";
+import React from "react";
+
+interface Props {
+ override: OverrideRule
+ onChange: any
+}
+
+
+const OverrideEditor = (props: Props) => {
+ return <>>
+}
+
+export default OverrideEditor
+
+export enum OverrideRules {
+ // basic
+}
+
+// The above example will get targets from SeriesData, Table and Graph panels are using this method to get targets
+// If return [] or null or undefined, Datav will use the default function to get override targets
+export const getOverrideTargets = (panel, data) => {
+ // for demonstration purpose, we just return a hard coded targets list
+ return []
+}
\ No newline at end of file
diff --git a/ui/src/views/dashboard/plugins/external/panel/radar/Panel.tsx b/ui/src/views/dashboard/plugins/external/panel/radar/Panel.tsx
new file mode 100644
index 000000000..6f5745268
--- /dev/null
+++ b/ui/src/views/dashboard/plugins/external/panel/radar/Panel.tsx
@@ -0,0 +1,69 @@
+// Copyright 2023 Datav.io Team
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+import { Box, Center, Text, useColorMode } from "@chakra-ui/react";
+import ChartComponent from "src/components/charts/Chart";
+import { memo, useMemo, useState } from "react";
+import { PanelProps } from "types/dashboard"
+import { FieldType, SeriesData } from "types/seriesData";
+import React from "react";
+import { isEmpty } from "utils/validate";
+import NoData from "src/views/dashboard/components/PanelNoData";
+import { defaultsDeep } from "lodash";
+import { PluginSettings, initSettings } from "./types";
+import { buildOptions } from "./buildOptions";
+import mockData from './mockData.json'
+import { isSeriesData } from "utils/seriesData";
+
+interface Props extends PanelProps {
+ data: SeriesData[][]
+}
+
+const PanelComponentWrapper = memo((props: Props) => {
+ const d: SeriesData[] = props.data.flat()
+ if (isEmpty(d)) {
+ return