diff --git a/src/common/meta/dashboards/v5/mod.rs b/src/common/meta/dashboards/v5/mod.rs index 53bed11ced..acf4363a6e 100644 --- a/src/common/meta/dashboards/v5/mod.rs +++ b/src/common/meta/dashboards/v5/mod.rs @@ -196,6 +196,8 @@ pub struct PanelConfig { #[serde(skip_serializing_if = "Option::is_none")] decimals: Option, #[serde(skip_serializing_if = "Option::is_none")] + line_thickness: Option, + #[serde(skip_serializing_if = "Option::is_none")] top_results: Option, #[serde(skip_serializing_if = "Option::is_none")] top_results_others: Option, @@ -204,6 +206,12 @@ pub struct PanelConfig { #[serde(skip_serializing_if = "Option::is_none")] axis_border_show: Option, #[serde(skip_serializing_if = "Option::is_none")] + label_option: Option, + #[serde(skip_serializing_if = "Option::is_none")] + show_symbol: Option, + #[serde(skip_serializing_if = "Option::is_none")] + line_interpolation: Option, + #[serde(skip_serializing_if = "Option::is_none")] legend_width: Option, base_map: Option, map_view: Option, @@ -427,3 +435,33 @@ pub struct LegendWidth { #[serde(skip_serializing_if = "Option::is_none")] pub unit: Option, } + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, ToSchema)] +pub struct LabelOption { + #[serde(skip_serializing_if = "Option::is_none")] + pub position: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub rotate: Option, +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, ToSchema)] +#[serde(rename_all = "lowercase")] +pub enum LineInterpolation { + Smooth, + Linear, + #[serde(rename = "step-start")] + StepStart, + #[serde(rename = "step-end")] + StepEnd, + #[serde(rename = "step-middle")] + StepMiddle, +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, ToSchema)] +#[serde(rename_all = "lowercase")] +pub enum LabelPosition { + Top, + Inside, + InsideTop, + InsideBottom +} \ No newline at end of file diff --git a/web/src/components/dashboards/addPanel/ConfigPanel.vue b/web/src/components/dashboards/addPanel/ConfigPanel.vue index 99449c99ce..b5a60f18f4 100644 --- a/web/src/components/dashboards/addPanel/ConfigPanel.vue +++ b/web/src/components/dashboards/addPanel/ConfigPanel.vue @@ -190,7 +190,7 @@ along with this program. If not, see . :display-value="`${ dashboardPanelData.data.config.unit ? unitOptions.find( - (it) => it.value == dashboardPanelData.data.config.unit + (it) => it.value == dashboardPanelData.data.config.unit, )?.label : 'Default' }`" @@ -348,7 +348,7 @@ along with this program. If not, see . handleBlur( dashboardPanelData.data.config.map_symbol_style.size_by_value, 1, - 'min' + 'min', ) " :label="t('dashboard.minimum')" @@ -379,7 +379,7 @@ along with this program. If not, see . handleBlur( dashboardPanelData.data.config.map_symbol_style.size_by_value, 100, - 'max' + 'max', ) " :label="t('dashboard.maximum')" @@ -409,7 +409,7 @@ along with this program. If not, see . handleBlur( dashboardPanelData.data.config.map_symbol_style, 2, - 'size_fixed' + 'size_fixed', ) " :label="t('dashboard.fixedValue')" @@ -678,7 +678,7 @@ along with this program. If not, see . . . dashboardPanelData.layout.currentQueryIndex ].config, 1, - 'weight_fixed' + 'weight_fixed', ) " :label="t('common.weight')" @@ -895,10 +895,197 @@ along with this program. If not, see . />
+ + + + +
+ + + + +
+ + + + + +
+ + + + +
+ + + + +
+ { const layoutFields = dashboardPanelData.data.queries[ @@ -1289,8 +1571,8 @@ export default defineComponent({ label: it.name, value: it.name, }; - } - ) + }, + ), ); const timeShifts = []; @@ -1341,6 +1623,9 @@ export default defineComponent({ symbolOptions, legendsPositionOptions, unitOptions, + labelPositionOptions, + showSymbol, + lineInterpolationOptions, isWeightFieldPresent, setUnit, handleBlur, diff --git a/web/src/components/icons/dashboards/LinearIcon.vue b/web/src/components/icons/dashboards/LinearIcon.vue new file mode 100644 index 0000000000..85d37ead8d --- /dev/null +++ b/web/src/components/icons/dashboards/LinearIcon.vue @@ -0,0 +1,22 @@ + + + diff --git a/web/src/components/icons/dashboards/NoSymbol.vue b/web/src/components/icons/dashboards/NoSymbol.vue new file mode 100644 index 0000000000..c16373a937 --- /dev/null +++ b/web/src/components/icons/dashboards/NoSymbol.vue @@ -0,0 +1,19 @@ + + + diff --git a/web/src/components/icons/dashboards/Smooth.vue b/web/src/components/icons/dashboards/Smooth.vue new file mode 100644 index 0000000000..30063400c6 --- /dev/null +++ b/web/src/components/icons/dashboards/Smooth.vue @@ -0,0 +1,26 @@ + + + diff --git a/web/src/components/icons/dashboards/StepAfter.vue b/web/src/components/icons/dashboards/StepAfter.vue new file mode 100644 index 0000000000..c6794e8525 --- /dev/null +++ b/web/src/components/icons/dashboards/StepAfter.vue @@ -0,0 +1,40 @@ + + + diff --git a/web/src/components/icons/dashboards/StepBefore.vue b/web/src/components/icons/dashboards/StepBefore.vue new file mode 100644 index 0000000000..07d7cbf4e9 --- /dev/null +++ b/web/src/components/icons/dashboards/StepBefore.vue @@ -0,0 +1,22 @@ + + + diff --git a/web/src/components/icons/dashboards/StepMiddle.vue b/web/src/components/icons/dashboards/StepMiddle.vue new file mode 100644 index 0000000000..e55997effc --- /dev/null +++ b/web/src/components/icons/dashboards/StepMiddle.vue @@ -0,0 +1,33 @@ + + + diff --git a/web/src/composables/useDashboardPanel.ts b/web/src/composables/useDashboardPanel.ts index 5601b33d46..55ad153f31 100644 --- a/web/src/composables/useDashboardPanel.ts +++ b/web/src/composables/useDashboardPanel.ts @@ -48,10 +48,17 @@ const getDefaultDashboardPanelData: any = () => ({ unit: null, unit_custom: null, decimals: 2, + line_thickness: 1.5, top_results: null, top_results_others: false, axis_width: null, axis_border_show: false, + label_option: { + position: null, + rotate: 0, + }, + show_symbol: false, + line_interpolation: "smooth", legend_width: { value: null, unit: "px", diff --git a/web/src/locales/languages/en.json b/web/src/locales/languages/en.json index 34c6d18433..99ec7c27da 100644 --- a/web/src/locales/languages/en.json +++ b/web/src/locales/languages/en.json @@ -582,6 +582,8 @@ "showBorder": "Show Axis Border", "legendsPositionLabel": "Legends Positions", "unitLabel": "Unit", + "labelPosition": "Value Position", + "labelRotate": "Value Rotate", "basemapLabel": "Base Map", "customunitLabel": "Custom Unit", "currencyDollar": "Currency - Dollar ($)", @@ -657,7 +659,21 @@ "scheduledReports": "Scheduled Reports", "newReport": "New Report", "scheduledDashboards": "Scheduled Dashboards", - "panelHeight": "Panel Height" + "panelHeight": "Panel Height", + "none": "None", + "inside": "Inside", + "insideTop": "Inside Top", + "insideBottom": "Inside Bottom", + "top": "Top", + "showSymbol": "Show Symbol", + "yes": "Yes", + "no": "No", + "lineInterpolation": "Line Interpolation", + "linear": "Linear", + "smooth": "Smooth", + "stepBefore": "Step Before", + "stepAfter": "Step After", + "stepMiddle": "Step Middle" }, "panel": { "header": "Panel", diff --git a/web/src/utils/dashboard/convertSQLData.ts b/web/src/utils/dashboard/convertSQLData.ts index 2b88d4c9e6..98a25bfd33 100644 --- a/web/src/utils/dashboard/convertSQLData.ts +++ b/web/src/utils/dashboard/convertSQLData.ts @@ -722,6 +722,12 @@ export const convertSQLData = async ( // inverse data for h-stacked and h-bar inverse: ["h-stacked", "h-bar"].includes(panelSchema.type), name: index == 0 ? panelSchema.queries[0]?.fields?.x[index]?.label : "", + label: { + show: + panelSchema.config?.label_option?.position != null, + position: panelSchema.config?.label_option?.position || "None", + rotate: panelSchema.config?.label_option?.rotate || 0, + }, nameLocation: "middle", nameGap: 25, nameTextStyle: { @@ -830,7 +836,7 @@ export const convertSQLData = async ( series: [], }; - const defaultSeriesProps = getPropsByChartTypeForSeries(panelSchema.type); + const defaultSeriesProps = getPropsByChartTypeForSeries(panelSchema); // Now set the series values as per the chart data // Override any configs if required as per the chart type @@ -897,11 +903,19 @@ export const convertSQLData = async ( const data = missingValueData.filter( (it: any) => it[key1] == key ); + const seriesObj = { //only append if yaxiskeys length is more than 1 name: yAxisKeys.length == 1 ? key : key + " (" + yAxisName + ")", ...defaultSeriesProps, + label: { + show: + panelSchema.config?.label_option?.position != null, + position: + panelSchema.config?.label_option?.position || "None", + rotate: panelSchema.config?.label_option?.rotate || 0, + }, // markLine if exist markLine: { silent: true, @@ -928,6 +942,12 @@ export const convertSQLData = async ( name: panelSchema?.queries[0]?.fields?.y.find( (it: any) => it.alias == key )?.label, + label: { + show: + panelSchema.config?.label_option?.position != null, + position: panelSchema.config?.label_option?.position || "None", + rotate: panelSchema.config?.label_option?.rotate || 0, + }, // color: // panelSchema.queries[0]?.fields?.y.find( // (it: any) => it.alias == key, @@ -1021,6 +1041,12 @@ export const convertSQLData = async ( name: panelSchema?.queries[0]?.fields?.y.find( (it: any) => it.alias == key )?.label, + label: { + show: + panelSchema.config?.label_option?.position != null, + position: panelSchema.config?.label_option?.position || "None", + rotate: panelSchema.config?.label_option?.rotate || 0, + }, // color: // panelSchema.queries[0]?.fields?.y.find( // (it: any) => it.alias == key, @@ -1053,6 +1079,12 @@ export const convertSQLData = async ( // ?.color || "#5960b2", opacity: 0.8, ...defaultSeriesProps, + label: { + show: + panelSchema.config?.label_option?.position != null, + position: panelSchema.config?.label_option?.position || "None", + rotate: panelSchema.config?.label_option?.rotate || 0, + }, // markLine if exist markLine: { silent: true, @@ -1094,6 +1126,12 @@ export const convertSQLData = async ( animation: false, data: getMarkLineData(panelSchema), }, + label: { + show: + panelSchema.config?.label_option?.position != null, + position: panelSchema.config?.label_option?.position || "None", + rotate: panelSchema.config?.label_option?.rotate || 0, + }, data: getAxisDataFromKey(key), barMinHeight: 1, }; @@ -1296,6 +1334,12 @@ export const convertSQLData = async ( const seriesObj = { name: key, ...defaultSeriesProps, + label: { + show: + panelSchema.config?.label_option?.position != null, + position: panelSchema.config?.label_option?.position || "None", + rotate: panelSchema.config?.label_option?.rotate || 0, + }, // markLine if exist markLine: { silent: true, @@ -1357,6 +1401,7 @@ export const convertSQLData = async ( { ...defaultSeriesProps, name: panelSchema?.queries[0]?.fields?.y[0].label, + data: zValues .map((it: any, index: any) => { return xAxisZerothPositionUniqueValue.map( @@ -1506,6 +1551,12 @@ export const convertSQLData = async ( const seriesObj = { name: key, ...defaultSeriesProps, + label: { + show: + panelSchema.config?.label_option?.position != null, + position: panelSchema.config?.label_option?.position || "None", + rotate: panelSchema.config?.label_option?.rotate || 0, + }, // markLine if exist markLine: { silent: true, @@ -2231,8 +2282,8 @@ const largestLabel = (data: any) => { * @param {string} type - The type of chart. * @return {Object} - The properties for the given chart type. */ -const getPropsByChartTypeForSeries = (type: string) => { - switch (type) { +const getPropsByChartTypeForSeries = (panelSchema: any) => { + switch (panelSchema.type) { case "bar": return { type: "bar", @@ -2243,10 +2294,18 @@ const getPropsByChartTypeForSeries = (type: string) => { return { type: "line", emphasis: { focus: "series" }, - smooth: true, - showSymbol: false, + smooth: + panelSchema.config?.line_interpolation === "smooth" || + panelSchema.config?.line_interpolation == null, + step: ["step-start", "step-end", "step-middle"].includes( + panelSchema.config?.line_interpolation, + ) + // TODO: replace this with type integrations + ? panelSchema.config.line_interpolation.replace("step-", "") + : false, + showSymbol: panelSchema.config?.show_symbol ?? false, areaStyle: null, - lineStyle: { width: 1.5 }, + lineStyle: { width: panelSchema.config?.line_thickness ?? 1.5 }, }; case "scatter": return { @@ -2304,11 +2363,18 @@ const getPropsByChartTypeForSeries = (type: string) => { case "area": return { type: "line", - smooth: true, + smooth: + panelSchema.config?.line_interpolation === "smooth" || + panelSchema.config?.line_interpolation == null, + step: ["step-start", "step-end", "step-middle"].includes( + panelSchema.config?.line_interpolation, + ) + ? panelSchema.config.line_interpolation.replace("step-", "") + : false, emphasis: { focus: "series" }, areaStyle: {}, - showSymbol: false, - lineStyle: { width: 1.5 }, + showSymbol: panelSchema.config?.show_symbol ?? false, + lineStyle: { width: panelSchema.config?.line_thickness ?? 1.5 }, }; case "stacked": return { @@ -2336,14 +2402,21 @@ const getPropsByChartTypeForSeries = (type: string) => { case "area-stacked": return { type: "line", - smooth: true, + smooth: + panelSchema.config?.line_interpolation === "smooth" || + panelSchema.config?.line_interpolation == null, + step: ["step-start", "step-end", "step-middle"].includes( + panelSchema.config?.line_interpolation, + ) + ? panelSchema.config.line_interpolation.replace("step-", "") + : false, stack: "Total", areaStyle: {}, emphasis: { focus: "series", }, - showSymbol: false, - lineStyle: { width: 1.5 }, + showSymbol: panelSchema.config?.show_symbol ?? false, + lineStyle: { width: panelSchema.config?.line_thickness ?? 1.5 }, }; case "metric": return {