From 205cff3a94b5ecad0c74aec3698499e3150f01eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrian=20Kosza=C5=82ka?= <70269475+AdrianKoszalka@users.noreply.github.com> Date: Thu, 6 Feb 2025 21:48:28 +0100 Subject: [PATCH] feat: Add parseJson Handlebars Helper to Support Processing Nested JSON Data (#31998) Co-authored-by: AdrianKoszalka --- .../plugins/plugin-chart-handlebars/README.md | 23 +++++++++++ .../Handlebars/HandlebarsViewer.tsx | 13 ++++++ .../src/plugin/controls/handlebarTemplate.tsx | 40 ++++++++++++++++++- 3 files changed, 74 insertions(+), 2 deletions(-) diff --git a/superset-frontend/plugins/plugin-chart-handlebars/README.md b/superset-frontend/plugins/plugin-chart-handlebars/README.md index d0c7bdc52..1d9b2bd91 100644 --- a/superset-frontend/plugins/plugin-chart-handlebars/README.md +++ b/superset-frontend/plugins/plugin-chart-handlebars/README.md @@ -73,3 +73,26 @@ more details. └── types └── external.d.ts ``` + +### Available Handlebars Helpers in Superset + +Below, you will find a list of all currently registered helpers in the Handlebars plugin for Superset. These helpers are registered and managed in the file [`HandlebarsViewer.tsx`](./path/to/HandlebarsViewer.tsx). + +#### List of Registered Helpers: + +1. **`dateFormat`**: Formats a date using a specified format. + + - **Usage**: `{{dateFormat my_date format="MMMM YYYY"}}` + - **Default format**: `YYYY-MM-DD`. + +2. **`stringify`**: Converts an object into a JSON string or returns a string representation of non-object values. + + - **Usage**: `{{stringify myObj}}`. + +3. **`formatNumber`**: Formats a number using locale-specific formatting. + + - **Usage**: `{{formatNumber number locale="en-US"}}`. + - **Default locale**: `en-US`. + +4. **`parseJson`**: Parses a JSON string into a JavaScript object. + - **Usage**: `{{parseJson jsonString}}`. diff --git a/superset-frontend/plugins/plugin-chart-handlebars/src/components/Handlebars/HandlebarsViewer.tsx b/superset-frontend/plugins/plugin-chart-handlebars/src/components/Handlebars/HandlebarsViewer.tsx index 883040743..8e1a1aab9 100644 --- a/superset-frontend/plugins/plugin-chart-handlebars/src/components/Handlebars/HandlebarsViewer.tsx +++ b/superset-frontend/plugins/plugin-chart-handlebars/src/components/Handlebars/HandlebarsViewer.tsx @@ -99,5 +99,18 @@ Handlebars.registerHelper( }, ); +// usage: {{parseJson jsonString}} +Handlebars.registerHelper('parseJson', (jsonString: string) => { + try { + return JSON.parse(jsonString); + } catch (error) { + if (error instanceof Error) { + error.message = `Invalid JSON string: ${error.message}`; + throw error; + } + throw new Error(`Invalid JSON string: ${String(error)}`); + } +}); + Helpers.registerHelpers(Handlebars); HandlebarsGroupBy.register(Handlebars); diff --git a/superset-frontend/plugins/plugin-chart-handlebars/src/plugin/controls/handlebarTemplate.tsx b/superset-frontend/plugins/plugin-chart-handlebars/src/plugin/controls/handlebarTemplate.tsx index 71b5b9b06..c43d95487 100644 --- a/superset-frontend/plugins/plugin-chart-handlebars/src/plugin/controls/handlebarTemplate.tsx +++ b/superset-frontend/plugins/plugin-chart-handlebars/src/plugin/controls/handlebarTemplate.tsx @@ -20,8 +20,9 @@ import { ControlSetItem, CustomControlConfig, sharedControls, + InfoTooltipWithTrigger, } from '@superset-ui/chart-controls'; -import { t, validateNonEmpty } from '@superset-ui/core'; +import { t, validateNonEmpty, useTheme, SafeMarkdown } from '@superset-ui/core'; import { CodeEditor } from '../../components/CodeEditor/CodeEditor'; import { ControlHeader } from '../../components/ControlHeader/controlHeader'; import { debounceFunc } from '../../consts'; @@ -33,13 +34,48 @@ interface HandlebarsCustomControlProps { const HandlebarsTemplateControl = ( props: CustomControlConfig, ) => { + const theme = useTheme(); + const val = String( props?.value ? props?.value : props?.default ? props?.default : '', ); + const helperDescriptionsHeader = t( + 'Available Handlebars Helpers in Superset:', + ); + + const helperDescriptions = [ + { key: 'dateFormat', descKey: 'Formats a date using a specified format.' }, + { key: 'stringify', descKey: 'Converts an object to a JSON string.' }, + { + key: 'formatNumber', + descKey: 'Formats a number using locale-specific formatting.', + }, + { + key: 'parseJson', + descKey: 'Parses a JSON string into a JavaScript object.', + }, + ]; + + const helpersTooltipContent = ` +${helperDescriptionsHeader} + +${helperDescriptions + .map(({ key, descKey }) => `- **${key}**: ${t(descKey)}`) + .join('\n')} +`; + return (
- {props.label} + +
+ {props.label} + } + /> +
+