diff --git a/superset-frontend/plugins/plugin-chart-table/src/TableChart.tsx b/superset-frontend/plugins/plugin-chart-table/src/TableChart.tsx index ed2d9319c..8b361c614 100644 --- a/superset-frontend/plugins/plugin-chart-table/src/TableChart.tsx +++ b/superset-frontend/plugins/plugin-chart-table/src/TableChart.tsx @@ -237,6 +237,7 @@ export default function TableChart( sticky = true, // whether to use sticky header columnColorFormatters, allowRearrangeColumns = false, + allowRenderHtml = true, onContextMenu, emitCrossFilters, } = props; @@ -469,7 +470,7 @@ export default function TableChart( accessor: ((datum: D) => datum[key]) as never, Cell: ({ value, row }: { value: DataRecordValue; row: Row }) => { const [isHtml, text] = formatColumnValue(column, value); - const html = isHtml ? { __html: text } : undefined; + const html = isHtml && allowRenderHtml ? { __html: text } : undefined; let backgroundColor; if (hasColumnColorFormatters) { diff --git a/superset-frontend/plugins/plugin-chart-table/src/controlPanel.tsx b/superset-frontend/plugins/plugin-chart-table/src/controlPanel.tsx index ad39b504c..6cce125f3 100644 --- a/superset-frontend/plugins/plugin-chart-table/src/controlPanel.tsx +++ b/superset-frontend/plugins/plugin-chart-table/src/controlPanel.tsx @@ -451,6 +451,18 @@ const config: ControlPanelConfig = { }, }, ], + [ + { + name: 'allow_render_html', + config: { + type: 'CheckboxControl', + label: t('Render columns in HTML format'), + renderTrigger: true, + default: true, + description: t('Render data in HTML format if applicable.'), + }, + }, + ], [ { name: 'column_config', diff --git a/superset-frontend/plugins/plugin-chart-table/src/transformProps.ts b/superset-frontend/plugins/plugin-chart-table/src/transformProps.ts index 0a2a3449c..92b23307a 100644 --- a/superset-frontend/plugins/plugin-chart-table/src/transformProps.ts +++ b/superset-frontend/plugins/plugin-chart-table/src/transformProps.ts @@ -238,6 +238,7 @@ const transformProps = ( show_totals: showTotals, conditional_formatting: conditionalFormatting, allow_rearrange_columns: allowRearrangeColumns, + allow_render_html: allowRenderHtml, } = formData; const timeGrain = extractTimegrain(formData); @@ -291,6 +292,7 @@ const transformProps = ( columnColorFormatters, timeGrain, allowRearrangeColumns, + allowRenderHtml, onContextMenu, }; }; diff --git a/superset-frontend/plugins/plugin-chart-table/src/types.ts b/superset-frontend/plugins/plugin-chart-table/src/types.ts index 02bae809f..639b525d4 100644 --- a/superset-frontend/plugins/plugin-chart-table/src/types.ts +++ b/superset-frontend/plugins/plugin-chart-table/src/types.ts @@ -130,6 +130,7 @@ export interface TableChartTransformedProps { onChangeFilter?: ChartProps['hooks']['onAddFilter']; columnColorFormatters?: ColorFormatters; allowRearrangeColumns?: boolean; + allowRenderHtml?: boolean; onContextMenu?: ( clientX: number, clientY: number, diff --git a/superset-frontend/src/SqlLab/components/ResultSet/index.tsx b/superset-frontend/src/SqlLab/components/ResultSet/index.tsx index 87ba0370e..a6bbb84ba 100644 --- a/superset-frontend/src/SqlLab/components/ResultSet/index.tsx +++ b/superset-frontend/src/SqlLab/components/ResultSet/index.tsx @@ -53,6 +53,7 @@ import FilterableTable from 'src/components/FilterableTable'; import CopyToClipboard from 'src/components/CopyToClipboard'; import { addDangerToast } from 'src/components/MessageToasts/actions'; import { prepareCopyToClipboardTabularData } from 'src/utils/common'; +import { getItem, LocalStorageKeys } from 'src/utils/localStorageHelpers'; import { addQueryEditor, clearQueryResults, @@ -579,6 +580,10 @@ const ResultSet = ({ const expandedColumns = results.expanded_columns ? results.expanded_columns.map(col => col.column_name) : []; + const allowHTML = getItem( + LocalStorageKeys.SqllabIsRenderHtmlEnabled, + false, + ); return ( {renderControls()} @@ -626,6 +631,7 @@ const ResultSet = ({ height={rowsHeight} filterText={searchText} expandedColumns={expandedColumns} + allowHTML={allowHTML} /> ); diff --git a/superset-frontend/src/SqlLab/components/SqlEditor/index.tsx b/superset-frontend/src/SqlLab/components/SqlEditor/index.tsx index 159072695..0c69e20fc 100644 --- a/superset-frontend/src/SqlLab/components/SqlEditor/index.tsx +++ b/superset-frontend/src/SqlLab/components/SqlEditor/index.tsx @@ -284,6 +284,9 @@ const SqlEditor: React.FC = ({ const [autocompleteEnabled, setAutocompleteEnabled] = useState( getItem(LocalStorageKeys.SqllabIsAutocompleteEnabled, true), ); + const [renderHTMLEnabled, setRenderHTMLEnabled] = useState( + getItem(LocalStorageKeys.SqllabIsRenderHtmlEnabled, false), + ); const [showCreateAsModal, setShowCreateAsModal] = useState(false); const [createAs, setCreateAs] = useState(''); const [showEmptyState, setShowEmptyState] = useState(false); @@ -607,6 +610,11 @@ const SqlEditor: React.FC = ({ setAutocompleteEnabled(!autocompleteEnabled); }; + const handleToggleRenderHTMLEnabled = () => { + setItem(LocalStorageKeys.SqllabIsRenderHtmlEnabled, !renderHTMLEnabled); + setRenderHTMLEnabled(!renderHTMLEnabled); + }; + const createTableAs = () => { startQuery(true, CtasEnum.Table); setShowCreateAsModal(false); @@ -631,6 +639,14 @@ const SqlEditor: React.FC = ({ : t('You must run the query successfully first'); return ( + + {' '} + {t('Render HTML')}{' '} + {' '} + {' '} {t('Autocomplete')}{' '} diff --git a/superset-frontend/src/components/Chart/DrillDetail/DrillDetailPane.tsx b/superset-frontend/src/components/Chart/DrillDetail/DrillDetailPane.tsx index 8bea9ddaa..2b5c87b27 100644 --- a/superset-frontend/src/components/Chart/DrillDetail/DrillDetailPane.tsx +++ b/superset-frontend/src/components/Chart/DrillDetail/DrillDetailPane.tsx @@ -265,6 +265,8 @@ export default function DrillDetailPane({ (!responseError && !resultsPages.size) || metadataBarStatus === ResourceStatus.Loading; + const allowHTML = formData.allow_render_html ?? true; + let tableContent = null; if (responseError) { // Render error if page download failed @@ -301,7 +303,7 @@ export default function DrillDetailPane({ } resizable virtualize - allowHTML + allowHTML={allowHTML} /> ); diff --git a/superset-frontend/src/utils/localStorageHelpers.ts b/superset-frontend/src/utils/localStorageHelpers.ts index 4d8d35a49..61e1bbc35 100644 --- a/superset-frontend/src/utils/localStorageHelpers.ts +++ b/superset-frontend/src/utils/localStorageHelpers.ts @@ -50,6 +50,7 @@ export enum LocalStorageKeys { * sqllab__is_autocomplete_enabled */ SqllabIsAutocompleteEnabled = 'sqllab__is_autocomplete_enabled', + SqllabIsRenderHtmlEnabled = 'sqllab__is_render_html_enabled', ExploreDataTableOriginalFormattedTimeColumns = 'explore__data_table_original_formatted_time_columns', DashboardCustomFilterBarWidths = 'dashboard__custom_filter_bar_widths', DashboardExploreContext = 'dashboard__explore_context', @@ -69,6 +70,7 @@ export type LocalStorageValues = { datasetname_set_successful: boolean; homepage_activity_filter: TableTab | null; sqllab__is_autocomplete_enabled: boolean; + sqllab__is_render_html_enabled: boolean; explore__data_table_original_formatted_time_columns: Record; dashboard__custom_filter_bar_widths: Record; dashboard__explore_context: Record;