From a35e6c22e997220ea7b26bf690b579d33b4c1f93 Mon Sep 17 00:00:00 2001
From: cccs-RyanS <71385290+cccs-RyanS@users.noreply.github.com>
Date: Thu, 1 Dec 2022 08:57:43 -0500
Subject: [PATCH] Feature/cldn 1749 (#222)
* [CLDN-1749] adding new viz
* chanigng to work with standard filters
* Adding generic filter extraction
* Removing unused imports
* [CLDN-1749] Cleaning up code for reusablility
* [CLDN-1749] removing unused files
* [CLDN-1746] fixing case
* [CLDN-1749] adding parameter validation
* [CLDN-1749] adding error message and prefix parameter
* [CLDN-1749] removing unused files
* [CLDN-1749] adding temp base image for docker deployment
* [CLDN-1749] Better error handling and new icon
* [CLDN-1749] remove unused imports
* temp dockerfile change
* [CLDN-1749] Adding the adhoc filters back in
* [CLDN-1749] Updating image
* [CLDN-1749] Adding new thumbnail
* Updating dockerfile
* [CLDN-1749] Removing uneeded control panel elements
* [CLDN-1749] Fixing build errors
* [CLDN-1749] New image
* Change to use data from dataset
* Removing unsed function
* Fixing typos
* renove unused import
* updating image
* error message and label fixes
* updating image
* Update cccs-build/superset/Dockerfile
Co-authored-by: cccs-Dustin <96579982+cccs-Dustin@users.noreply.github.com>
* Update superset-frontend/src/cccs-viz/plugins/plugin-chart-iframe/src/plugin/transformProps.ts
Co-authored-by: cccs-RyanK <102618419+cccs-RyanK@users.noreply.github.com>
* Update superset-frontend/src/cccs-viz/plugins/plugin-chart-iframe/src/plugin/transformProps.ts
Co-authored-by: cccs-RyanK <102618419+cccs-RyanK@users.noreply.github.com>
Co-authored-by: cccs-Dustin <96579982+cccs-Dustin@users.noreply.github.com>
Co-authored-by: cccs-RyanK <102618419+cccs-RyanK@users.noreply.github.com>
---
cccs-build/superset/Dockerfile | 1 +
.../src/cccs-viz/plugins/index.ts | 1 +
.../src/IFrameVisualization.tsx | 17 ++
.../src/images/thumbnail.png | Bin 0 -> 1547 bytes
.../src/images/thumbnail.png:Zone.Identifier | 4 +
.../plugins/plugin-chart-iframe/src/index.ts | 1 +
.../src/plugin/buildQuery.ts | 57 +++++
.../src/plugin/controlPanel.ts | 205 ++++++++++++++++++
.../plugin-chart-iframe/src/plugin/index.ts | 51 +++++
.../src/plugin/transformProps.ts | 80 +++++++
.../plugins/plugin-chart-iframe/src/styles.js | 22 ++
.../plugins/plugin-chart-iframe/src/types.ts | 9 +
.../src/visualizations/presets/MainPreset.js | 2 +
13 files changed, 450 insertions(+)
create mode 100644 superset-frontend/src/cccs-viz/plugins/plugin-chart-iframe/src/IFrameVisualization.tsx
create mode 100644 superset-frontend/src/cccs-viz/plugins/plugin-chart-iframe/src/images/thumbnail.png
create mode 100644 superset-frontend/src/cccs-viz/plugins/plugin-chart-iframe/src/images/thumbnail.png:Zone.Identifier
create mode 100644 superset-frontend/src/cccs-viz/plugins/plugin-chart-iframe/src/index.ts
create mode 100644 superset-frontend/src/cccs-viz/plugins/plugin-chart-iframe/src/plugin/buildQuery.ts
create mode 100644 superset-frontend/src/cccs-viz/plugins/plugin-chart-iframe/src/plugin/controlPanel.ts
create mode 100644 superset-frontend/src/cccs-viz/plugins/plugin-chart-iframe/src/plugin/index.ts
create mode 100644 superset-frontend/src/cccs-viz/plugins/plugin-chart-iframe/src/plugin/transformProps.ts
create mode 100644 superset-frontend/src/cccs-viz/plugins/plugin-chart-iframe/src/styles.js
create mode 100644 superset-frontend/src/cccs-viz/plugins/plugin-chart-iframe/src/types.ts
diff --git a/cccs-build/superset/Dockerfile b/cccs-build/superset/Dockerfile
index 0e1e13f04268b..6abb7e38ea3dd 100644
--- a/cccs-build/superset/Dockerfile
+++ b/cccs-build/superset/Dockerfile
@@ -4,6 +4,7 @@ FROM $VAULT_CA_CONTAINER AS vault_ca
FROM uchimera.azurecr.io/cccs/superset-base:cccs-2.0_20221014182839_b5135
+
USER root
COPY *requirements.txt /tmp/
diff --git a/superset-frontend/src/cccs-viz/plugins/index.ts b/superset-frontend/src/cccs-viz/plugins/index.ts
index 7851bb1560dc0..f8453be3c882f 100644
--- a/superset-frontend/src/cccs-viz/plugins/index.ts
+++ b/superset-frontend/src/cccs-viz/plugins/index.ts
@@ -28,3 +28,4 @@ export { default as AtAGlanceChartDnsPlugin } from './plugin-chart-at-a-glance-d
export { default as AtAGlanceUserIdChartPlugin } from './plugin-chart-at-a-glance-user-id/src/plugin';
export { default as AtAGlanceUserIDSasChartPlugin } from './plugin-chart-at-a-glance-user-id-sas/src/plugin';
export { default as ApplicationLinksChartPlugin } from './plugin-chart-application-links/src/plugin';
+export { default as IFrameVisualizationChartPlugin } from './plugin-chart-iframe/src/plugin';
diff --git a/superset-frontend/src/cccs-viz/plugins/plugin-chart-iframe/src/IFrameVisualization.tsx b/superset-frontend/src/cccs-viz/plugins/plugin-chart-iframe/src/IFrameVisualization.tsx
new file mode 100644
index 0000000000000..fa1cec2d74420
--- /dev/null
+++ b/superset-frontend/src/cccs-viz/plugins/plugin-chart-iframe/src/IFrameVisualization.tsx
@@ -0,0 +1,17 @@
+import React from 'react';
+import { IFrameVisualizationProps } from './types';
+
+
+export default function IFrameVisualization(props: IFrameVisualizationProps) {
+ const { url, url_parameter_value, parameter_name, parameter_prefix, errorMessage} = props
+
+ const parserdUrlParameterName = parameter_name.includes('=') ? parameter_name : `${parameter_name}=${parameter_prefix}`
+
+ return (
+ <>
+ { errorMessage ?
+ <>{errorMessage}> :
+ }
+ >
+ );
+}
diff --git a/superset-frontend/src/cccs-viz/plugins/plugin-chart-iframe/src/images/thumbnail.png b/superset-frontend/src/cccs-viz/plugins/plugin-chart-iframe/src/images/thumbnail.png
new file mode 100644
index 0000000000000000000000000000000000000000..b3c8eb2228ba700df9fdf3ddeab66af86d572d0f
GIT binary patch
literal 1547
zcmZvcc~BAv6vjzSQo$=MMZ>EM%q_2gOfymw4-7m;H-!>4TNCpbk94dS98zRe60OXG
zP&XFS%rztN#;{8<^CViuEN`W?LmfAko!S0t=6mmZ^UeGB`{m&SyusQ~Z2$lO_Q84v
zs$Blx>`+&2Es7OZW$}3bU@xUosX8SRNpf=Xr%#_sOG{-kSy@?GMMXtpW8=ogMn*
93pM>{$?P$-n6
zqhn!Vp+F!2fk1wKeh>&GCnsm_NZcdG`;Cnh+fe7WL6_#1oB$zom2nq~N&8-@pC
zmXyjq*1oq`mXTlSjG%B}_WImZXc9IqD5T&W`n$@J{VhcH2_YpnEjF}{NZchH89_={
zlh#UwB-o2SbobJG-{XLYh#M?ro
zWzTCdab+k+aCDiOmXmy1O7XwBJ1mhUJc!xFkw22fXf>&US5t26d+N4#{6m8;WbVT<
zBAvi>-A2FvIN$KSnZ0c0pemK{f?C<5pHV0~7|PE4N213P_a%Pff8>-wP0X;=`5`%%VBCJOi-g|5PrYjwF
z)VIHX#YP_SGiWUJAG7=8uEVKRvaYCe5qeo{i*y$jp7~Q!+O23+Zd^k@AvHFP$zD&G
zHs}E}@(A&jdgim5BQnLN(!lEEM|-MP^?3^Vbhz_Ge%1EJ?dRhKF!LxYp3+(>(&pF8
zH`gtA(+@08y&6_*E)t431*&`pzt++sHzL6TQ^36=zmfYzgSvT`>o&uYnozCBw-u1n
z>oh$ooL_=i`*>Ha%wECB_<9h{dc9k3YHhqVNeYLWXl5!7Db$kvS;P5A`mjNHU=5R-
zXW0UB-J5&BF!NPU5$qK#zL>Gjff|#ka)TxPd9Q2_lILBcC>lQ@ml!=rLE9KvA3{m#
zG8mJ<)ZsT-#+K!VGNE2X5&OSn-YZ1Z40FATgBn!xetBADBd+<(`20lUquDA1|;SRXo16<6A1N)ZEw9x|}k0`rIe2^KiWp%u+DKa&$+|0%9no)9r&eU2@DAYd*VI|nB&5-PpGNLgXCQ3Dg
zr5i8I^G>_kVNggGOGsoR**;PqEe^wAZvfCTZUUO!Mvn+|Z5>6YcM>TcP1i
z+t-%5QZQM4Ei>ND&mZOw9a(<+(iSuLb<^elN+pT~@~fr;#wfGIANQ|I@kuFqw|L2<
zO>9D5M7~hZtOIUYX=`TYd}9mYgi3%2sRBXspwaxX^bo3yHWsmzb*^?>=Y;w<@)#d
zt1*+(Hrk^L-dh927&X>yfLp>}DWT7!HjMYLcTZe?_=0$l^)~KQ_PycwH(rS5H-Rw3
gk?&YU7l_{L?Vd~@K3as!Rv{hW;}zi9aN;cWUl!ot {
+ // RAW mode (not aggregated)
+ // eslint-disable-next-line no-param-reassign
+ return [
+ {
+ ...baseQueryObject,
+ row_limit: 10,
+ },
+ ];
+ });
+ }
+
\ No newline at end of file
diff --git a/superset-frontend/src/cccs-viz/plugins/plugin-chart-iframe/src/plugin/controlPanel.ts b/superset-frontend/src/cccs-viz/plugins/plugin-chart-iframe/src/plugin/controlPanel.ts
new file mode 100644
index 0000000000000..5c7a9df66fbce
--- /dev/null
+++ b/superset-frontend/src/cccs-viz/plugins/plugin-chart-iframe/src/plugin/controlPanel.ts
@@ -0,0 +1,205 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 { ensureIsArray, t, validateNonEmpty } from '@superset-ui/core';
+import {
+ ControlPanelConfig,
+ ControlPanelState,
+ ControlState,
+ sharedControls,
+} from '@superset-ui/chart-controls';
+
+const config: ControlPanelConfig = {
+
+ /**
+ * The control panel is split into two tabs: "Query" and
+ * "Chart Options". The controls that define the inputs to
+ * the chart data request, such as columns and metrics, usually
+ * reside within "Query", while controls that affect the visual
+ * appearance or functionality of the chart are under the
+ * "Chart Options" section.
+ *
+ * There are several predefined controls that can be used.
+ * Some examples:
+ * - groupby: columns to group by (tranlated to GROUP BY statement)
+ * - series: same as groupby, but single selection.
+ * - metrics: multiple metrics (translated to aggregate expression)
+ * - metric: sane as metrics, but single selection
+ * - adhoc_filters: filters (translated to WHERE or HAVING
+ * depending on filter type)
+ * - row_limit: maximum number of rows (translated to LIMIT statement)
+ *
+ * If a control panel has both a `series` and `groupby` control, and
+ * the user has chosen `col1` as the value for the `series` control,
+ * and `col2` and `col3` as values for the `groupby` control,
+ * the resulting query will contain three `groupby` columns. This is because
+ * we considered `series` control a `groupby` query field and its value
+ * will automatically append the `groupby` field when the query is generated.
+ *
+ * It is also possible to define custom controls by importing the
+ * necessary dependencies and overriding the default parameters, which
+ * can then be placed in the `controlSetRows` section
+ * of the `Query` section instead of a predefined control.
+ *
+ * import { validateNonEmpty } from '@superset-ui/core';
+ * import {
+ * sharedControls,
+ * ControlConfig,
+ * ControlPanelConfig,
+ * } from '@superset-ui/chart-controls';
+ *
+ * const myControl: ControlConfig<'SelectControl'> = {
+ * name: 'secondary_entity',
+ * config: {
+ * ...sharedControls.entity,
+ * type: 'SelectControl',
+ * label: t('Secondary Entity'),
+ * mapStateToProps: state => ({
+ * sharedControls.columnChoices(state.datasource)
+ * .columns.filter(c => c.groupby)
+ * })
+ * validators: [validateNonEmpty],
+ * },
+ * }
+ *
+ * In addition to the basic drop down control, there are several predefined
+ * control types (can be set via the `type` property) that can be used. Some
+ * commonly used examples:
+ * - SelectControl: Dropdown to select single or multiple values,
+ usually columns
+ * - MetricsControl: Dropdown to select metrics, triggering a modal
+ to define Metric details
+ * - AdhocFilterControl: Control to choose filters
+ * - CheckboxControl: A checkbox for choosing true/false values
+ * - SliderControl: A slider with min/max values
+ * - TextControl: Control for text data
+ *
+ * For more control input types, check out the `incubator-superset` repo
+ * and open this file: superset-frontend/src/explore/components/controls/index.js
+ *
+ * To ensure all controls have been filled out correctly, the following
+ * validators are provided
+ * by the `@superset-ui/core/lib/validator`:
+ * - validateNonEmpty: must have at least one value
+ * - validateInteger: must be an integer value
+ * - validateNumber: must be an intger or decimal value
+ */
+
+ // For control input types, see: superset-frontend/src/explore/components/controls/index.js
+ controlPanelSections: [
+ {
+ label: t('Query'),
+ expanded: true,
+ controlSetRows: [
+ ['adhoc_filters'],
+ [
+ {
+ name: 'url',
+ config: {
+ type: 'TextControl',
+ label: t('URL'),
+ mapStateToProps: (
+ state: ControlPanelState,
+ controlState: ControlState,
+ ) => {
+ const originalMapStateToProps =
+ sharedControls?.groupby?.mapStateToProps;
+ const newState =
+ originalMapStateToProps?.(state, controlState) ?? {};
+ newState.externalValidationErrors = controlState.value ? [] : ["Please add a value for URL."]
+ return newState;
+ },
+ renderTrigger: true,
+ default: '',
+ description: t('The Base URL for the Iframe.'),
+ },
+ },
+ ],
+ [
+ {
+ name: 'groupby',
+ override: {
+ label: t('Parameter Column Name'),
+ description: "The name of the column that will populate the url parameter value.",
+ multi: false,
+ allowAll: false,
+ default: [],
+ includeTime: false,
+ mapStateToProps: (
+ state: ControlPanelState,
+ controlState: ControlState,
+ ) => {
+ const originalMapStateToProps =
+ sharedControls?.groupby?.mapStateToProps;
+ const newState =
+ originalMapStateToProps?.(state, controlState) ?? {};
+ newState.externalValidationErrors = ensureIsArray(controlState.value).length > 0 ? [] : ["Please add a value for Parameter Column Name."]
+ return newState;
+ },
+ },
+ },
+ ],
+ [
+ {
+ name: 'parameter_name',
+ config: {
+ type: 'TextControl',
+ label: t('Parameter Name'),
+ mapStateToProps: (
+ state: ControlPanelState,
+ controlState: ControlState,
+ ) => {
+ const originalMapStateToProps =
+ sharedControls?.groupby?.mapStateToProps;
+ const newState =
+ originalMapStateToProps?.(state, controlState) ?? {};
+ newState.externalValidationErrors = controlState.value ? [] : ["Please add a value for Parameter Name."]
+ return newState;
+ },
+ default: '',
+ description: t('The name for the URL parameter.'),
+ },
+ },
+ ],
+ [
+ {
+ name: 'parameter_prefix',
+ config: {
+ type: 'TextControl',
+ label: t('Parameter Prefix'),
+ default: '',
+ description: t('A value that will be prefix the parameter value.'),
+ },
+ },
+ ]
+ ],
+ },
+ ],
+
+ controlOverrides: {
+ series: {
+ validators: [validateNonEmpty],
+ clearable: false,
+ },
+ row_limit: {
+ default: 1,
+ },
+ },
+};
+
+export default config;
diff --git a/superset-frontend/src/cccs-viz/plugins/plugin-chart-iframe/src/plugin/index.ts b/superset-frontend/src/cccs-viz/plugins/plugin-chart-iframe/src/plugin/index.ts
new file mode 100644
index 0000000000000..0efe549552fcb
--- /dev/null
+++ b/superset-frontend/src/cccs-viz/plugins/plugin-chart-iframe/src/plugin/index.ts
@@ -0,0 +1,51 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 { t, ChartMetadata, ChartPlugin } from '@superset-ui/core';
+import controlPanel from './controlPanel';
+import transformProps from './transformProps';
+import buildQuery from './buildQuery';
+import thumbnail from '../images/thumbnail.png';
+
+export default class IFrameVisualizationChartPlugin extends ChartPlugin {
+ /**
+ * The constructor is used to pass relevant metadata and callbacks that get
+ * registered in respective registries that are used throughout the library
+ * and application. A more thorough description of each property is given in
+ * the respective imported file.
+ *
+ * It is worth noting that `buildQuery` and is optional, and only needed for
+ * advanced visualizations that require either post processing operations
+ * (pivoting, rolling aggregations, sorting etc) or submitting multiple queries.
+ */
+ constructor() {
+ const metadata = new ChartMetadata({
+ description: 'IFrame Visualization',
+ name: t('IFrame Visualization'),
+ thumbnail,
+ });
+
+ super({
+ buildQuery,
+ controlPanel,
+ loadChart: () => import('../IFrameVisualization'),
+ metadata,
+ transformProps,
+ });
+ }
+}
diff --git a/superset-frontend/src/cccs-viz/plugins/plugin-chart-iframe/src/plugin/transformProps.ts b/superset-frontend/src/cccs-viz/plugins/plugin-chart-iframe/src/plugin/transformProps.ts
new file mode 100644
index 0000000000000..ee67ef9d2aff7
--- /dev/null
+++ b/superset-frontend/src/cccs-viz/plugins/plugin-chart-iframe/src/plugin/transformProps.ts
@@ -0,0 +1,80 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 { ChartProps, TimeseriesDataRecord, } from '@superset-ui/core';
+
+export default function transformProps(chartProps: ChartProps) {
+ /**
+ * This function is called after a successful response has been
+ * received from the chart data endpoint, and is used to transform
+ * the incoming data prior to being sent to the Visualization.
+ *
+ * The transformProps function is also quite useful to return
+ * additional/modified props to your data viz component. The formData
+ * can also be accessed from your IframeDemo.tsx file, but
+ * doing supplying custom props here is often handy for integrating third
+ * party libraries that rely on specific props.
+ *
+ * A description of properties in `chartProps`:
+ * - `height`, `width`: the height/width of the DOM element in which
+ * the chart is located
+ * - `formData`: the chart data request payload that was sent to the
+ * backend.
+ * - `queriesData`: the chart data response payload that was received
+ * from the backend. Some notable properties of `queriesData`:
+ * - `data`: an array with data, each row with an object mapping
+ * the column/alias to its value. Example:
+ * `[{ col1: 'abc', metric1: 10 }, { col1: 'xyz', metric1: 20 }]`
+ * - `rowcount`: the number of rows in `data`
+ * - `query`: the query that was issued.
+ *
+ * Please note: the transformProps function gets cached when the
+ * application loads. When making changes to the `transformProps`
+ * function during development with hot reloading, changes won't
+ * be seen until restarting the development server.
+ */
+ const formData = chartProps.formData;
+ const queriesData = chartProps.queriesData;
+
+ const { url, parameterName, parameterPrefix, groupby } = formData
+
+ const data = queriesData[0]?.data as TimeseriesDataRecord[];
+
+ let value: string | number | true | Date = ""
+ let errorMessage = "";
+
+ if(Array.isArray(data) && data.length > 1) {
+ errorMessage = "The query returned too many rows when only one was expected."
+ }
+
+ if(Array.isArray(data) && data.length === 0) {
+ errorMessage = "The query returned no rows."
+ }
+
+ if(Array.isArray(data) && data.length === 1) {
+ value = data[0][groupby] || ""
+ }
+
+ return {
+ url_parameter_value: value,
+ parameter_name: parameterName,
+ url,
+ parameter_prefix: parameterPrefix,
+ errorMessage,
+ };
+}
diff --git a/superset-frontend/src/cccs-viz/plugins/plugin-chart-iframe/src/styles.js b/superset-frontend/src/cccs-viz/plugins/plugin-chart-iframe/src/styles.js
new file mode 100644
index 0000000000000..d7bb66e9bb356
--- /dev/null
+++ b/superset-frontend/src/cccs-viz/plugins/plugin-chart-iframe/src/styles.js
@@ -0,0 +1,22 @@
+const InlineBlock = {
+ display: 'inline-block',
+};
+
+const InlineImg = {
+ display: 'inline-block',
+ transform: 'translateY(-10%)',
+ '-ms-transform': 'translateY(-10%)',
+};
+
+const InlineText = {
+ display: 'inline-block',
+ 'text-align': 'center',
+};
+
+const styles = {
+ InlineBlock,
+ InlineImg,
+ InlineText,
+};
+
+export default styles;
diff --git a/superset-frontend/src/cccs-viz/plugins/plugin-chart-iframe/src/types.ts b/superset-frontend/src/cccs-viz/plugins/plugin-chart-iframe/src/types.ts
new file mode 100644
index 0000000000000..bd24375ee377c
--- /dev/null
+++ b/superset-frontend/src/cccs-viz/plugins/plugin-chart-iframe/src/types.ts
@@ -0,0 +1,9 @@
+import { QueryFormData } from '@superset-ui/core';
+
+export type IFrameVisualizationProps = QueryFormData & {
+ url_parameter_value: string;
+ parameter_name: string;
+ url: string;
+ parameter_prefix: string;
+ errorMessage: string;
+};
diff --git a/superset-frontend/src/visualizations/presets/MainPreset.js b/superset-frontend/src/visualizations/presets/MainPreset.js
index 709c32aeff8ca..0c64a7c57ff2e 100644
--- a/superset-frontend/src/visualizations/presets/MainPreset.js
+++ b/superset-frontend/src/visualizations/presets/MainPreset.js
@@ -91,6 +91,7 @@ import {
AtAGlanceUserIdChartPlugin,
AtAGlanceUserIDSasChartPlugin,
ApplicationLinksChartPlugin,
+ IFrameVisualizationChartPlugin,
} from 'src/cccs-viz/plugins/';
import FilterBoxChartPlugin from '../FilterBox/FilterBoxChartPlugin';
import TimeTableChartPlugin from '../TimeTable';
@@ -118,6 +119,7 @@ export default class MainPreset extends Preset {
}),
new AtAGlanceChartIpPlugin().configure({ key: 'at_a_glance_ip' }),
new AtAGlanceChartDnsPlugin().configure({ key: 'at_a_glance_dns' }),
+ new IFrameVisualizationChartPlugin().configure({ key: 'i_frame' }),
new GwwkChartsChartPlugin().configure({ key: 'gwwk_charts' }),
new GwwkDatasetsChartPlugin().configure({ key: 'gwwk_datasets' }),
new GwwkDashboardsChartPlugin().configure({ key: 'gwwk_dashboards' }),